最近我对“模特”感到困惑。假设我们在数据库中有一个表“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%相同)。
第一个问题以上用户模型类似,设计的正确方法是什么?
将它们分成不同的独立类
这是我目前正在做的事情,但有些属性很常见,我需要手动设置值(或者使用像AutoMapper这样的东西)
他们之间的共享/继承
似乎“共同属性”被共享,我们在不同的“用户”模型中没有“UserName”属性。但是,注册页面中的视图模型非常奇怪,因为它具有名为“Password”和“PlainTextPassword”的属性,甚至是“UserType”,但实际上只设置了UserName和PlainTextPassword。
-
[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(业务) - >数据。什么是正确的设计?
答案 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)
{
}
谢谢!