Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the ID parameter passed twice in the Edit() action method (POST) scaffold added by ASP.NET Core MVC?

I'm working with ASP.NET Core MVC 5.0 in Visual Studio 2019. I had the scaffolder generate a controller with CRUD operations using Entity Framework Core. I see that there are two Edit() methods, the GET version of the method looks up the entity in the database and passes it to the Edit view. So far, everything makes sense. What I'm a bit confused about is the POST version of the Edit() method. This is what its signature and first statement look like:

 [HttpPost]
 [ValidateAntiForgeryToken]
 public async Task<IActionResult> Edit(int id, [Bind("Id,Name")] Department department)
 {
      if (id != department.Id)
      {
                return NotFound(); 
      }
      // ... (Removed for brevity)
}

If the ID can be bound to the Department entity using model binding, why does it require the first int id as parameter? I have tried removing it along with the equality check and the edit still works. I have also noticed a hidden input type in my Edit view:

 <input type="hidden" asp-for="Id" />

which I tried removing as well after removing the id parameter. The Edit() somehow still works. I would like to know the purpose of the ID parameter, the equality check id == department.Id in the Edit() method and the hidden input field in the Edit view. I actually wanted to use a viewmodel instead of using my entity directly with BindAttribute but ran into this confusion.

My entity is called Department and it looks like this:

public class Department
{
        public int Id { get; set; }

        [Required(AllowEmptyStrings = false, ErrorMessage = "{0} is required")]
        [StringLength(maximumLength: 100, MinimumLength = 1, ErrorMessage = "{0} should be between {2} and {1} characters")]
        public string Name { get; set; }

        public List<Course> Courses { get; set; }
}

For more context, here's what the GET version of Edit() looks like:

public async Task<IActionResult> Edit(int? id)
{
            if (id == null)
            {
                return NotFound();
            }

            var department = await _context.Departments.FindAsync(id);
            if (department == null)
            {
                return NotFound();
            }
            return View(department);
}
like image 947
Amal K Avatar asked Nov 19 '25 04:11

Amal K


1 Answers

Firstly,the hidden input in Edit View is to bind department.Id in Post Edit method. Because your department have Id property,so when you delete <input type="hidden" asp-for="Id" />,the Id in url will still bind to department.Id and int Id.If department.Id not exists,db will create a new one.Here is a demo:

Teacher:

public class Teacher
    {
        public int TeacherId { get; set; }
        public string TeacherName { get; set; }
        public int TeacherAge { get; set; }


    }

Edit:

<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="TeacherName" class="control-label"></label>
                <input asp-for="TeacherName" class="form-control" />
                <span asp-validation-for="TeacherName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="TeacherAge" class="control-label"></label>
                <input asp-for="TeacherAge" class="form-control" />
                <span asp-validation-for="TeacherAge" 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="Index">Back to List</a>
</div>

Edit method:

[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("TeacherId,TeacherName,TeacherAge")] Teacher teacher)
        {
            

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(teacher);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!TeacherExists(teacher.TeacherId))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return RedirectToAction(nameof(Index));
            }
            return View(teacher);
        }

result: enter image description here

Sometimes not each model have a property named Id as primary key,so the hidden input is necessary.

And the id is used to make sure the edited data Id is right.For example,if some people custom the page,and make the Id modifiable.Or some one change the value of hidden input.

Here is two demos: enter image description here enter image description here

like image 175
Yiyi You Avatar answered Nov 21 '25 17:11

Yiyi You