asp.net-mvc – ASP.NET MVC – 正确使用View Model和Command模
我已经编写ASP.NET MVC应用程序一段时间了,我发现它们是使用命令模式的好地方:我们将每个用户请求表示为命令 – 一组输入参数 – 然后处理此命令(处理包括验证和其他域逻辑),结果将发送回用户.
我在我的应用程序中使用的另一件事是视图模型.我发现它们是将数据传递给视图比使用域对象作为模型或填充ViewData / ViewBag更方便的方式. 这两个概念非常适合将显示给用户的数据与用户输入及其处理分开,但它们在ASP.NET MVC中并不完全一致. 假设我想在开发一个简单的网上商店时使用命令和视图模型,用户可以在其中查看产品,并可以通过提供产品名称和电子邮件地址来订购产品: class ProductViewModel { public ProductViewModel(int id) { /* init */ } public int Id { get; set; } public string Name { get; set; } // a LOT of other properties (let's say 50) } class OrderProductCommand { public int ProductId { get; set; } [Required(ErrorMessage = "Name not specified")] public string Name { get; set; } [Required(ErrorMessage ="E-Mail not specified")] public string Email { get; set; } public CommandResult Process() { /* validate,save to DB,send email,etc. */ } } 在浏览教程时,我看到人们提出了几种方法. 选项1 控制器: [HttpGet] public ActionResult Product(int id) { return View(new ProductViewModel(id)); } [HttpPost] public ActionResult Product(OrderProductCommand command) { if (ModelState.IsValid) { var result = command.Process(); if(result.Success) return View("ThankYou"); else result.CopyErrorsToModelState(ModelState); } return Product(command.Id); } 视图: @using (Html.BeginForm()) { @Html.Hidden("ProductId",Model.Id) @Html.TextBox("Name") @Html.TextBox("Email") <input type="submit" value="Place order" /> } 优点:视图模型和命令相互分离,HttpPost方法看起来很干净 缺点:我无法使用方便的HTML帮助程序,如@ Html.TextBoxFor(model => model.Email),我无法使用客户端验证(参见my other question) 选项2 我们将Id,Name和Email连同其验证属性从命令复制到viewModel. 控制器: [HttpPost] public ActionResult Product(ProductViewModel viewModel) { var command = new OrderProductCommand(); command.Id = viewModel.Id; command.Name = viewModel.Name; command.Email = viewModel.Email; if (ModelState.IsValid) // ... } 视图: @Html.TextBoxFor(m => m.Email) ... 优点:所有选项1缺点都消失了 缺点:复制属性似乎不方便(如果我有50个?),在视图模型中验证名称和电子邮件(它应该在域逻辑的其余部分所在的命令中完成),模型作为POST参数(请参阅下面) 选项3 我们使命令成为viewModel的属性. 控制器: [HttpPost] public ActionResult Product(ProductViewModel viewModel) { var command = viewModel.Command; if (ModelState.IsValid) // ... } 视图: @Html.TextBoxFor(m => m.Command.Email) ... 优点:所有选项1缺点都消失了 缺点:视图模型应该只包含显示给用户的数据(并且不显示命令),模型作为POST参数(见下文) – 我不喜欢选项2和3的是我们使用视图模型作为POST方法参数.此方法用于处理用户输入(在这种情况下仅隐藏2个字段1),并且该模型包含50个我将永远不会在此方法中使用且始终为空的属性.更不用说为视图模型创建一个空构造函数的必要性,只是为了处理这个POST请求以及为每个POST请求创建大型视图模型对象时不必要的内存消耗. 我的问题是(这就像有史以来最长的问题,我知道):是否存在一个秘密的选项4,用于正确使用命令和查看模型,这些模型具有所有优点,而没有其他优点?或者我是偏执狂,这些缺点并不重要,可以忽略不计? 解决方法
看起来像唯一的另一种不错的方式是使用局部视图来渲染表单并使用OrderProductCommand作为视图模型.
Product.cshtml: @model ProductViewModel ... @Html.Partial("Product_OrderForm",new OrderProductCommand { ProductId = Model.Id }) ... Product_OrderForm.cshtml: @model OrderProductCommand ... @using (Html.BeginForm("Product","Home")) { @Html.HiddenFor(cmd => cmd.ProductId) @Html.TextBoxFor(cmd => cmd.Name) @Html.TextBoxFor(cmd => cmd.Email) <input type="submit" value="Place order" /> } ... 这样就不需要在视图模型和业务对象之间创建数据映射,并且控制器代码可以像在选项1中一样保持干净: [HttpGet] public ActionResult Product(int id) { return View(new ProductViewModel(id)); } [HttpPost] public ActionResult Product(OrderProductCommand command) { // process command... } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- ASP.NET DateTime Picker
- asp.net – 在Visual Studio 2015中保存* .cs或* .cshtml文
- asp.net-mvc-2 – 在名称中使用连字符处理MVC2变量
- asp.net – 检测是否加载了HttpModule
- EE 519: Speech Recognition and Processing for Multimedi
- Asp.net会话交叉/混合
- asp.net-mvc – 输入类型=“隐藏”vs htmlhelper奇怪的问题
- asp.net – IIS错误 – HTTP错误500.24 – 内部服务器错误
- asp.net-mvc-4 – ASP.NET MVC电子商务解决方案(商业或开放
- asp.net-mvc – 为什么DropDownListFor不能识别编辑器模板中
- asp.net-mvc – 设置登台和生产环境,最大限度地减
- 如何为新项目决定WebForms vs ASP.NET MVC 3?
- asp.net-mvc – ASP.NET MVC,将Model从View传递给
- asp.net-mvc – ASP.net MVC 4从数据库加载菜单到
- asp.net-mvc – Asp.net Web api异常仅在IIS部署
- asp.net – 为本地化设置TemplateField HeaderTe
- ASP.Net Gridview,如何激活基于ID的编辑模式(Dat
- asp.net – 重启后,每个页面的MVC应用程序都很慢
- 创建全局ASP.NET功能?
- ASP.NET 存取EXCEL 使用NPOI相关小技巧