Страницы

Поиск по вопросам

вторник, 31 марта 2020 г.

Ошибка биндинга - приходит пустая модель

#c_sharp #aspnet_mvc


Есть два метода для редактирования 

Первый передает значения для редактирования, а второй редактирует

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");
}


из-за того что делаю ViewModel пришлось столкнуться с mapping'ом ,

так вот проблема в том что во втором методе выходит исключение из-за этого 

var magazineModel = new Magazine
 {


я создаю новый обьект 

Кто подскажет как правильно передать значения с первого метода для второго метода 

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


Вот ViewModel 

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


а вот Model 

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


Вот View EditMagazine 

@model Library.ViewModel.MagazineViewModel.EditMagazineViewModel

@{
Layout = "~/Views/Home/Layout.cshtml";
}

 








 @using (Html.BeginForm("EditMagazine1", "Magazine"))

   {

       @Html.AntiForgeryToken()

    

Magazine


@Html.ValidationSummary(true, "", new { @class = "text-danger" }) @Html.HiddenFor(model => model.Magazine.MagazineId)
@Html.LabelFor(model => model.Magazine.Name, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.Magazine.Name, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Magazine.Name, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.Magazine.Number, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.Magazine.Number, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Magazine.Number, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.Magazine.YearOfPublishing, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.Magazine.YearOfPublishing, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Magazine.YearOfPublishing, "", new { @class = "text-danger" })
}


Ответы

Ответ 1



Ваша модель основана на простых типах типа int и string: public class Magazine { public int MagazineId { get; set; } public string Name { get; set; } public int Number { get; set; } public int YearOfPublishing { get; set; } } При этом вы могли пойти по пути использования модели в качестве ViewModel - но раз уж вы пошли по пути ухода от модели - то не надо было во вьюмодели ссылаться на доменную логику: public class EditMagazineViewModel { public Magazine Magazine { get; set; } } Сделайте класс на простых типах: public class EditMagazineViewModel { public int MagazineId { get; set; } public string Name { get; set; } public int Number { get; set; } public int YearOfPublishing { get; set; } } (Чувствуете, что хочется записаться в сторонники использования моделей в качестве вьюмоделей? Код копипастится) Давайте теперь переделаем наш первый action: public ActionResult Edit(int id) { var magazine = magazineService.GetById(id); var model = new EditMagazineViewModel(magazine); return View(model); } и второй: [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"); } (Обратите внимание: в сервис мы передаём уже доменную модель, сервис относится к слою бизнес-логики и может ничего не знать о десятках приложений (веб, мобильных) у каждого свои собственные вьюмодели) Только для этого нам нужно класс модели переписать следующим образом: 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; } } Первый конструктор нужен для asp.net, второй - для нас (чтобы не разбухал метод контроллера), а ToEntity - преобразует обратно ViewModel в Model. Понадобится - можете потом подтащить мапперы вместо этих методов. Остаётся переписать view: @model Library.ViewModel.MagazineViewModel.EditMagazineViewModel @{ Viewbag.Title = "Edit magazine"; }

@Viewbag.Title

@using (Html.BeginForm("EditMagazine", "Magazine", FormMethod.Post)) { @Html.AntiForgeryToken()
@Html.ValidationSummary(true, "", new { @class = "text-danger" }) @Html.HiddenFor(model => model.MagazineId)
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.Number, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.Number, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Number, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.YearOfPublishing, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.YearOfPublishing, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.YearOfPublishing, "", new { @class = "text-danger" })
} У меня в тестовом приложении работает (естественно чуть другие неймспейсы), проблем нет:

Комментариев нет:

Отправить комментарий