为啥在 ASP.NET MVC 中回发后模型为空

Posted

技术标签:

【中文标题】为啥在 ASP.NET MVC 中回发后模型为空【英文标题】:Why model is null after postback in ASP.NET MVC为什么在 ASP.NET MVC 中回发后模型为空 【发布时间】:2021-12-19 01:12:31 【问题描述】:

我正在使用最新的 .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 代码并将它们命名为以“模型”开头。如下所示,而不是使用 @HTML 助手。

它工作正常,我在行动中得到了价值。

解决方法:

我在这里找到了解决方法:ASP.NET MVC 4 override emitted html name and id 所以我将代码更改为:

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

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

【问题讨论】:

有几件事情浮现在脑海中,您可以检查一下:您确定您的视图具有与控制器操作所期望的相同类型的视图模型吗?使用 TextBoxFor 帮助器生成的 HTML 是什么样子的? 【参考方案1】:

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

关于你的情况,我认为你对HtmlFieldPrefix 有问题。

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

MVC 使用此代码 sn-p 生成 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 并且您需要使用一些前缀呈现属性才能正确绑定。

请查看带有示例和可能解决方案的下一个链接:

ASP.NET MVC Partial Views with Partial Models ASP.NET MVC3 add a HtmlFieldPrefix when calling Controller.PartialView Define a custom HTML prefix for your .NET MVC models

【讨论】:

就我而言,我没有部分视图。您提供了一些有用的信息,尤其是最后一个链接。谢谢你。我仍然想知道为什么它没有按照开箱即用的方式工作。显然框架正在运行,我很困惑我的代码出了什么问题。 @FLICKER 也许您还有其他 DataBinding 实现?这些实现重新定义了数据绑定的标准行为。 我不这么认为。使用 VS 项目创建,一切都是开箱即用的。【参考方案2】:

在其他返回模型时,您必须使用表单标签。 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>

【讨论】:

我已经准备好了一切。为了简单起见,我只是删除了它们。感谢您的建议。 不客气。

以上是关于为啥在 ASP.NET MVC 中回发后模型为空的主要内容,如果未能解决你的问题,请参考以下文章

在mvc中回发后自动完成功能不起作用

在gridview中回发后Javascript代码不会运行

在 ASPX 中回发后按键不起作用

在 .NET 中回发后从后面的代码中获取 HTML5 输入类型搜索的值

回发后asp.net jquery脚本未运行

动态创建的 asp.net 控件在回发后消失