Entity Framework如何识别我的视图模型并绑定到我的域模型的属性?

时间:2015-10-07 11:22:21

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

根据我的理解,视图模型仅表示我想在特定视图中显示的数据,并且可以包含来自多个域模型的属性。我也理解视图模型充当我的域模型和视图之间的数据绑定器。

话虽如此,我有以下模型:

public class Image
{
    public int ImageID { get; set; }
    public string ImageCaption { get; set; }
    public int NumOfLikes { get; set; }
    public string ImageFilePath { get; set; }
}

带有以下视图模型的ProfileViewModels类:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace Splend.Models
{
    public class ImageUploadViewModel
    {
    }

    public class EditUserProfileViewModel
    {
    }

    public class ViewUserProfileViewModel
    {
    }

    public class ViewImagesViewModel
    {
    }
}

首先,我假设这是基于ASP.NET身份生成的AccountViewModels创建视图模型的正确方法。其次,我没有从这两个模型中搭建任何物品。所以我还没有任何观点或控制器。


问题

  1. 我的视图模型如何在我的域模型和视图之间绑定数据?
  2. 如何将我的视图模型映射到我的域模型?
  3. 实体框架如何知道我的视图模型属性是从我的域模型引用的,而我不是在创建新的模型属性,即是 我有一个特定的视图模型和属性命名约定 必须用来告诉实体框架ImageUploadViewModel是一个视图模型吗?

1 个答案:

答案 0 :(得分:1)

我不建议采用一刀切的方法来创建和管理视图模型,因为它会很快变得复杂,尤其是当你为它们分配验证时。

您似乎想在创建视图之前预测所需的视图模型?

通常我建议您在视图模型和视图之间建立1:1的关系,并确保您的视图模型包含的字段数量最少,只能保存显示所述视图所需的信息。

我假设您的用户有多个Images和以下视图模型:

public class ProfileViewModel
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public string FullName { get; set; }
    public List<ImageViewModel> UserImages { get; set; }
}

// View model to represent user images
public class ImageViewModel
{
    public int ImageID { get; set; }
    public string ImageCaption { get; set; }
    public int NumOfLikes { get; set; }
    public string ImageFilePath { get; set; }
}
  1. 以下是映射到视图模型的方法。只需创建视图模型类的新实例,为它们赋值并将它们传递给视图:

    [HttpGet]
    public ActionResult EditUser()
    {
        //
        // LOAD INFO ABOUT THE USER (Using a service layer, but you're probably just using Entity Framework)
        //
    
        // Get the user ID?
        var userId = this.User.Identity.GetUserId();
    
        // Get the user domain models from the database?
        var userDomainModel = this.UserService.GetUserInfo(userId);
    
        // Get the user's image domain models from the database?
        var userImagesDomainModelList = this.UserImageService.GetImagesForUser(userId);
    
        //
        // THE VIEW MODEL MAPPING STARTS HERE...
        //
    
        // Create an instance of your view model and assign basic info
        var responseModel = ProfileViewModel()
        {
            public string UserName = userDomainModel.UserName;
            public string Password = userDomainModel.Password;
            public string FullName = userDomainModel.FullName;
        }
    
        // Initialise list for images
        responseModel.UserImages = new List<ImageViewModel>();
    
        // Loop though each image domain model and assign them to the main view model
        foreach (var imageDomainModel in userImagesDomainModelList)
        {
             // Initialise image view model
             var imageViewModel = new ImageViewModel()
             {
                 ImageID = imageDomainModel.ImageID,
                 ImageCaption = imageDomainModel.ImageCaption,
                 NumOfLikes = imageDomainModel.NumOfLikes,
                 ImageFilePath = imageDomainModel.ImageFilePath
             };
    
             // Add the image view model to the main view model
             responseModel.UserImages.Add(imageViewModel);
        }
    
        // Pass the view model back to the view
        return View(responseModel);
    }
    
  2. 只需以相同方式映射已发布到您的域模型的传入值:

    [HttpPost]
    public ActionResult UpdateImage(UpdateImageViewModel requestResponseModel)
    {   
        // Get the user ID?
        var userId = this.User.Identity.GetUserId();
    
        // Map incoming view model values to domain model
        var imageDomainModel = new Image()
        {
            ImageID = requestResponseModel.ImageId,
            ImageCaption = requestResponseModel.ImageCaption,
            NumOfLikes = requestResponseModel.NumOfLikes,
            ImageFilePath = requestResponseModel.ImageFilePath,
        }
    
        try
        {
            // Send the domain model up to your service layer ready to be saved
            this.UserImageService.UpdateImage(userId, imageDomainModel);
    
            ViewBag.SuccessMessage = "Your image was updated";
        }
        catch (Exception)
        {
            // Critical error saving user image
        }
    
        return View(requestResponseModel);
    }
    
  3. 您决不会尝试将View Models附加到您的实体框架上下文中。如果你这样做,那么就会拒绝它。它知道在DbContext定义中定义的IDbSet<object>属性可以接受哪些模型:

    public class YourDbContext : DbContext
    {
        public YourDbContext() : ("YourDbConnectionStringName")
        {
        }
    
        // Definitions of valid Entity Framework objects
        public virtual IDbSet<User> Users { get; set; }
        public virtual IDbSet<Image> Images { get; set; }
    }
    
    var dbContext = new YourDbContext();
    
    var imageViewModel = new ImageViewModel();
    var imageDomainModel = new Image();
    
    // Adding object defined within your db context is fine...
    dbContext.Set<Image>().Add(imageDomainModel); // OK
    dbContext.Set<Image>().Add(imageViewModel); // Not OK, will result in exception
    
  4. 我个人不会将域模型发送到我的服务层,我使用DTO(数据传输对象)。但这是另一个故事......

    请参阅我的这篇文章,解释我如何布置我的MVC应用程序:https://stackoverflow.com/a/32890875/894792