如何将ViewModel映射回模型(MVC EF)

时间:2017-08-02 13:08:04

标签: c# asp.net-mvc entity-framework mvvm

有很多解决方案如何将模型映射到mvc asp.net中的viewmodel,如automapper或valueinjecter。但是,我无法弄清楚如何映射回来。一个简单的例子

我有一个像这样的复杂模型

public class Address
{
    public int AddressID { get; set; }

    public string OwnerID { get; set; }
    public virtual ApplicationUser Owner { get; set; }

    public String Name { get; set; }

    public String Street { get; set; }

    public int ZipCode { get; set; }

    public String City { get; set; }

    public string Email { get; set; }

    // fancy business logic stuff like
    public Nullable<Guid> requestCode { get; set; }

    // or even this
    public string BestFriendID { get; set; }
    public virtual ApplicationUser BestFriend{ get; set; }

    public virtual ICollection<OtherModel> Mycollection { get; set; }

    // And some enums
    public MyEnum MyEnum { get; set; }
}

但是在一个场景中,我只想编辑这个地址的名称和电子邮件,所以我继续为它创建一个viewmodel

public class SimpleEmailEditVM
{
      [MyDataAnnotations]
      public String Name { get; set; }

      [MyDataAnnotations] 
      public String Email { get; set; }
}

这样可以创建非常简单的视图,例如

@model project.ViewModels.SimpleEmailEditVM
@Html.EditorFor(model => model, new { htmlAttributes = new { @class = "form-control" } })

我可以在viewmodel中添加例如Street作为字段,不需要更新视图。从模型到视图模型的映射可以用例如模型轻松完成。 valueinjecter,但现在我的问题:我如何映射回来?

在viewmodel中没有Id信息,所以如何找到正确的模型(我可以想象,多个条目具有相同的名称和电子邮件,但完全不同的ID)?控制器怎么样?

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind] SimpleEmailEditVM vm)
    {
        if (ModelState.IsValid)
        {
            /* find the correct address from db and update the
               fields specified in the viewmodel? */
            db.Entry(address).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(address);
    }

我能想到的一个解决方案是添加ID并将其隐藏(like this here)。这是正确的唯一方法吗?这里的问题是,我的身份证已通过,我可以想象将内部身份证传递给用户并不是一个很好的做法。

2 个答案:

答案 0 :(得分:1)

  

我可以想象,将内部ID传递给不是很好的做法   用户。

除非id是敏感数据(如SSN),否则公开id本身并不是问题。此问题的ID在网址中公开。您的用户ID已在您的个人资料中公开。

诀窍是确保当id返回时检查其有效性并检查执行该操作的身份是否允许执行该操作。这可能是角色或权限检查,也可能需要在记录级别进行细化。

这里有一些伪代码证明了这一点。

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind] SimpleEmailEditVM vm)
{
    var itemToEdit = db.Find(vm.Id);

    //Make sure Id is valid
    if(itemToEdit == null) return BadRequest();

    //Make sure user can edit this object
    if(!User.IsInRole("CanEditItems")) return Forbidden();  
    if(itemToEdit.AllowedUser != User.Identity.Name) return Forbidden(); 

    if (ModelState.IsValid)
    {
        /* find the correct address from db and update the
           fields specified in the viewmodel? */
        db.Entry(address).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(address);
}

答案 1 :(得分:0)

您可以使用temproray会话(TempData)将值发送到另一个操作的操作。

请检查enter link description here