复杂模型在行动中返回null?

时间:2014-11-08 05:58:36

标签: c# .net asp.net-mvc asp.net-mvc-4

强类型视图有<form>并且在提交<form>时我希望它应该在模型中返回更新的值,但实际情况并非如此。我无法弄清楚它到底发生了什么。

查看模式:

public class HomeLoanViewModel
{
    public Lead_Options leadOption { get; set; }       
    public Lead HomeLoanLead {get;set;}

    public HomeLoanViewModel()
    {
        this.leadOption= new Lead_Options();
        this.HomeLoanLead= new Lead();
    }
}

和ViewModel中的Lead类如下:

public partial class Lead
{
    public string Lead_id { get; set; }      
    public string Income { get; set; }

    [NotMapped]
    public List<SelectListItem> Income_Binder
    {
        get
        {
            return new List<SelectListItem>()
            {
                new SelectListItem(){ Value="", Text="Please select...", Selected=true },
                new SelectListItem(){ Value="$0 - $30,000", Text="$0 - $30,000" },
                new SelectListItem(){ Value="$30,001 - $40,000", Text="$30,001 - $40,000" },
                new SelectListItem(){ Value="$40,001 - $50,000", Text="$40,001 - $50,000"},
                new SelectListItem(){ Value="$50,001 - $60,000", Text="$50,001 - $60,000"},
                new SelectListItem(){ Value="$60,001 - $70,000", Text="$60,001 - $70,000"},
                new SelectListItem(){ Value="$70,001 - $80,000", Text="$70,001 - $80,000"},
                new SelectListItem(){ Value="$80,001 - $90,000", Text="$80,001 - $90,000"},
                new SelectListItem(){ Value="$90,001 - $100,000", Text="$90,001 - $100,000"},
                new SelectListItem(){ Value="$100,001 - $150,000", Text="$100,001 - $150,000"},
                new SelectListItem(){ Value="$150,000+", Text="$150,000+"}
            };
        }
    }
}

控制器&amp;动作:

public class HomeLoanController : ParentController
{
    [HttpGet]
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Submit(FormCollection form)
    {
        Session["loan_type"] = form.GetValue("Type").AttemptedValue;
        Session["m_I_need_to"] = form.GetValue("LoanPurpose").AttemptedValue;
        Session["m_The_property_is_a"] = form.GetValue("LoanFor").AttemptedValue;
        Session["m_My_time_frame_to_buy_or_refinance_is"] = form.GetValue("LoanTimeFrame").AttemptedValue;

       // return View("LeadContact", new HomeLoanViewModel());
       return RedirectToAction("LeadContact");
    }

    [HttpGet]
    public ActionResult LeadContact(HomeLoanViewModel model)
    {
        return View(model);
    }
}

查看:

@using HMC.Common.Utilities;
@model HMC.Common.ViewModel.HomeLoanViewModel
@{
    ViewBag.Title = "LeadContact";
    Layout = "~/Views/_Base.cshtml";
}

<form class="wrapper minheight homeloan-form border-top" id="homeloan-form" method="post" action="" novalidate="novalidate">
<label>Total Annual Income</label>
@Html.DropDownListFor(m => m.HomeLoanLead.Income, Model.HomeLoanLead.Income_Binder, new { required = "", aria_required = "true", name = "interestratetype" })
@Html.HiddenFor(m => m.HomeLoanLead.Income)
<div class="formnav row">
     <button class="btn btn-large">Show Top Home Loans <i class="fa fa-chevron-right"></i></button>
</div>
</form>

编辑: 从上一页/查看请求到提交控制器的操作,然后它重定向到LeadContact。这是我传递模型和回发后想要接收更新值的视图。

1 个答案:

答案 0 :(得分:0)

将ViewModel或强类型视图与模型一起使用时,此类问题很常见。这就是为什么...... 当回发发生时,模型绑定器最终在控制器被调用回发之前被调用。如果控制器接受类(model或viewmodel)作为输入参数,则MVC将首先使用null构造函数创建类的实例。然后,模型绑定器将获取HTML查询字符串(名称值对),并尝试根据名称值对填充模型/视图模型属性。如果绑定器找不到正确的名称匹配,它根本不做任何事情(这是正确的行为),因此其症状是“嘿我丢失了我知道我从视图中发布的数据”。

调试此方法的最佳方法是1)在控制器的操作方法上设置断点。 2)转到客户端并按F12查看网络帖子。 3)开始回发并注意从浏览器发送的名称值对。在控制器条目处断开时,请执行Debug / Windows / Locals并查看控制器参数的模型部分。你会在网络端看到同样的东西(证明他们都回来了)。现在看一下打字的值,如果有什么不存在,那只是因为帖子后面和模型(名称值)不匹配。

90%的时间根本原因是DisplayFor的第一个参数,HiddenFor或其他“For”元素没有指向要返回的正确的东西。这就是我喜欢使用ViewModels的原因..

鉴于:

public class HomeLoanViewModel
{
  public Lead_Options leadOption { get; set; }       
  public Lead HomeLoanLead {get;set;}
  public String SelectedValue {get;set;}

  public HomeLoanViewModel()
  {
    this.leadOption= new Lead_Options();
    this.HomeLoanLead= new Lead();
  }
  public void Post(){
     //do all your post logic here
     if(SelectedValue > XYZ) //do this
  }
}

我会像这样创建控制器签名:

 [HttpPost]
public ActionResult Submit(HomeLoanViewModel vm)
{
     if (ModelState.IsValid){
               vm.Post();
               return View(vm);
     }
  return View(vm);
}

我会创建这样的视图:

@using HMC.Common.Utilities;
@model HMC.Common.ViewModel.HomeLoanViewModel
@{
  ViewBag.Title = "LeadContact";
  Layout = "~/Views/_Base.cshtml";
}
@Using Html.BeginForm(){

    <label>Total Annual Income</label>
     @Html.DropDownListFor(m => m.HomeLoanLead.SelectedValue, Model.HomeLoanLead.Income_Binder, new { required = "", aria_required = "true"})

     <input type="submit/>

}

<div class="formnav row">
 <button class="btn btn-large">Show Top Home Loans <i class="fa fa-chevron-right"></i></button>
</div>

最后另一个指针,在SelectListItems Text和Value中没有任何意义相同,你可以很容易地在Int中设置值,例如[1,2,3,4,5]为每个选择。将值视为文本字段的标识符,这对于具有用于查找字段值的ID的数据库尤其有效。