MVC.NET来自Create POST的ViewModel始终为null

时间:2014-04-06 19:49:32

标签: c# html asp.net-mvc razor viewmodel

在我的MVC.NET项目中,我使用了脚手架模板。最初将其绑定到一个DTO模型。现在我决定将它链接到ViewModel,因为我需要使用两个多重选择来传递值。这就是我的ViewModel的外观:

public class CreateQuestionModel
{
   public Question Question { get; set; }
   public List<int> PoliticianIds { get; set; }
   public List<int> TopicIds { get; set; }
}

我的创建POST方法,从View:

获取ViewModel
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Regular")]
public ActionResult Create(CreateQuestionModel question)
{
  if (ModelState.IsValid)
  {
    int id = WebSecurity.CurrentUserId;
    manager.CreateQuestion(question.Question, id, question.PoliticianIds, question.TopicIds);
    return RedirectToAction("Index");
  }

  return View(question);
}

我的Create.cshtml看起来像这样:

@model PoliticiOnline.Models.CreateQuestionModel
@{
ViewBag.Title = "Stel een vraag!";
}
<head>
<link rel="stylesheet" href="~/Content/Questions.css" type="text/css" />
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
<script src="@Url.Content("~/Scripts/Extra/Chosen/chosen.jquery.min.js")" type="text/javascript"></script>
<link rel="stylesheet" href="@Url.Content("~/Scripts/Extra/Chosen/chosen.min.css")" type="text/css">   
<script src="@Url.Content("~/Scripts/Extra/select2-3.4.6/select2.min.js")" type="text/javascript"></script>
<link rel="stylesheet" href="@Url.Content("~/Scripts/Extra/select2-3.4.6/select2.css")" type="text/css">
</head>

<h2>Stel een vraag!</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
    <legend>Vraag</legend>
    <div class="general-question">
        <div class="editor-label">
            @Html.LabelFor(model => model.Question.GeneralQuestion, "Algemene Vraag")
        </div>
        <div class="editor-field">
            @Html.TextBox("Question.GeneralQuestion", new { @class = "general-question-edit" })
            @Html.ValidationMessageFor(model => model.Question.GeneralQuestion)
        </div>
    </div>

    <div id="geadresseerde-politici">
        @Html.LabelFor(model => model.PoliticianIds, "Geadresseerde Politicians:")
        @Html.ListBox("PoliticianIds", (MultiSelectList)ViewBag.Politicians, new { @id = "polDrop" })
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.Question.Explanation, "Extra Uitleg")
    </div>
    <div class="editor-field">
        @Html.TextArea("Question.Explanation", new { @class = "explanation-textarea-edit" })
        @Html.ValidationMessageFor(model => model.Question.Explanation)
    </div>

    <div>
        @Html.LabelFor(model => model.TopicIds, "Kies je thema's (maximum 2):")
        @Html.ListBox("TopicIds", (MultiSelectList)ViewBag.Topics, new { @id = "select2select", @style = "width: 500px"})
    </div>

    <p>
        <input type="submit" value="Indienen!" />
    </p>
</fieldset>
}

<div>
@Html.ActionLink("Back to List", "Index")
</div>


<script type="text/javascript">
function format(topic) {
    if (topic.css == 'optionGroup') {
        return "<b>" + topic.text + "</b>";
    } else {
        return "<i>&nbsp;&nbsp;&nbsp;" + topic.text + "<i>";
    }
}

$("#select2select").select2({
    placeholder: "Selecteer een thema...",
    maximumSelectionSize: 2,
    formatResult: format,
    escapeMarkup: function(m) {
        return m;
    }
});
</script>

底部的<script>部分并不重要,但无论如何我粘贴了它,我使用了ListBox的jQuery插件select2。

这是一种将文本框绑定到ViewModel属性的方法,我在Stackoverflow上找到了这个。我还尝试使用@Html.EditorFor@HtmlListBoxFor的经典方法,但ViewModel的属性始终为null。

我做错了什么/我在忽视什么?

修改 我在ViewModel中放置了一个构造函数,现在ViewModel(CreateQuestionModel)不再为null,但值仍然是默认值(不是表单中的值)。我的ViewModel现在看起来像:

public class CreateQuestionModel
{
public Question Question { get; set; }
public List<int> PoliticianIds { get; set; }
public List<int> TopicIds { get; set; }

public CreateQuestionModel()
{
  Question = new Question();
  PoliticianIds = new List<int>();
  TopicIds = new List<int>();
}
}

评论者Yoeri提供了解决方案,你可以在我对这个问题的回答中看到它!

3 个答案:

答案 0 :(得分:2)

我在发送到ViewModel时导致Controller中所有属性为 默认 值的愚蠢错误。我没有为每个属性声明{get; set;}

错误

public class ApplicationViewModel
{
    public Application App;        
    public SelectList SelectSimple;
    public ApplicationViewModel() 
    {
        // Create/Init App & SelectSimple
    }
}

<强> CORRECT

public class ApplicationViewModel
{
    public Application App { get; set; }
    public SelectList SelectSimple { get; set; }
    public ApplicationViewModel() 
    {
        // Create/Init App & SelectSimple
    }

}

<强> COMMENT

需要重复的是,Controller需要一个将非空ViewModel传递给View的[HttpGet];和Controller需要一个[HttpPost]来接收用户提交的ViewModel。

答案 1 :(得分:1)

好的伙计们,我刚刚发现我做错了什么。我犯了一个极其愚蠢的错误,不能相信我现在已经挣扎了2天。

我的创建POST方法的签名是:

public ActionResult Create(CreateQuestionModel question)
{
    ...
}

应该是:

public ActionResult Create(CreateQuestionModel createQuestionModel)
{
    ...
}

我只需要将参数形式CreateQuestionModel question更改为CreateQuestionModel createQuestionModel,就这么简单,现在一切正常。

<强>更新 感谢Yoeri,我现在明白为什么它首先提出问题:

最初我将参数命名为CreateQuestionModel question,这没有用,因为我有一个名为Question的模型类。所以基本上参数名称必须是您在创建视图中使用的模型的名称,或者任何其他名称,只要它不是另一个模型类的名称!

谢谢Yoeri!

答案 2 :(得分:0)

尝试,

@using(Html.BeginForm("Create", "*controller-name*",FormMethod.Post))