这种行为让我怀疑我的理智..
我的表单有两个地方可以接受输入,我们称它们为 ValueA 和 ValueB。用户可以在其中任何一个中输入一个值,然后提交表单。
<div id="MyUpdateTarget">
<% using (Ajax.BeginForm("MyControllerAction", new AjaxOptions { UpdateTargetId = "MyUpdateTarget" })) { %>
<%=Html.TextBox("ValueA", Model.ValueA, new Dictionary<string, object> {
{ "onchange", "$('#SubmitButton').click(); return false;" },
}) %>
<%=Html.TextBox("ValueB", Model.ValueB, new Dictionary<string, object> {
{ "onchange", "$('#SubmitButton').click(); return false;" },
}) %>
<input id="SubmitButton" type="submit" value="Save" style="display: none;" />
<% } %>
</div>
Controller Action 看起来像这样:
public ActionResult MyControllerAction(MyViewModel viewModel)
{
//做一些其他的事情...
return PartialView("MyPartialView", viewModel);
}
ViewModel 就是这样:
public class MyViewModel
{
private int _valueA;
private int _valueB;
public int ValueA
{
get
{
return _valueA;
}
set
{
if (value > 0)
{
ValueB = 0;
}
_valueA = value;
}
}
public int ValueB
{
get
{
return _valueB;
}
set
{
if (value > 0)
{
ValueA = 0;
}
_valueB = value;
}
}
}
现在,意想不到的作品。假设页面最初加载并且 ValueB 的值为 7。用户将 ValueA 更改为 5 并且表单提交。我可以在 Controller 操作中放置一个断点,并在 viewModel 参数中查看这两个值。此时,ValueA 为 5,ValueB 为 0(由于 ValueA 的设置)。该操作将 viewModel 作为 PartialView 的一部分返回。回到局部,我可以在 Html.TextBox("ValueB", Model.ValueB, ...) 行上放置一个断点,然后看到 ValueB 确实是 0。但是当表单呈现给浏览器时,ValueB 仍然有一个值为 7。这就是我被困的地方。我什至将 Update 目标更改为不同的 div,因此部分只是在完全不同的地方吐出形式,但它仍然具有原始值 7,即使我通过调试看到该值是 0 从 Controller 。
有什么我想念的吗?
最佳答案
这是文本框的 MVC 源代码:
string attemptedValue = (string)htmlHelper.GetModelStateValue(name, typeof(string));
tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(name) : valueParameter**), isExplicitValue);
break;
以及 GetModelStateValue() 的代码
internal object GetModelStateValue(string key, Type destinationType) {
ModelState modelState;
if (ViewData.ModelState.TryGetValue(key, out modelState)) {
if (modelState.Value != null) {
return modelState.Value.ConvertTo(destinationType, null /* culture */);
}
}
return null;
}
那么发生的是 Html“Helper”通过匹配名称在您的 ViewData.ModalState 中查找文本框值,如果它在 ModelState 字典中,它完全忽略您的值提供。
所以所有这些 if (value > 0) { ValueA = 0; } 没关系,因为如果名称匹配,它将使用 ModelState 中发布的值。
我解决这个问题的方法是在 View 呈现我想在我的 View 模型中弄乱的某些值之前吹走 ModelState。这是我用过的一些代码:
public static void SanitizeWildcards( Controller controller, params string[] filterStrings )
{
foreach( var filterString in filterStrings )
{
var modelState = controller.ModelState;
ModelState modelStateValue;
if( modelState.TryGetValue(filterString,out
controller.ModelState.SetModelValue(filterString, new ValueProviderResult("","", null));
}
}
关于c# - 如果发布后模型中的值发生变化,表单仍显示旧值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1848586/