ASP.NET MVC:使用多视图模型以及如何将数据正确传递给模型?

问题描述:

根据我最后的question和我得到的答案,我正在考虑他们以及我的应用程序的真正问题。我想你们帮助我弄清楚了你写的所有内容,非常感谢。于是我做了一个小但工作为例来说明我的问题:ASP.NET MVC:使用多视图模型以及如何将数据正确传递给模型?

我的模型:

public class Order 
    { 
     public int OrderID { get; set; } 
     public string NameOfCustomer { get; set; } 
     public string Address { get; set; } 
    } 

包含2周的ViewModels我所需要的视图模型:

public class ViewModelOrder 
    { 
     public ViewModelSendItNow viewModelSenditNow { get; set; } 
     public ViewModelSafeForLater viewModelSafeForLater { get; set; } 
    } 

视图模型SendItNow:

public class ViewModelSendItNow 
    { 
     [Required] 
     public string NameOfCustomer { get; set; } 
     [Required] 
     public string Address { get; set; } 
    } 

ViewModel SafeForLater:

public class ViewModelSafeForLater 
    { 
     public string NameOfCustomer { get; set; } 
     public string Address { get; set; } 
    } 

的观点:

@model ProblemExample.Models.ViewModelOrder 

@{ 
    ViewBag.Title = "CreateOrder"; 
} 

<h2>CreateOrder</h2> 

@using (Html.BeginForm()) 
{ 
    @Html.AntiForgeryToken() 

    <div class="form-horizontal"> 
     @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 

     @if (Request.Form["SafeForLater"] != null) 
     { 
      @Html.TextBoxFor(m => m.viewModelSafeForLater.NameOfCustomer) 
      @Html.TextBoxFor(m => m.viewModelSafeForLater.Address) 
     } 

     else 
     { 
      @Html.TextBoxFor(m => m.viewModelSenditNow.NameOfCustomer) 
      @Html.TextBoxFor(m => m.viewModelSenditNow.Address) 
     } 
     <hr /> 
     <button class="formular-button-submit" type="submit" name="SenditNow">Send it now!</button> 
     <button class="formular-button-submit" type="submit" name="SafeForLater">Safe it for later!</button> 
    </div> 
} 

@section Scripts { 
    @Scripts.Render("~/bundles/jqueryval") 
} 

控制器:

public ActionResult CreateOrder() 
     { 
      ViewModelOrder viewModel = new ViewModelOrder(); 
      return View(viewModel); 
     } 

     [HttpPost] 
     public ActionResult CreateOrder(ViewModelOrder viewModel) 
     { 
      if (Request.Form["SafeForLater"] != null) 
      { 
       Order myOrder = new Order() 
       { 
        NameOfCustomer = viewModel.viewModelSafeForLater.NameOfCustomer, 
        Address = viewModel.viewModelSafeForLater.Address 
       }; 
       db.Orders.Add(myOrder); 
       db.SaveChanges(); 
      } 

      else 
      { 
       Order myOrder = new Order() 
       { 
        NameOfCustomer = viewModel.viewModelSenditNow.NameOfCustomer, 
        Address = viewModel.viewModelSenditNow.Address 
       }; 
       db.Orders.Add(myOrder); 
       db.SaveChanges(); 
      } 
      return View(viewModel); 
     } 

因此,用户应该看到一种形式,当他决定现在向它发送,确认应跳,如果他想要稍后保存它,不应该进行验证。这就是为什么我试图用视图中的2个按钮来做到这一点。问题是,这个例子适用于现在发送它,它会像保存在数据库中一样,但是当我点击按钮Safe以后,我得到一个Nullreference Exception,我不知道为什么。所以,也许你们看到我的代码中的错误,并给我一个提示,我可以如何解决这个问题或我可以尝试的。

问候,

+0

你的代码没有意义。当视图第一次呈现时,你总是碰到'else'块,并为'viewModelSenditNow'生成表单控件(所以验证将始终启动)。然后在POST方法中,Request.Form [“SafeForLater”]'将始终为'null',因为您的提交按钮不具有'value'属性,因此不会返回值。你为什么然后返回视图呢? –

+0

@StephenMuecke谢谢你的回答。我可以问你一件事,用言语来说,你会如何解决这个问题?从概念的角度来看,我是否完全错过了做这样的事情? – RawMVC

+0

你没有给出足够的信息来解释你想要做什么,但最好的猜测是使用单一的视图模型,其中包含一个'bool SaveAsDraft'属性,并应用一个[万无一失](http://foolproof.codeplex.com /)'[RequiredIfFalse(“SaveAsDraft”)]'到其他属性(并可能重新配置'$ .validator'只在提交时验证)。然后,如果用户想要保存可能无效的“草稿”,他们可以检查由“@ Html.CheckBoxFor(m => m.SaveAsDraft)''生成的复选框。 –

答案很简单,因为你只渲染两个文本框在页面加载时,所以只有两个文本框会得到一个时间,这是渲染,因为它看起来Request.Form["SafeForLater"]是空的,现在把它所以,代码移动到else块并仅渲染现在发送文本框。

你应该渲染并且只隐藏/使用css显示它们。 所以你的代码应该是这样的:

@model ProblemExample.Models.ViewModelOrder 

@{ 
    ViewBag.Title = "CreateOrder"; 
} 

<h2>CreateOrder</h2> 

@using (Html.BeginForm()) 
{ 
    @Html.AntiForgeryToken() 

    <div class="form-horizontal"> 
     @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 

     @if (Request.Form["SafeForLater"] != null) 
     { 
      @Html.TextBoxFor(m => m.viewModelSafeForLater.NameOfCustomer) 
      @Html.TextBoxFor(m => m.viewModelSafeForLater.Address) 
      <div style="display:none"> 
       @Html.TextBoxFor(m => m.viewModelSenditNow.NameOfCustomer) 
       @Html.TextBoxFor(m => m.viewModelSenditNow.Address) 
      </div> 
     } 

     else 
     { 
      <div style="display:none"> 
       @Html.TextBoxFor(m => m.viewModelSafeForLater.NameOfCustomer) 
       @Html.TextBoxFor(m => m.viewModelSafeForLater.Address) 
      </div> 

      @Html.TextBoxFor(m => m.viewModelSenditNow.NameOfCustomer) 
      @Html.TextBoxFor(m => m.viewModelSenditNow.Address) 
     } 
     <hr /> 
     <button class="formular-button-submit" type="submit" name="SenditNow">Send it now!</button> 
     <button class="formular-button-submit" type="submit" name="SafeForLater">Safe it for later!</button> 
    </div> 
} 

@section Scripts { 
    @Scripts.Render("~/bundles/jqueryval") 
} 
+0

Hi @Haitham Shaddad, 感谢您的回答,我尝试了您的解决方案,它解决了Nullreference的错误,但Safe It for Later的值并未保存到数据库,它只显示为空 – RawMVC

+0

您是否调试过并检查行动中的值?你能否确认这些值绑定到控制器操作中的模型?只是为了知道它是一个数据绑定问题还是保存到数据库问题 –

+0

我做了一步一步调试,并且这些值似乎没有绑定到模型,在模型中这两个值均为空。 – RawMVC