【问题标题】:Form-data is not binding to viewmodel with a generic type表单数据未绑定到具有泛型类型的视图模型
【发布时间】:2021-03-19 07:29:01
【问题描述】:

我在 ASP.NET Core 5.0 之上使用 C# 编写了一个应用程序。

我有以下视图模型

public class TestVM 
{
   public Name  { get; set; }

   public MenuViewModel<string> State { get; set;}

   public TestVM()
   {
       State = MenuViewModel<string>();
   }
}

这是我的MenuViewModel的精简版


public class MenuViewModel
{
    [BindNever]
    public IEnumerable<SelectListItem> Items { get; set; }
}

public class MenuViewModel<T> : MenuViewModel
{
    public T Value { get; set; }
}

问题是,当 post 请求进来时,viewModel.State.Value 为空。当我评估Request.Form 时,我确实看到了State.Value 的正确值CA

这是我在控制器中的操作方法的精简版。

[HttpPost, ValidateAntiForgeryToken]
public IActionResult Store(TestVM viewModel)
{

   if(ModelState.IsValid)
   {
     // do some
   }

   return View(viewModel);
}

如何将请求中的表单数据正确绑定到State.Value 属性?

更新我创建了一个编辑器模板来允许我渲染 MenuVieModel。 ~/Views/Shared/EditorTemplates/MenuViewModel.cshtml 包含以下代码

@model dynamic

@{
    if (!(Model is MenuViewModel m))
    {
        return;
    }

    dynamic obj = new System.Dynamic.ExpandoObject();
    obj.Class = "form-control";
    if (Html.ViewData.ModelMetadata.IsRequired)
    {
        obj.Required = true;
    }
}

@Html.DropDownList("Value", m.Options, Html.ViewData.ModelMetadata.Placeholder, obj)

【问题讨论】:

  • 显示相关视图部分。
  • @mxmissile 请查看更新后的帖子
  • 你如何渲染 MenuViewModel.cshtml?你能分享一下get方法吗?你的m.Options在剃刀视图中是什么?当我复制你的代码时,它会出错:'MenuViewModel' does not contain a definition for 'Options' and no accessible extension method 'Options' accepting a first argument of type 'MenuViewModel' could be found (are you missing a using directive or an assembly reference?) .您的 MenuViewModel 是否包含 Options 属性?

标签: c# asp.net-core asp.net-core-mvc model-binding asp.net-core-5.0


【解决方案1】:

首先,您需要知道对于复杂类型的每个属性,模型绑定会在源中查找名称模式prefix.property_name。如果未找到任何内容,则只查找不带前缀的 property_name

这是一个您可以关注的工作演示:

型号:

public class TestVM
{
    public string Name { get; set; }

    public MenuViewModel<string> State { get; set; }
    public TestVM()
    {
        State =new MenuViewModel<string>();
    }
}
public class MenuViewModel
{
    [BindNever]
    public IEnumerable<SelectListItem> Items { get; set; }
}

public class MenuViewModel<T> : MenuViewModel
{
    public T Value { get; set; }
}

查看:

@model dynamic

@{
    if (!(Model is MenuViewModel m))
    {
        return;
    }

    dynamic obj = new System.Dynamic.ExpandoObject();
    obj.Class = "form-control";
    if (Html.ViewData.ModelMetadata.IsRequired)
    {
        obj.Required = true;
    }
}
<form asp-action="Store">

          @*change here,And I do not find Options in your MenuViewModel,So I change it to Items*@
    @Html.DropDownList("State.Value", m.Items, Html.ViewData.ModelMetadata.Placeholder, obj)
    <input type="submit" value="post" />
</form>

控制器:

public IActionResult Index()
{
    var model = new MenuViewModel<string>()
    {
        Items = new List<SelectListItem>() {
            new SelectListItem() { Value = "-1", Text = "--- Select ---" },
            new SelectListItem() { Value = "org1", Text = "org1" },
            new SelectListItem() { Value = "org2", Text = "org2" },
            new SelectListItem() { Value = "org3", Text = "org3" }
            }
    };        
    return View(model);
}
[HttpPost, ValidateAntiForgeryToken]
public IActionResult Store(TestVM viewModel)
{
    if (ModelState.IsValid)
    {
        // do some
    }

    return View(viewModel);
}

结果:

【讨论】:

  • 嗯,我的代码对你有用吗?我想知道为什么Value 对我来说总是为空,即使请求有State.Value
  • 不,你的代码对我不起作用。我认为你需要将整个代码分享给我,我在你的剃刀视图中找不到m.Options。请检查我的剃刀视图,我的代码和你的不一样。
  • 是的。抱歉,这是一个复制/粘贴错误。正确的代码是 m.Items。但是模型绑定对你有用,对我没用。对我来说 State.Value 始终为空
  • 你把@Html.DropDownList("Value"改成@Html.DropDownList("State.Value"了吗?另外,检查我的模型,你提供的模型也是错误的。检查TestVM中的构造函数和名称。
  • 感谢您的帮助!问题是在我的代码中我有public T Value 而不是public T Value { get; set; } 这就是为什么Value 总是设置为null。但是为了让视图起作用,应该使用“Value”而不是“State.Value”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-07
  • 2011-02-08
  • 1970-01-01
  • 2012-08-28
  • 1970-01-01
相关资源
最近更新 更多