asp.net-mvc – 如何在MVC中完全分离视图和模型
|
在我的第一个例子中,我有一个像这样的模型: public class GuestResponse
{
[Required(ErrorMessage = "Please enter your name")]
public string Name { get; set; }
[Required(ErrorMessage = "Please enter your email")]
[RegularExpression(".+@.+..+",ErrorMessage = "Please enter a valid email address")]
public string Email { get; set; }
public string Phone { get; set; }
[Required(ErrorMessage = "Please specify whether you'll attend")]
public bool? WillAttend { get; set; }
}
控制者: public class HomeController : Controller
{
public ViewResult Index()
{
ViewData["greeting"] = (DateTime.Now.Hour < 12 ? "Good morning" : "Good afternoon");
return View();
}
[HttpGet]
public ViewResult RsvpForm()
{
return this.View();
}
[HttpPost]
public ViewResult RsvpForm(GuestResponse guestResp)
{
if (ModelState.IsValid)
{
return this.View("Thanks",guestResp);
}
else
{
return this.View();
}
}
}
一个视图: @model GuestResponse
<body>
<div>
<h1>
Thank you,<%: Model.Name %>.</h1>
<p>
<% if (Model.WillAttend == true)
{ %>
It's great that you're coming. The drinks are already in
the fridge!
<% }
else
{ %>
Sorry to hear you can't make it,but thanks for letting
us know.
<% } %>
</p>
</div>
对我来说似乎很奇怪的是,View与模型紧密耦合:它使用类似Model.WillAttend等代码……那么如果在未来的时间模型发生变化会发生什么?我应该更改此特定视图中的所有片段. 假设我的视图将显示一个注册页面,我将在其中显示名称,标题,地址1,地址2等的输入,并且所有这些字段将绑定到模型,但该模型可能不存在.那么我可以创建一个接口,模型将实现该接口,视图将只导入该接口而不是模型类?因此,创建UI作为结果,当我们键入Model时,IntelliSense将显示名称,地址2等. 我应该遵循什么方法,这样两个人可以分别开发视图和模型?因此,当创建视图时,模型可能不存在,而模型将在以后创建.怎么可能?通过界面? 解决方法将视图与视图模型分开一秒钟深入思考这个问题,不可能将View与View模型分离.你无法开始创建一个网页,而不会以某种方式预期会在页面上显示哪些信息以及在哪里 – 因为这正是编写HTML代码的原因.如果您没有至少决定这两件事中的一件,那么就没有任何HTML代码可供编写.因此,如果您有一个显示来自控制器的信息的页面,则需要定义视图. 传递给视图的视图模型应仅表示仅为单个视图(或部分视图)显示的数据字段.它不是“可解耦的”,因为你永远不需要多次实现它 – 它没有逻辑,因此没有其它的实现.这是您的应用程序的其他部分需要解耦才能使它们可重用和可维护. 即使您使用动态ViewBag并使用反射来确定其中包含的属性以动态显示整个页面,最终您还必须决定信息的显示位置和顺序.如果您在视图和相关帮助程序之外的任何地方编写任何HTML代码,或者在视图中执行除显示逻辑之外的任何操作,那么您可能违反了MVC的基本原则之一. 一切都没有丢失,继续阅读…… 独立于视图模型开发视图 就两个人而言,他们分别独立地开发您的视图和模型 //@model RegistrationViewModel <p>Welcome to the Registration Page</p> 如果没有定义@model,则不必将模型从控制器传递到视图: public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
// Return the view,without a view model
return View();
}
}
您还可以为MVC使用HTML帮助程序的非强类型版本.因此,如果定义了@model视图,您可能已写入: @Html.LabelFor(m => m.UserName) @Html.TextBoxFor(m => m.UserName) 相反,使用名称末尾没有For的版本,这些版本接受字符串作为名称而不是直接引用您的模型: @Html.Label("UserName")
@Html.TextBox("UserName")
稍后当您为页面完成视图模型时,可以稍后使用强类型的帮助程序版本更新这些版本.这将使您的代码在以后更加强大. ASP.NET MVC中对象的一般注释 在评论的背面,我将尝试向您展示我如何倾向于在MVC中布置我的代码以及我使用的不同对象以便将事物分开…这将真正使您的代码更易于维护由多人组成.当然,这是一个时间上的投资,但在我看来,随着应用程序的发展,这是非常值得的. 您应该为不同的目的使用不同的类,一些跨层,一些驻留在特定层中,不从这些层外部访问. 我的MVC项目通常有以下类型的模型: >域模型 – 表示数据库中行的模型,我倾向于仅在我的服务层中操作它们,因为我使用实体框架,所以我没有这样的“数据访问层”. 这是我如何使用它们(你问了代码,所以这里是一个我刚刚与你的相似的例子,但只是为了一个简单的注册): 领域模型 这是一个域模型,它简单地表示用户及其在数据库中的列.我的DbContext使用域模型,我操纵我的服务层中的域模型. public User
{
public string UserName { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
数据传输对象(DTO) 以下是我在控制器的UI层中映射的一些数据传输对象,并传递给我的服务层,反之亦然.看看它们有多干净,它们应该只包含在层之间来回传递数据所需的字段,每个字段都应该有特定的用途,比如服务层中的特定方法接收或返回. public class RegisterUserDto()
{
public string UserName { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
public class RegisterUserResultDto()
{
public int? NewUserId { get; set; }
}
查看模型 这是一个仅存在于UI层的视图模型.它特定于单个视图,永远不会在您的服务层内触及!您可以使用它来映射回发到控制器的值,但您不必这样做 – 您可以专门为此目的使用一个全新的模型. public class RegistrationViewModel()
{
public string UserName { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
服务层 这是服务层的代码.我有一个DbContext的实例,它使用域模型来表示数据.我将注册的响应映射到我专门为RegisterUser()方法的响应创建的DTO. public interface IRegistrationService
{
RegisterUserResultDto RegisterUser(RegisterUserDto registerUserDto);
}
public class RegistrationService : IRegistrationService
{
public IDbContext DbContext;
public RegistrationService(IDbContext dbContext)
{
// Assign instance of the DbContext
this.DbContext = dbContext;
}
// This method receives a DTO with all of the data required for the method,which is supposed to register the user
public RegisterUserResultDto RegisterUser(RegisterUserDto registerUserDto)
{
// Map the DTO object ready for the data access layer (domain)
var user = new User()
{
UserName = registerUserDto.UserName,Password = registerUserDto.Password,Email = registerUserDto.Email,Phone = registerUserDto.Phone
};
// Register the user,pass the domain object to your DbContext
// You could pass this up to your Data Access LAYER if you wanted to,to further separate your concerns,but I tend to use a DbContext
this.DbContext.EntitySet<User>.Add(user);
this.DbContext.SaveChanges();
// Now return the response DTO back
var registerUserResultDto = RegisterUserResultDto()
{
// User ID generated when Entity Framework saved the `User` object to the database
NewUserId = user.Id
};
return registerUserResultDto;
}
}
调节器 在控制器中,我们映射DTO以发送到服务层,作为回报,我们收到DTO. public class HomeController : Controller
{
private IRegistrationService RegistrationService;
public HomeController(IRegistrationService registrationService)
{
// Assign instance of my service
this.RegistrationService = registrationService;
}
[HttpGet]
public ActionResult Index()
{
// Create blank view model to pass to the view
return View(new RegistrationViewModel());
}
[HttpPost]
public ActionResult Index(RegistrationViewModel requestModel)
{
// Map the view model to the DTO,ready to be passed to service layer
var registerUserDto = new RegisterUserDto()
{
UserName = requestModel.UserName,Password = requestModel.Password,Email = requestModel.Email,Phone = requestModel.Phone
}
// Process the information posted to the view
var registerUserResultDto = this.RegistrationService.RegisterUser(registerUserDto);
// Check for registration result
if (registerUserResultDto.Id.HasValue)
{
// Send to another page?
return RedirectToAction("Welcome","Dashboard");
}
// Return view model back,or map to another view model if required?
return View(requestModel);
}
}
(编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 将ASP.NET MVC4应用程序部署到GoDaddy编译器问题
- asp.net+Ajax 文本文件静态分页实现代码
- ASP.NET中的超链接控件和链接控件有什么区别?
- asp.net-mvc – 从控制器重定向初始化不工作
- asp.net – 如何知道一个javascript文件是否已被包含在顶级
- asp.net – BrowserLink MVC 6 – 不工作 – 没有额外的代码
- ASP.NET MVC4 WebAPI和Posting XML数据
- asp.net-mvc-3 – MVC按钮点击动作
- asp.net-mvc – MVC3 AntiForgeryToken打破了Ajax登录
- 模型 – 视图 – 控制器 – ASP.NET MVC:使用SendAsync发送
