ASP.NET MVC - 从视图中部分更新模型

UpT*_*eek 15 model-view-controller asp.net-mvc

我只是想知道人们是如何接近这种情况的.在我使用ORM的MVC(在这种情况下为NHibernate)中,这似乎是一个弱点......

假设您的模型中有一个细粒度和复杂的实体.您可能会有一个管理页面来管理此类对象.如果实体很复杂,则您不太可能以一种形式修改整个实体.您仍然需要将相关属性传递给视图,并在视图返回时将更改合并到模型中的那些属性.

在这种情况下,有什么人做的?

  • 创建一个视图模型,该视图模型是(或包含)实体属性的子集.将此传递给视图和从视图传递.在控制器中的"编辑"操作方法中,从存储库中获取对象,遍历ViewModel中的所有属性并将它们应用于Model对象(model.a = viewmodel.a,modelb = viewmodel.b).这似乎是明显合理的路线,但产生了许多繁琐的管道代码.这也使验证复杂化了一些.

  • 别的什么?

我简要地看了一下自动播放器 - 但这似乎不符合法案,也许我错了?

谢谢.

Say*_*imi 11

这听起来像是automapper的完美场景.您创建一个包含字段子集或实际模型的视图模型类,并让AutoMapper注意将域模型对象中的值从视图模型对象中提取出来.你对这种方法有什么问题?

考虑这个例子:

这是您的域模型和视图模型

public class Person
{
    public string FirstName
    { get; set; }

    public string LastName
    { get; set; }

    public string HomeNumber
    { get; set; }

    public string Address1
    { get; set; }

    public string Address2
    { get; set; }
}

public class PersonViewModel
{
    public string FirstName
    { get; set; }

    public string LastName
    { get; set; }

    public string HomeNumber
    { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这是您的映射,您必须在dm-> vm和vm-> dm的两个方向上创建映射.

从我在使用Automapper时看到的是,如果你从对象A映射到B而B有一个A没有的属性,它将被重置.因此,当我创建地图时,我指示它忽略那些缺少的属性.我不是Automapper专家所以我可能错了.

制图

Mapper.CreateMap<Person, PersonViewModel>();
// Automapper will reset values in dest which don't exist in source, so be sure to ignore them!
Mapper.CreateMap<PersonViewModel, Person>()
    .ForMember(dest => dest.HomeNumber, opt => opt.Ignore());
Run Code Online (Sandbox Code Playgroud)

最后用法:

Person p = new Person()
{
    FirstName = "First",
    LastName = "Last",
    Address1 = "add 1",
    Address2 = "add 2"
};

PersonViewModel pvm = Mapper.Map<Person, PersonViewModel>(p);
// Map to a new person
Person p2 = Mapper.Map<PersonViewModel, Person>(pvm);

// Map to the existing person just to update it
Person p3 = new Person()
{
    HomeNumber = "numberHere"
};

// This will update p3
Mapper.Map<PersonViewModel, Person>(pvm, p3);
Run Code Online (Sandbox Code Playgroud)

由于排除,这显然不太理想,但比手动完成整个事情要好得多.


小智 5

  1. 让您的视图模型与您的域模型一对一地映射.

  2. 指定Model为以下的参数routeValues.这意味着您的视图模型将使用域模型中的值进行初始化.只有表单中的子字段集将被覆盖在结果中personViewData.

更新视图:

@model ViewModel.PersonView

@using (Html.BeginForm("Update", "Profile", Model, FormMethod.Post))
{
  ...Put your sub set of the PersonView fields here
}
Run Code Online (Sandbox Code Playgroud)

ProfileController可:

public ActionResult Update(string userName)
{
    Person person = _unitOfWork.Person.Get().Where(p => p.UserName == userName).FirstOrDefault();
    PersonView personView = new PersonView();
    Mapper.Map(person, personView);

    return View(personView);
}

[HttpPost]
public ActionResult Update(PersonView personViewData)
{
   Person person = _unitOfWork.Person.Get().Where(p => p.UserName == personViewData.UserName).FirstOrDefault();
   Mapper.Map(personViewData, person);
   _unitOfWork.Person.Update(person);
   _unitOfWork.Save();

   return Json(new { saved = true, status = "" });
}
Run Code Online (Sandbox Code Playgroud)