Search code examples
c#asp.net-corecrudn-tier-architecture

When editing a item in my CRUD screen, my Id sets automatically to 0


I am working on the CRUD functions in my ASP.NET Core application. I have this problem where when I try to edit a character (character is Karakter in Dutch) the ID of the character that I provide is always reset to 0. This is a problem because I now always edit the character with Id = 0 and I can't edit characters with an other id.

My view:

@model IEnumerable<Apex.Models.KarakterViewModel>

@{
    ViewData["Title"] = "Karakter";
}

<h1>Karakter</h1>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.KarakterId)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.KarakterSoort)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.KarakterNaam)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.KarakterId)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.KarakterSoort)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.KarakterNaam)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new {KarakterId = item.KarakterId}) |
                @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
                @Html.ActionLink("Delete", "Home", new { /* id=item.PrimaryKey */ })
            </td>
        </tr>
}
    </tbody>
</table>

My edit view:

@model Apex.Models.KarakterViewModel

@{
    ViewData["Title"] = "Edit";
}

<h1>Edit</h1>

<h4>KarakterViewModel</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Edit">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="KarakterId" class="control-label"></label>
                <input asp-for="KarakterId" class="form-control" />
                <span asp-validation-for="KarakterId" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="KarakterSoort" class="control-label"></label>
                <input asp-for="KarakterSoort" class="form-control" />
                <span asp-validation-for="KarakterSoort" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="KarakterNaam" class="control-label"></label>
                <input asp-for="KarakterNaam" class="form-control" />
                <span asp-validation-for="KarakterNaam" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Karakter">Back to List</a>
</div>

My controller:

public class KarakterController : Controller
{
    private readonly IKarakterLogic _karakterLogic;

    public KarakterController()
    {
        // Waarom moet  apexfactory ervoor?
        _karakterLogic = ApexFactory.ApexFactory.GetKarakterLogic();
    }

    public ActionResult Index()
    {
        return Karakter();
    }

    // GET: Karakter
    public ActionResult Karakter()
    {
        var allKarakters = _karakterLogic.GetAllKarakters();
        var karakters = new List<KarakterViewModel>();

        foreach (var karakter in allKarakters)
        {
            karakters.Add(new KarakterViewModel
            {
                KarakterId = karakter.KarakterId,
                KarakterNaam = karakter.KarakterNaam,
                KarakterSoort = karakter.KarakterSoort
            });
        }

        return View(karakters);
    }

    public ActionResult Delete(int KarakterId)
    {
        _karakterLogic.DeleteKarakter(KarakterId);
        return RedirectToAction("Karakter");
    }

    [HttpGet]
    public ActionResult Create()
    {
        var karakterViewModel = new KarakterViewModel();
        return View(karakterViewModel);
    }

    [HttpPost]
    public ActionResult Create(KarakterViewModel karakter)
    {
        _karakterLogic.CreateKarakter(karakter);
        return RedirectToAction("Karakter");
    }

    [HttpGet]
    public ActionResult Edit()
    {
        KarakterViewModel karakterViewModel = new KarakterViewModel();
        _karakterLogic.GetById(karakterViewModel);
        return View(karakterViewModel);
    }

    [HttpPost]
    public ActionResult Edit(KarakterViewModel karakterViewModel)
    {
        _karakterLogic.UpdateKarakter(karakterViewModel);
        return RedirectToAction("Karakter");
    }

    public ActionResult AllKarakters()
    {
        return Karakter();
    }
}

My logic layer:

public class KarakterLogic : IKarakterLogic
{
        private IKarakterContext karakterContext { get;}

        public KarakterLogic(IKarakterContext context)
        {
            karakterContext = context;
        }

        public void CreateKarakter(IKarakter _karakter)
        {
            var karakter = new KarakterModel
            {
                KarakterNaam = _karakter.KarakterNaam,
                KarakterSoort = _karakter.KarakterSoort
            };

            karakterContext.CreateKarakter(karakter);
        }

        public IEnumerable<IKarakter> GetAllKarakters()
        {
            return karakterContext.GetKarakters();
        }

        public IKarakter UpdateKarakter(IKarakter karakter)
        {
            karakterContext.UpdateKarakter(karakter);
            return karakter;
        }

        public void DeleteKarakter(int KarakterId)
        {
            karakterContext.DeleteKarakter(KarakterId);
        }

        public IKarakter GetById(IKarakter karkter)
        {
            return karakterContext.GetById(karkter);
        }    
}

I think my logic and DAL are working fine, because it does edit the character with id 0 in the right way. The problem is that I don't only want to edit the character with id = 0.

How do I get it that I edit the character with the requested ID (and not the character with id 0.)?

Note: When I click the desired character (in this case the second character) my HTTP link is this:

Httplink

So there it does recognize that the Id of the character I want to edit is 2. Can anyone help me?


Solution

  • Your code

    @Html.ActionLink("Edit", "Edit", new {Id= item.KarakterId})
    

    KarakterId is passed as a parameter to the Edit method, so you should receive it in the Edit method, like this:

    [HttpGet]      
    public ActionResult Edit(int Id)
    {
     //Get the corresponding ViewModel according to this Id, and then return to the view.
     var allKarakters = _karakterLogic.GetAllKarakters();
        var karakters = new List<KarakterViewModel>();
        foreach (var karakter in allKarakters)
        {
            karakters.Add(new KarakterViewModel
            {
                KarakterId = karakter.KarakterId,
                KarakterNaam = karakter.KarakterNaam,
                KarakterSoort = karakter.KarakterSoort
            });
        }
      var viewmodel=karakters.Where(c=>c.KarakterId==Id).FirstOrDefault();
      return View(viewmodel);
    }
    

    This is just an example, you can write a method to get model based on Id in your logic and then use it.