C# ViewModel在MVC中是如何工作的

C# ViewModel在MVC中是如何工作的,c#,asp.net-mvc,C#,Asp.net Mvc,我真的不知道如何在MVC中使用ViewModel。假设我有两个简单的域模型: public class Customer { public int Id { get; set; } public string CustomerName { get; set; } } public class Order { public int Id { get; set; } public string ProductName { get; set; } } 现在我的目标

我真的不知道如何在MVC中使用ViewModel。假设我有两个简单的域模型:

public class Customer
{
    public int Id { get; set; }
    public string CustomerName { get; set; }
}

 public class Order
{
    public int Id { get; set; }
    public string ProductName { get; set; }
}
现在我的目标是创建一个ViewModel,它显示(组合)CustomerName和ProductName以显示到视图中。我不知道在ViewModel中包含什么来实现这一点。我是否像这样使用与我的域模型相同的属性名

public class MyViewModel
{
    public string CustomerName { get; set; }
    public string ProductName { get; set; }
}

ViewModel如何知道属性来自两个不同的类?还是我的ViewModel格式不正确

您必须自己在ViewModel中设置它,作为一个模板,它可能看起来像:

public class MyViewModel
{
    public string CustomerName { get; set; }
    public string ProductName { get; set; }

    public void GetCustomerName(int customerId) 
    {
       CustomerName = CustomerServiceLayer.GetCustomerName(customerId);
       // CustomerService Layer (I.e. a repository that contains this info;
    }

    public void GetProductName(int productId) 
    {
       ProductName = ProductServiceLayer.GetProductName(productId); 
       // ProductService Layer (I.e. a repository that contains this info;
    }

}
然后,您将有另外两个服务层(
ProductServiceLayer
CustomerServiceLayer
)与数据库/存储库通信以获取所需信息。然后,该信息返回到视图(通过ViewModel)并显示给用户

或者,您可以将
客户
产品
对象直接传递到ViewModel中(通过构造函数)


这里的缺点是您在视图中公开了整个
客户
产品
类。

您可以这样做,但是您通常在get操作中在render上构建viewmodel,然后将该视图模型的部分发布回来,并在post操作中处理它。一旦从表单返回值,MVC绑定就发挥了神奇的作用

我不会将业务逻辑放在viewmodel中,而是使用管理器/服务在控制器中构建viewmodel

您还可以使viewmodel具有复杂的模型类型,如以下属性

public class MyViewModel
{
    public Customer Customer { get; set; }
    public Product Product { get; set; }
}

ViewModel表示用于转到视图的模型。在控制器中,您将检索数据并将其传递给ViewModel

假设您在视图中有一个复选框,表示对黄金客户的不满:不适合更改域模型以添加此信息,并且使用Viewbag和Viewdata(imho)使代码变脏不是一个好的做法

因此,您可以创建一个包含所有所需信息的模型或模板。就我们而言:

public class MyViewModel
{
    public string CustomerName { get; set; }
    public string ProductName { get; set; }
    public boolean IsGoldCustomer { get; set; }
}

通常,为了将数据从“域模型”传递到“视图模型”,您必须将模型转换为ViewModel,反之亦然。

正如我所看到的,您这里有一个更大的设计问题

假设您只需要在UI上显示
CustomerName
ProductName
。那么,只要将这两个元素添加到ViewModel类中,就可以了,就像您描述的那样

public class MyViewModel
{
    public string CustomerName { get; set; }
    public string ProductName { get; set; }
}
在两个变量中获取数据不是问题:

Customer customer = service.GetCustomer();
Product product = service.GetProduct()
现在您已经拥有了所需的一切,只需设置数据并将其传递给视图即可

MyViewModel viewModel = new MyViewModel();
viewModel.CustomerName = customer.CustomerName;
viewModel.ProductName = product.ProductName;
它始终取决于您需要在UI上显示什么,只发送您需要的内容,而不发送其他内容。
您不需要在应用程序中到处传递一个模型,
Business
DataAccess
UI
。如果您真的需要,您可以定制一些东西。

viewmodel可能不知道您的属性来自何处。视图模型为视图提供数据。它可能只是您在模型对象中已经拥有的数据,但通常您拥有视图特定的数据(可以是排序顺序或其他数据),这些数据也应该是视图模型的一部分,但这些数据不会来自业务实体/模型对象。在这个简单的例子中,视图模型与模型对象非常相似。为了使用强类型视图,我需要组合这两个模型。数据在两个单独的表中。上面的示例是否将业务逻辑放入视图模型?@dc922此示例没有将任何逻辑放入视图模型。当您同时拥有客户和产品时,您将实例化视图模型,并将相关项传递给它。我的项目通常的工作方式是将域/EF/数据模型传输到不同层中的POCO模型,以将其与我的数据层分离。然后我直接在视图模型中使用这些模型。我的视图模型通常表示一个视图,有时在两个类似视图之间共享。因此视图模型将包含与特定视图相关的内容。我喜欢您的第一个示例,但我不确定如何使用代码优先实体框架实现它。我对MVC非常陌生,所以我不知道如何设置服务层。@dc922-服务层只是一个类(它是一个独立的关注点,只需与DBContext对话并从ORM(在您的案例中是实体框架)检索数据)。有道理?
MyViewModel viewModel = new MyViewModel();
viewModel.CustomerName = customer.CustomerName;
viewModel.ProductName = product.ProductName;