Priyanshu
Priyanshu

Reputation: 13

HttpPost method in controller not coordinating with HttpGet method

I tried to insert a breakpoint before each action and I was stuck at a point when ClassId value in HttpGet method takes the actual(correct)Id of the class which needs to be deleted but ClassId value in HttpPost method does not match with the ClassId value of the HttpGet method, infact value of ClassId in HttpPost returns null due to which I run into an exception error that object has null value. It would be really great if any one can acknowledge me that how that error can be removed. Thanks. Below is the code for the controller and the corresponding view respectively.

Controller Code

 [HttpGet]
    public IActionResult Delete(int ClassId)
    {
        return View(db.Class.Include(x => x.Student).First(c => c.ClassId == ClassId));
    }


   [ActionName("Delete")]
    [HttpPost]
    public IActionResult DeletePost(int ClassId)
    {
        var r = db.Class.First(a => a.ClassId == ClassId);
        var student = r.StudentId.ToString();
        db.Remove(r);
        db.SaveChanges();
        return RedirectToAction("Details", "Student", new { id = student });
    }

View Code

 @model DemoProject.Models.Class

 @{
   ViewData["Title"] = "Delete Class";
  }

   <h3>Are you sure you want to delete this?</h3>
                <div>
                    <hr />
                    <dl class="dl-horizontal">
                        <dt>
                            @Html.DisplayNameFor(model => model.ClassName)
                        </dt>
                        <dd>
                            @Html.DisplayFor(model => model.ClassName)
                        </dd>
                        <dt>
                            @Html.DisplayNameFor(model => model.Title)
                        </dt>
                        <dd>
                            @Html.DisplayFor(model => model.Title)
                        </dd>
                        <dt>
                            @Html.DisplayNameFor(model => model.Text)
                        </dt>
                        <dd>
                            @Html.DisplayFor(model => model.Text)
                        </dd>

                    </dl>

                    <form asp-action="Delete">
                        <div class="form-actions no-color">
                            <input type="submit" value="Delete" class="btn btn-danger" /> 
                           <div class="row">
                               <a asp-action="Details" asp-controller="Student" asp-route-id="@Model.Student.StudentId">Back</a>
                           </div>
                        </div>
                    </form>
                </div>

Upvotes: 0

Views: 1202

Answers (1)

Corey Smith
Corey Smith

Reputation: 1823

You have two options:

  1. As @stephen.vakil said, add a hidden field for the ClassId property to your view within the <form> element.

View with Hidden Field

@model ModelBinding.Models.Class

@{
    ViewData["Title"] = "Delete Class";
}

<h3>Are you sure you want to delete this?</h3>
<div>
  <hr/>
  <dl class="dl-horizontal">
    <dt>
      @Html.DisplayNameFor(model => model.ClassName)
    </dt>
    <dd>
      @Html.DisplayFor(model => model.ClassName)
    </dd>
    <dt>
      @Html.DisplayNameFor(model => model.Title)
    </dt>
    <dd>
      @Html.DisplayFor(model => model.Title)
    </dd>
    <dt>
      @Html.DisplayNameFor(model => model.Text)
    </dt>
    <dd>
      @Html.DisplayFor(model => model.Text)
    </dd>

  </dl>

  <form asp-action="Delete">
    <div class="form-actions no-color">
      @Html.HiddenFor(model => model.ClassId)
      <input type="submit" value="Delete" class="btn btn-danger"/>
      <div class="row">
        <a asp-action="Details" asp-controller="Student" asp-route-id="@Model.Student.StudentId">Back</a>
      </div>
    </div>
  </form>
</div>
  1. Add asp-route-id="@Model.ClassId" to your <form> tag and change the ClassId parameter name of your DeletePost method to id.

View with asp-route-id

@model ModelBinding.Models.Class

@{
    ViewData["Title"] = "Delete Class";
}

<h3>Are you sure you want to delete this?</h3>
<div>
  <hr/>
  <dl class="dl-horizontal">
    <dt>
      @Html.DisplayNameFor(model => model.ClassName)
    </dt>
    <dd>
      @Html.DisplayFor(model => model.ClassName)
    </dd>
    <dt>
      @Html.DisplayNameFor(model => model.Title)
    </dt>
    <dd>
      @Html.DisplayFor(model => model.Title)
    </dd>
    <dt>
      @Html.DisplayNameFor(model => model.Text)
    </dt>
    <dd>
      @Html.DisplayFor(model => model.Text)
    </dd>

  </dl>

  <form asp-action="Delete" asp-route-id="@Model.ClassId">
    <div class="form-actions no-color">
      <input type="submit" value="Delete" class="btn btn-danger"/>
      <div class="row">
        <a asp-action="Details" asp-controller="Student" asp-route-id="@Model.Student.StudentId">Back</a>
      </div>
    </div>
  </form>
</div>

Controller with Renamed Action Parameter

[HttpGet]
public IActionResult Delete(int classId)
{
    return View(db.Class.Include(x => x.Student).First(c => c.ClassId == classId));
}

[ActionName("Delete")]
[HttpPost]
public IActionResult DeletePost(int id)
{
    var r = db.Class.First(a => a.ClassId == id);
    var student = r.StudentId.ToString();
    db.Remove(r);
    db.SaveChanges();
    return RedirectToAction("Details", "Student", new { id = student });
}

Unless you just can't use <hidden> fields for some reason, option 1 is the superior choice.

Upvotes: 3

Related Questions