为什么 ASP.NET MVC 回发后模型为空

问题描述 投票:0回答:2

我正在使用最新的 .NET Framework 和 VS 2019 开发 ASP.NET MVC 应用程序。

在我的页面中,我有一个简单的文本框和一个搜索按钮。当我单击搜索按钮并回发表单时,在控制器中,我得到

model.Code
is NULL

这是我的代码 - 我的视图模型:

public class UserManagementViewModel
{
    public string Code { get; set; }
    // some other properties including simple and complex types
}

视图中:

<td style="min-width: 300px">
    @Html.TextBoxFor(m => m.Code)
</td>

在控制器中:

[HttpPost]
public ActionResult UpdateUserPermissions(UserManagementViewModel model)
{
    // model.Code is null here!!
    return RedirectToAction("UserManagement");
}

经过几个小时的研究,我尝试了以下方法:

我查看了 html 源代码并发现了

<input id="Code" name="Code">

使用 Chrome 开发工具,我将输入的名称更改为

"Model.Code"

<input id="Code" name="Model.Code">

这次,我在回发后得到了文本框中输入的值。

我不知道为什么会发生这种情况以及为什么元素名称没有正确生成!

我能做什么?

编辑:

我还有一些其他控件,例如复选框和单选按钮,我使用纯 HTMl 代码并将它们命名为以“Model”开头。像下面这样而不是使用 @HTML 助手。

它工作得很好,我在行动中得到了价值。

解决方法:

我在这里找到了解决方法:ASP.NET MVC 4 覆盖发出的 html 名称和 id 所以我将代码更改为:

@Html.TextBoxFor(m => m.Code, new { @Name = "Model.Code" })

但是这段代码帮助我解决了我的问题,我仍然不知道为什么 Razor 引擎生成的名称不起作用。

c# .net asp.net-mvc model-binding
2个回答
2
投票

辅助方法

@Html.TextBoxFor
工作绝对正确。基本上,几乎所有情况都需要使用此方法(除了某些需要使用非标准行为的情况)。

关于您的情况,我认为您在 HtmlFieldPrefix 方面遇到了麻烦。

此属性用于生成 HTML 输入的名称。我们可以在 GitHub 中查看 MVC 源代码...

MVC 使用以下代码片段生成 HTML 输入(GitHub link):

private static MvcHtmlString InputHelper(HtmlHelper htmlHelper, InputType inputType, ModelMetadata metadata, string name, object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, string format, IDictionary<string, object> htmlAttributes)
{
    string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
    if (String.IsNullOrEmpty(fullName))
    {
        throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name");
    }

    TagBuilder tagBuilder = new TagBuilder("input");
    tagBuilder.MergeAttributes(htmlAttributes);
    tagBuilder.MergeAttribute("type", HtmlHelper.GetInputTypeString(inputType));
    tagBuilder.MergeAttribute("name", fullName, true);

    string valueParameter = htmlHelper.FormatValue(value, format);
    bool usedModelState = false;

    ...

    return tagBuilder.ToMvcHtmlString(TagRenderMode.SelfClosing);
}

正如我们所见,

name
属性是通过方法
GetFullHtmlFieldName
计算出来的。

这个方法我们也可以在GitHub上查看(link):

public string GetFullHtmlFieldName(string partialFieldName)
{
    if (partialFieldName != null && partialFieldName.StartsWith("[", StringComparison.Ordinal))
    {
        // See Codeplex #544 - the partialFieldName might represent an indexer access, in which case combining
        // with a 'dot' would be invalid.
        return HtmlFieldPrefix + partialFieldName;
    }
    else
    {
        // This uses "combine and trim" because either or both of these values might be empty
        return (HtmlFieldPrefix + "." + (partialFieldName ?? String.Empty)).Trim('.');
    }
}

此方法使用

HtmlFieldPrefix
属性计算名称。因此,如果您更改此属性,您可以修改生成的名称。

我认为您使用部分

Views
并且您需要使用一些前缀来渲染属性才能正确绑定。

请查看下一个链接,其中包含示例和可能的解决方案:


0
投票

在其他情况下,要提交模型,您必须使用表单标签。 MVC 有时将名称视为模型属性,但最好明确地执行此操作。该代码经过测试,文本框的两种变体都可以正常工作。如果您使用表单,则根本不需要任何名称,相反,在大多数情况下,如果您同时使用名称和表单,您将得到 null。

@model UserManagementViewModel 

<form  asp-action="UpdateUserPermissions" method="post">

     @Html.TextBoxFor(m => m.Code)

    // or

    <div class="form-group">
        <label asp-for="Code" class="control-label"></label>
        <input asp-for="Code" class="form-control" />
    </div>
    
    <div>
        <button  type="submit"> submit </button>
    </div>

</form>
© www.soinside.com 2019 - 2024. All rights reserved.