c# - 在 ASP.NET MVC 3 中使用 View 模型

标签 c# asp.net-mvc-3 viewmodel automapper

我对查看模型还比较陌生,在使用它们时遇到了一些问题。在这种情况下,我想知道最佳做法是什么......

我将 View 所需的所有信息放入 View 模型中。这是一个示例 - 请原谅任何错误,这是我脑海中的代码。

public ActionResult Edit(int id)
{
    var project = ProjectService.GetProject(id);

    if (project == null)
        // Something about not found, possibly a redirect to 404.

    var model = new ProjectEdit();
    model.MapFrom(project); // Extension method using AutoMapper.

    return View(model);
}

如果屏幕只允许编辑一个或两个字段,当 View 模型返回时它会丢失相当多的数据(这是应该的)。

[HttpPost]
public ActionResult Edit(int id, ProjectEdit model)
{
    var project = ProjectService.GetProject(id);

    if (project == null)
        // Something about not found, possibly a redirect to 404.

    try
    {
        if (!ModelState.IsValid)
            return View(model) // Won't work, view model is incomplete.

        model.MapTo(project); // Extension method using AutoMapper.
        ProjectService.UpdateProject(project);
        // Add a message for the user to temp data.

        return RedirectToAction("details", new { project.Id });
    }
    catch (Exception exception)
    {
        // Add a message for the user to temp data.

        return View(model) // Won't work, view model is incomplete.
    }
}

我的临时解决方案是从头开始重新创建 View 模型,从域模型中重新填充它,将表单数据重新应用到它,然后照常进行。但这使得 View 模型参数有些毫无意义。

[HttpPost]
public ActionResult Edit(int id, ProjectEdit model)
{
    var project = ProjectService.GetProject(id);

    if (project == null)
        // Something about not found, possibly a redirect to 404.

    // Recreate the view model from scratch.
    model = new ProjectEdit();
    model.MapFrom(project); // Extension method using AutoMapper.

    try
    {
        TryUpdateModel(model); // Reapply the form data.

        if (!ModelState.IsValid)
            return View(model) // View model is complete this time.

        model.MapTo(project); // Extension method using AutoMapper.
        ProjectService.UpdateProject(project);
        // Add a message for the user to temp data.

        return RedirectToAction("details", new { project.Id });
    }
    catch (Exception exception)
    {
        // Add a message for the user to temp data.

        return View(model) // View model is complete this time.
    }
}

有没有更优雅的方式?

编辑

两个答案都是正确的,所以如果可以的话,我会奖励他们两个。 MJ 点了点头,但经过反复试验后,我发现他的解决方案是最精益的。

Jimmy,我仍然可以使用助手。如果我把我需要显示的内容添加到 View 包(或 View 数据)中,像这样...

ViewBag.Project= project;

然后我可以执行以下操作...

@Html.LabelFor(model => ((Project)ViewData["Project"]).Name)
@Html.DisplayFor(model => ((Project)ViewData["Project"]).Name)

有点 hack,在某些情况下它需要用 System.ComponentModel.DisplayNameAttribute 修饰域模型,但我已经这样做了。

我很想调用...

@Html.LabelFor(model => ViewBag.Project.Name)

但是动态会导致表达式出现问题。

最佳答案

经过反复试验(又名编写代码,然后讨厌它)学习后,我目前首选的方法是:

使用 View 模型来绑定(bind)输入字段。所以在你的情况下,如果你的 View 只编辑两个字段,那么你的 View 模型将只有两个属性。对于填充 View 所需的数据(下拉列表、标签等),我使用动态 ViewBag。

我认为显示 View (即填充 View 需要显示的任何内容)和捕获发布的表单值(绑定(bind)、验证等)是两个独立的问题。而且我发现将填充 View 所需的数据与从 View 回发的数据混合在一起会变得困惑,并且经常会准确地创建您的情况。我不喜欢传递部分填充的对象。

不过,我不确定这对 Automapper(用于将域对象映射到动态 ViewBag)如何发挥作用,因为我还没有使用过它。我相信它有一个可能有效的 DynamicMap 方法?将发布的强类型 ViewModel 自动映射到域对象上应该没有任何问题。

关于c# - 在 ASP.NET MVC 3 中使用 View 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5306655/

相关文章:

c# - new Thread(void Target()) 和 new Thread(new ThreadStart(void Target())) 有什么区别?

asp.net-mvc-3 - 测试 RazorViewEngine View 的输出

asp.net-mvc - 将大型实体列表映射到 ViewModel 的 PagedList

jquery - ASP.NET MVC 3 - ViewModel 和刷新 - 问题

c# - MVC3 ValidationAttribute validationContext.memberName 为空

android - 如何生成具有临时 subview 的组合 View 模型?

c# - 尝试模拟 Entity Framework 上下文时抛出 TargetInitationException

c# - 显示椭圆的半径 - WPF

c# - 如何使用 LINQ 删除符合特定条件的列表子集?

ASP.Net MVC3 Razor Href 错误