There are two methods for editing

The first transmits the values ​​for editing, and the second edits

public ActionResult EditMagazine(int id) { var editMagazineModel = new EditMagazineViewModel() { Magazine = magazineService.EditMagazine(id) }; return View(editMagazineModel); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult EditMagazine1(EditMagazineViewModel magazine) { var magazineModel = new Magazine { MagazineId = magazine.Magazine.MagazineId, Name = magazine.Magazine.Name, Number = magazine.Magazine.Number, YearOfPublishing = magazine.Magazine.YearOfPublishing }; magazineService.EditMagazine1(magazineModel); return RedirectToAction("Magazine"); } 

due to the fact that I'm doing the ViewModel, I had to deal with the mapping,

So the problem is that in the second method there is an exception because of this.

 var magazineModel = new Magazine { 

I create a new object

Who will tell you how to correctly transfer the values ​​from the first method to the second method

 [NullReferenceException: Object reference not set to an instance of an object.] 

Here is the ViewModel

 public class EditMagazineViewModel { public Magazine Magazine { get; set; } } 

but Model

 public class Magazine { public int MagazineId { get; set; } public string Name { get; set; } public int Number { get; set; } public int YearOfPublishing { get; set; } } 

Here is View EditMagazine

 @model Library.ViewModel.MagazineViewModel.EditMagazineViewModel @{ Layout = "~/Views/Home/Layout.cshtml"; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <link rel="stylesheet" href="~/Content/style-form.css" type="text/css"> <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Oswald:400,300" type="text/css"> </head> <body> @using (Html.BeginForm("EditMagazine1", "Magazine")) { @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>Magazine</h4> <hr /> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) @Html.HiddenFor(model => model.Magazine.MagazineId) <div class="form-group"> @Html.LabelFor(model => model.Magazine.Name, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Magazine.Name, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Magazine.Name, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Magazine.Number, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Magazine.Number, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Magazine.Number, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Magazine.YearOfPublishing, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Magazine.YearOfPublishing, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Magazine.YearOfPublishing, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Save" class="btn btn-default" /> </div> </div> </div> } 

  • one
    Show class code Magazine - Bulson
  • one
    exception text? - tym32167
  • one
    You put a break point at the beginning of the method and check whether your EditMagazineViewModel magazine - Bulson does not come empty.
  • @AK I made a mistake and showed the wrong ViewModel, I already fixed it - Simon
  • @Bulson I checked through Debug to me comes empty, that is the question how to transfer the log from the first method to the second - Simon

1 answer 1

Your model is based on simple int and string types:

 public class Magazine { public int MagazineId { get; set; } public string Name { get; set; } public int Number { get; set; } public int YearOfPublishing { get; set; } } 

In this case, you could go along the path of using the model as a ViewModel - but since you went along the path of leaving the model - you did not need to refer to the domain logic in the view model:

 public class EditMagazineViewModel { public Magazine Magazine { get; set; } } 

Make a class on simple types:

 public class EditMagazineViewModel { public int MagazineId { get; set; } public string Name { get; set; } public int Number { get; set; } public int YearOfPublishing { get; set; } } 

(Do you feel that you want to sign up for supporters of using models as view models? The code is copy-pasted)

Let's now redo our first action:

 public ActionResult Edit(int id) { var magazine = magazineService.GetById(id); var model = new EditMagazineViewModel(magazine); return View(model); } 

and second:

 [HttpPost] [ValidateAntiForgeryToken] public ActionResult Edit(EditMagazineViewModel model) { if (!this.ModelState.IsValid) return this.View(model); var magazine = model.ToEntity(); magazineService.Update(magazine); return RedirectToAction("Magazine"); } 

(Please note: we are transferring the domain model to the service, the service belongs to the business logic layer and may not know anything about dozens of applications (web, mobile) each has its own view model)

Only for this we need to rewrite the model class as follows:

 public class EditMagazineViewModel { public EditMagazineViewModel() { } public EditMagazineViewModel(Magazine magazine) { this.MagazineId = magazine.MagazineId; this.Name = magazine.Name; this.Number = magazine.Number; this.YearOfPublishing = magazine.YearOfPublishing; } public Magazine ToEntity() { return new Magazine { MagazineId = this.MagazineId, Name = this.Name, Number = this.Number, YearOfPublishing = this.YearOfPublishing, }; } public int MagazineId { get; set; } public string Name { get; set; } public int Number { get; set; } public int YearOfPublishing { get; set; } } 

The first constructor is needed for asp.net, the second for us (so that the controller method does not swell), and ToEntity converts the ViewModel back into Model.

It will take - you can then drag the mappers instead of these methods.

It remains to rewrite the view:

 @model Library.ViewModel.MagazineViewModel.EditMagazineViewModel @{ Viewbag.Title = "Edit magazine"; } <h2>@Viewbag.Title</h2> @using (Html.BeginForm("EditMagazine", "Magazine", FormMethod.Post)) { @Html.AntiForgeryToken() <div class="form-horizontal"> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) @Html.HiddenFor(model => model.MagazineId) <div class="form-group"> @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Number, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Number, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Number, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.YearOfPublishing, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.YearOfPublishing, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.YearOfPublishing, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Save" class="btn btn-default" /> </div> </div> </div> } 

It works for me in the test application (of course, a little other namespaces), no problems:

enter image description here

  • thanks, it works - Simon
  • in his example, he changed the name of magazine to model and the problem was solved too - Simon
  • @Simon Curious, but incomprehensible: it should not have affected. - AK