【问题标题】:MVC 5 Viewmodel binding works but post back is partial filledMVC 5 Viewmodel 绑定有效,但回发已部分填充
【发布时间】:2015-02-20 07:56:02
【问题描述】:

我有一个无参数的Index 用于HttpGet,它可以工作。但是当我发布它时,会调用IndexHttpPost 版本并传入viewmodel 对象,但其中只有下拉列表的值。其余为空(产品、标题)

[HttpPost]
public ActionResult Index(ProductsViewModel pvm)
{
    // breakpoint on line 36, shows that pvm.Title is null and Products too.
    return View(pvm);
}

我的可编译运行示例可以从我的 OneDrive http://1drv.ms/1zSsMkr下载

我的看法:

@model KleinKloteProductOverzicht.Models.ProductsViewModel
@using (Html.BeginForm("Index", "Products"))
{
<h2>@Html.DisplayFor(m => m.Title)</h2>
<input type="submit" value="post dit" /><br/>
<div class="row">
    <div class="col-lg-2 col-md-2">
        @Html.DropDownListFor(x => x.CurrentSort, EnumHelper.GetSelectList(typeof(SortOptions)), new { @class = "multiselect"})
    </div>
</div>
if (Model.Products.Count() > 0)
{
    <div class="row">
        @foreach (var item in Model.Products)
        {
            @Html.DisplayFor(i => item.Name);
        }
    </div>
}
}

【问题讨论】:

  • 你能提供视图相关部分的代码吗?发布时表单数据包含什么?
  • 你需要给你看相关的查看代码
  • 没有人会费心去下载代码...
  • 它必须在您的视图中设置才能被回发。例如,如果您从操作中填写了一个选择列表并将其发送到视图,则在回发时它将为空,因为该属性不是从视图中设置的!
  • 大声笑,似乎将测试项目上传到 onedrive 是没用的 ;) 将用我的剃刀视图更新问题

标签: c# model-view-controller asp.net-mvc-5


【解决方案1】:

如果我有这个视图模型:

public class ViewModel
{
    public string Name {get;set;}
    public string SelectedLocation {get;set;}

    public IEnumerable<SelectListItem> Locations {get;set;}
}

你的动作看起来像这样:

public ActionResult MyForm()
{
    var vm = new ViewModel
    {
        Locations = context.Locations.ToList() // Some database call
    }

    return View(vm);
}

[HttpPost]
public ActionResult MyForm(ViewModel vm)
{
    vm.Locations // this is null
}

它是null,因为模型绑定器找不到正在设置其数据的表单控件。

&lt;form&gt; 必须在视图中设置一些数据,以便模型绑定器拾取它。

<form>
    Name: <input type="text" id="name" />
</form>

这将在视图模型上设置Name 属性,因为模型绑定可以看到表单控件的id 并使用它来知道要绑定到什么。

因此,就您的观点而言,您需要确保使用@using(Html.BeginForm()) 包装任何要回发到服务器的内容

反正这是我的猜测。

【讨论】:

  • 那么我应该如何调整我的视图以确保 Model.Products 不为空(标题相同)
  • 更新了我的答案,也请查看asp.net,因为他们向您展示了如何做到这一点。
【解决方案2】:

好吧,您似乎对 [HttpPost] 和表单标签如何相互作用感到困惑。

您会看到,当 .NET MVC 在您的控制器操作中绑定您的参数时,它会尝试从请求中派生该数据。对于 [HttpGet],它通过查看查询字符串来做到这一点。

对于 [HttpPost] 调用,它还会查看 Request.Form。此变量由您提交的表单中的所有输入字段的值填充。

现在,这是你的观点:

@using (Html.BeginForm("Index", "Products"))
{
    <h2>@Html.DisplayFor(m => m.Title)</h2>
    <input type="submit" value="post dit" /><br/>
    <div class="row">
        <div class="col-lg-2 col-md-2">
            @Html.DropDownListFor(x => x.CurrentSort, EnumHelper.GetSelectList(typeof(SortOptions)), new { @class = "multiselect" })
        </div>
    </div>
    if (Model.Products.Count() > 0)
    {
        <div class="row">
            @foreach (var item in Model.Products)
            {
                @Html.DisplayFor(i => item.Name);
            }
        </div>
    }
}

您只有一个select 标签(由 Dropdownlistfor 生成),但没有其他输入。这就是 .NET MVC 无法为您的视图模型推断任何其他数据的原因。

如果您将视图更改为:

@model KleinKloteProductOverzicht.Models.ProductsViewModel

@using (Html.BeginForm("Index", "Products"))
{
    <h2>@Html.DisplayFor(m => m.Title)</h2>
    <input type="submit" value="post dit" /><br/>
    <div class="row">
        <div class="col-lg-2 col-md-2">
            @Html.DropDownListFor(x => x.CurrentSort, EnumHelper.GetSelectList(typeof(SortOptions)), new { @class = "multiselect" })
        </div>
    </div>
    if (Model.Products.Count() > 0)
    {
        <div class="row">
            @for (var i = 0; i < Model.Products.Count; i++)
            {
                @Html.DisplayFor(model => model.Products[i].Name)
                @Html.HiddenFor(model => model.Products[i].ID)
            }
        </div>
    }

}

您会看到我为产品 ID 添加了一个隐藏输入 (&lt;input type="hidden"&gt;)。请注意,产品名称仍将为空。

我建议您遵循 .NET MVC 教程并阅读其背后的一些概念,因为您提出这个问题的事实表明您有很多东西要学。

祝你好运!

附:最后一个提示:@Html.Blablabla 直接写入您的视图。你通常不需要那个“;”最后,因为它将在您生成的 html 中。

【讨论】:

    【解决方案3】:

    您的属性与“可发布”控件无关,因此它不会与表单数据一起提交。如果您真的想获取 Title 属性中的值,只需将其设置为隐藏输入即可。

     @Html.HiddenFor(m => m.Title)
    

    提交form 时不会发布label,但会发布input。这正是HiddenFor 所做的;它创建了一个隐藏的input 元素,form 提交将拾取该元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-27
      • 2013-07-10
      • 1970-01-01
      • 2015-10-17
      • 1970-01-01
      • 1970-01-01
      • 2015-09-14
      相关资源
      最近更新 更多