为啥在 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 中回发后模型为空的主要内容,如果未能解决你的问题,请参考以下文章