【问题标题】:MVC.NET the ViewModel from Create POST is always nullMVC.NET Create POST 中的 ViewModel 始终为空
【发布时间】:2014-04-06 19:49:32
【问题描述】:

在我的 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; }
}

我的 Create 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>

底部的&lt;script&gt; 部分并不重要,但我还是把它粘贴了,我正在为 ListBox 使用 jQuery 插件 select2。

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

我做错了什么/我忽略了什么?

编辑: 我在 ViewModel 中放置了一个构造函数,现在 ViewModel (CreateQuestionModel) 不再为空,但值仍然是默认值(不是表单中的值)。我的 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 提供了解决方案,您可以在下面我对这个问题的回答中看到它!

【问题讨论】:

  • 构造函数无济于事:它在您的模型初始化时运行,因此它与模型绑定无关。我目前正在测试用例中查看它。第一个提示:使用带有 lambda 的 @Html.TextBoxFor 而不是 @Html.Textbox("")。使用字符串很容易出错!
  • 您是否实际调试过控制器方法以确定“问题”参数是否为空?
  • 我做了,我刚刚发现我做错了什么,我会发布答案!
  • @E.V.d.B.为了回应您关于返回的视图模型属性是它们的“默认”值的评论,我通过修复一个愚蠢的错误解决了这个错误。在我的视图模型中,我忘记为每个属性声明 {get; set;},例如TopicId, PoliticianId, Question

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


【解决方案1】:

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

错误

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

正确

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

}

评论

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

【讨论】:

    【解决方案2】:

    好的,伙计们,我刚刚发现我做错了什么。我犯了一个非常愚蠢的错误,不敢相信我已经为此苦苦挣扎了 2 天。

    我的 Create POST 方法的签名是:

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

    应该是:

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

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

    更新 多亏了 Yoeri,我现在明白了为什么它首先会出现问题:

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

    谢谢约里!

    【讨论】:

    • 幸好你让它工作了,但这很奇怪。参数的名称应该无关紧要。
    • 能否再尝试更改参数名称?我能够重现您的问题,重命名后又恢复了,绑定按预期工作。
    • 我在这个 StackOverflow 线程中找到了解决方案,其中标记的解决方案也在更改参数。
    • @Yoeri 你的意思是把它从createQuestionModel改回question然后试试看?
    • 我想我找到了真正的问题。你有一个名为“问题”的模型,我认为它混淆了模型绑定器。尝试将名称更改为例如。 “模型”(或任何不是您的解决方案中的类)。
    【解决方案3】:

    试试,

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

    【讨论】:

    • 刚试了一下,模型还是 null :((然后我在 ViewModel 中放了一个构造函数,不,它不是 null,但它的所有值都是 null ...)
    猜你喜欢
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    • 1970-01-01
    • 2014-11-05
    • 2020-05-22
    • 1970-01-01
    • 2016-12-03
    • 1970-01-01
    相关资源
    最近更新 更多