项目中不同层的模型

时间:2014-07-13 07:54:20

标签: c# asp.net-mvc

最近我对“模特”感到困惑。假设我们在数据库中有一个表“Users”,包括4列,在数据层中我有一个相应的“User”模型。

namespace MyProject.Data
{
    public class User
    {
         public int Id { get; set; }
         public string UserName { get; set; }
         public string Password { get; set; }
         public int UserType { get; set; }
    }
}

在用户注册页面中,通常我有一个名为“User”的视图模型(或者你可以将其命名为UserRegistration)

namespace MyProject.Web
{
    public class User
    {
        public string UserName { get; set; }
        public string PlainTextPassword { get; set; }
    }
}

此外,我们可能还有一个用户个人资料页面,其中有一个名为“User”或“UserProfile”的相应视图模型具有非常相似的属性(但不是100%相同)。

第一个问题以上用户模型类似,设计的正确方法是什么?

  1. 将它们分成不同的独立类

    这是我目前正在做的事情,但有些属性很常见,我需要手动设置值(或者使用像AutoMapper这样的东西)

  2. 他们之间的共享/继承

    似乎“共同属性”被共享,我们在不同的“用户”模型中没有“UserName”属性。但是,注册页面中的视图模型非常奇怪,因为它具有名为“Password”和“PlainTextPassword”的属性,甚至是“UserType”,但实际上只设置了UserName和PlainTextPassword。

  3. -

    [HttpPost]
    public ActionResult Register(User user)
    {
        //only user.UserName and user.PlainTextPassword are useful
        //however you will have user.Password, user.UserType with default values
        //it even breaks the validation if you use ModelState.IsValid
    }
    

    似乎选项1更好?如果我错了或者你有另一个想法,请纠正我。然后是另一个基于选项1的问题。

    第二个问题我们将MyProject.Web.User作为视图模型,将MyProject.Data.User作为数据模型。注册页面将MyProject.Web.User实例发布到我的控制器,最后我需要通过MyProject.Data.User将它保存到数据库。应该是这样的:

    //the controller in the web project
    [HttpPost]
    public ActionResult Register(User user)
    {
         UserManager.Register(user.UserName, user.PlainTextPassword);
         //blabla
    }
    
    //UserManager in the business layer
    public void Register(string userName, string plainTextPassword)
    {
         //validation
         //set properties to MyProject.Data.User
         //save the changes to db (probably via EF)
    }
    

    您可以看到UserManager的签名。如果添加了更多属性,则会增加。例如string address, string mobile。我认为这里需要一个“用户”模型。 MyProject.Web.User位于Web中,因此无法在UserManager中使用。虽然MyProject.Data.User位于数据层,但如果我们在这里使用MyProject.Data.User,那么MyProject.Web项目需要添加一个引用MyProject.Data,但目前引用关系是UI-> Core(业务) - >数据。什么是正确的设计?

2 个答案:

答案 0 :(得分:1)

这对我来说过去很有用。

在您的场景中,我将创建一个User实体(在另一个项目中 - 可能称为实体或模型)。然后在我的UI层中,我创建了一堆特定于视图的 ViewModels (你当然可以在一些视图之间共享一个基本ViewModel),例如:

// This goes in MyProject.Web/ViewModels ...

public abstract class UserSecurityViewModel {
    // stuff that is shared between the other ViewModels
    public string Username { get; set; }
    public string Password { get; set; }
    // you get the idea ...
}

public class RegistrationViewModel : UserSecurityViewModel {
    // Registration specific properties
    public string Email { get; set; }
    // more ...
}

public class LoginViewModel : UserSecurityViewModel {
    // you don't need the email here ...
    public bool RememberMe { get; set; }
}

然后我当然会在ViewModel和模型之间使用AutoMapper map 之类的东西(在你的情况下是User)。

例如:

[HttpPost]
public ActionResult Register(RegistrationViewModel viewModel) {
   User user = viewModel.ToUser(); // <-- this is an AutoMapper helper

   // now pass that to your business logic layer and do magic
   _userManager.Register(user);
}

我希望我有意义(并且我没有误解你)。

答案 1 :(得分:1)

您可以使用“查看模型”模式来解决您的问题。它只是一个可以传递给视图以显示或形成提交目的的类。

namespace MyProject.Web
{
    public class UserViewModel
    {
        public string UserName { get; set; }
        public string PlainTextPassword { get; set; }
    }
}

然后您的User课程可以放在一个单独的项目中(您可以将其称为Entity),并且可以在Web项目和Data项目中引用它。< / p>

然后在您的控制器中,您可以将ViewModel映射到Model(您可以在此处使用Automapper)并创建User对象并将其传递给Data图层。

[HttpPost]
public ActionResult Register(UserViewModel userViewModel)
{
    User user = // map UserViewModel to User and get user object.
    // pass user object to data layer.
    _userService.Register(user);
}

然后,您可以在User图层中使用相同的Data课程,因为您可以参考Entity项目。

public void Register(User user)
{

}

谢谢!