Asp.net mvc 使用MVC/实体框架,如何在视图中管理内务管理任务?

Asp.net mvc 使用MVC/实体框架,如何在视图中管理内务管理任务?,asp.net-mvc,asp.net-mvc-3,entity-framework,asp.net-mvc-4,entity-framework-5,Asp.net Mvc,Asp.net Mvc 3,Entity Framework,Asp.net Mvc 4,Entity Framework 5,我的理解是,一次只能向视图传递一个模型。我看到的问题是,我被迫传递实体框架模型,而不是任何将在视图中管理内务管理的模型。我的意思是: 您需要创建一个页面,允许某人向数据库提交汽车。除了表单字段(例如CarName、CarMake、CarYear),您还需要在页面底部设置一个名为“记住值”的复选框,选中该复选框后,当用户单击底部的“提交”按钮时,该复选框将“记住”表单值,因此当用户返回表单时,所有表单数据仍在表单字段中。不用说,这个membervalues变量不是实体框架模型的一部分——它只是视图

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

您需要创建一个页面,允许某人向数据库提交汽车。除了表单字段(例如CarName、CarMake、CarYear),您还需要在页面底部设置一个名为“记住值”的复选框,选中该复选框后,当用户单击底部的“提交”按钮时,该复选框将“记住”表单值,因此当用户返回表单时,所有表单数据仍在表单字段中。不用说,这个membervalues变量不是实体框架模型的一部分——它只是视图中使用的内务管理变量

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

.NET 4.5/MVC 5/EntityFramework 6

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

@model Tuple<SomeEFModel, SomeViewModel>
然后,只需在控制器中构建一个实例,并将其发送到模型:

@model SomeViewModel
您甚至可以将EF模型和视图模型完全解耦,创建一个包含该视图所有内容的自定义视图模型,然后在控制器级别转换为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
}
从技术上讲,如果模型实际上类似于
元组,则可以向视图发送两个模型:

@model Tuple<SomeEFModel, SomeViewModel>
然后,只需在控制器中构建一个实例,并将其发送到模型:

@model SomeViewModel
您甚至可以将EF模型和视图模型完全解耦,创建一个包含该视图所有内容的自定义视图模型,然后在控制器级别转换为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
}

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


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

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


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

这是使用ViewModels的好情况

使用希望发送/检索到视图或从视图检索的所有属性构建视图模型。例如:

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类,用于保存通过管道传输的数据。例如,在您的业务层中,您可能希望审核对您的车型所做的任何更改。因此,您可能具有诸如CreatedBy、CreatedDate、UpdatedBy、UpdateDate等属性(这些属性通常不会向最终用户显示,但对存储很重要)

因此,您将创建以下类:

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->CarDTO映射到:

var car = _carService.GetCarById(id);

var carDTO = Mapper.Map<Car, CarDTO>(car);
var car=\u carService.GetCarById(id);
var carDTO=Mapper.Map(汽车);

通过这种方式,您可以通过使用DTO选择要向视图公开的属性。

使用ViewModels是一种很好的情况

使用希望发送/检索到视图或从视图检索的所有属性构建视图模型。例如:

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类,用于保存通过管道传输的数据。例如,在您的业务层中,您可能希望审核对您的车型所做的任何更改。因此,您可能具有诸如CreatedBy、CreatedDate、UpdatedBy、UpdateDate等属性(这些属性通常不会向最终用户显示,但对存储很重要)

因此,您将创建以下类:

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->CarDTO映射到:

var car = _carService.GetCarById(id);

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