使用MVC / Entity Framework,如何在视图中管理内务处理任务?

时间:2014-04-25 13:30:56

标签: asp.net-mvc asp.net-mvc-3 entity-framework asp.net-mvc-4 entity-framework-5

我的理解是,一次只能将一个模型传递给视图。我看到的问题是,我被迫传递实体框架模型,而不是任何将在视图中管理内务管理的模型。这就是我的意思:

您需要创建一个允许某人将Cars提交到数据库的页面。除了表单字段(例如CarName,CarMake,CarYear),您还需要在页面底部有一个名为"记住值和#34;的复选框。在检查时将记得"记住"当用户单击底部的“提交”按钮时,表单值,因此当他们返回所有表单数据时仍然在表单字段中。不用说,这个Remember Values变量不是Entity Framework模型的一部分 - 它只是一个在视图中使用的内务变量。

你们如何处理添加此复选框?感觉它应该是模型的一部分,但我无法向视图发送两个模型。我只是看着这个问题错了吗?你会推荐什么?

.NET 4.5 / MVC 5 / EntityFramework 6

4 个答案:

答案 0 :(得分:1)

从技术上讲,如果模型实际上类似于Tuple可以向视图发送两个模型:

@model Tuple<SomeEFModel, SomeViewModel>

虽然那有点难看。如果你正在创建一个视图模型,你也可以将它作为Entity Framework模型的组合。类似的东西:

public class SomeViewModel
{
    public SomeEFModel EFModel { get; set; }
    public string SomeOtherProperty { get; set; }
    // other stuff...
}

然后在控制器中构建一个实例并将其发送到模型:

@model SomeViewModel

您甚至可以完全解耦EF模型和视图模型,创建一个自定义视图模型,该模型包含该视图的所有内容,然后在控制器级别转换为/和EF模型。最终,它归结为哪种实现看起来更干净,更易于维护,这可能因环境而异。

编辑另一种选择,如果模型对您所依赖的框架的任何位置都不熟悉,可能会将您的传出分开模型。要将数据推送到视图,可以使用上面的复合视图模型。但是当数据从视图中返回时,只需使用正常的实体框架模型以及其他附加字段的附加参数:

public ActionResult Edit(int id)
{
    // build the view model with the EF model as a property
    return View(someViewModel);
}

[HttpPost]
public ActionResult Edit(SomeEFModel model, string someOtherProperty)
{
    // here you have an EF model from the view like normal
    // plus the additional property (however many you need)
    // you can even create a separate view model to collect the other properties
    // as long as the names are well defined, the model binder should build both
}

答案 1 :(得分:1)

我总是创建一个额外的模型,我可以在EF模型之间进行转换。 这个附加模型被传递给View并保存了必要的属性,如CarName,Carmake,CarYear,Remember,可能最重要的是,该特定对象的Id。

因此,当用户提交时,此模型将传递给Post方法,您可以在其中提取所有必需的属性。您使用DbContext中的Id获取数据库模型,并使用刚刚传递的值更新属性。

答案 2 :(得分:1)

这是使用ViewModels的好方法。

使用您要在视图中发送/检索的所有属性构建ViewModel。例如:

EF实体

public class Car {
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
    public virtual string Make { get; set; }
    public virtual string Year { get; set; }
}

查看模型

public class AddCarViewModel {
    public Car Car { get; set; }
    public bool RememberValues { get; set; }
}

<强>控制器

public class CarController : Controller {
    // Constructor....

    public ActionResult Add() {
        var vm = new AddCarViewModel();

        return View(vm);
    }

    [HttpPost]
    public ActionResult Add(AddCarViewModel vm) {
        if (ModelState.IsValid) {
            _carService.Save(vm.Car);
        }

        return View(vm);
    }
}

另一个好方法是创建域转移对象,它是POCO类,用于保存通过管道传输的数据。例如,在您的业务层中,您可能希望审核对Car模型的任何更改。因此,您可能拥有CreatedBy,CreatedDate,UpdatedBy,UpdatedDate等属性(这些属性通常不会显示给最终用户,但对于存储非常重要)。

所以你要创建以下类:

public class Car {
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
    public virtual string Make { get; set; }
    public virtual string Year { get; set; }
    public virtual User CreatedBy { get; set; }  
    public virtual User UpdatedBy { get; set; }  
    public virtual DateTime CreatedDate { get; set; }  
    public virtual DateTime UpdatedDate { get; set; }  
}

public class CarDTO {
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Make { get; set; }
    public string Year { get; set; }
}

您可以使用AutoMapper等库来映射Car的属性 - &gt; CarDTO:

var car = _carService.GetCarById(id);

var carDTO = Mapper.Map<Car, CarDTO>(car);

这样,您可以使用DTO选择要向您的视图公开的属性。

答案 3 :(得分:1)

首先,您绝对不应该将EF模型直接传递给您的视图,并且您当然不应该直接发布到您的EF模型。这主要是采用不受信任的,未经过计算的输入,并直接将其写入您的数据模型,只需极少的验证。

虽然这可能适用于没有安全性或其他后果的简单模型,但想象一下您允许用户编辑其个人资料信息的情况。此外,想象一下,在他的个人资料中,您还存储了与其订阅信息相关的信息。特制的提交可能会改变他的订阅信息并让他自由访问您的网站,或者更糟糕......

相反,您使用视图模型。除了安全方面,视图模型也很好,因为除了非常简单的CRUD样式站点之外,您的视图要求通常与数据模型要求不同。例如,某个特定字段可能在您的数据模型中可以为空,但您可能希望在视图中使其成为必需字段。如果您直接通过模型,那么就不能轻易做到。

最后,聚合视图模型聚合了许多不同的子模型,以便为视图提供整体模型,这就是您所获得的。然后,您将使用服务层,存储库或业务逻辑层将视图模型转换为数据模型,按摩数据或根据需要应用逻辑。