这种行为让我开始怀疑自己的理智..
我有一个表单,它有两个地方接受输入,我们称它们为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>
控制器操作如下所示:
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,然后表单提交。我可以在控制器操作中设置断点,并在viewModel参数中查看这两个值。此时,ValueA为5,ValueB为0(由于ValueA的设置)。该操作将viewModel作为PartialView的一部分返回。回到片断部分,我可以在Html.TextBox("ValueB",Model.ValueB,...)上设置一个断点。行中,可以看到ValueB确实为0。但是当表单呈现给浏览器时,ValueB的值仍然是7,这就是我遇到的问题。我甚至将Update目标更改为一个不同的div,以便partial只是在完全不同的地方显示出表单,但它仍然具有原始值7,即使我通过调试看到从控制器返回的值是0。
我是不是漏掉了什么?
发布于 2009-12-04 19:58:25
下面是文本框的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;
}
所以发生了什么是Helper查找文本框的值,通过匹配名称,在你的ViewData.ModalState中,如果它在ModelState字典中,它完全忽略你提供的值。
所以所有的if (value > 0) { ValueA = 0;}都无关紧要,因为如果名称匹配,它将使用ModelState中的POST值。
我解决这个问题的方法是,在视图呈现某些我想在视图模型中弄乱的值之前,清除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));
}
}
发布于 2010-11-09 13:01:10
清除整个ModelState也可以做到这一点:
ViewData.ModelState.Clear();
发布于 2010-07-18 14:50:54
谢谢jaf..这是vb代码:
Sub CleanForm(ByVal ParamArray Fields() As String)
Dim modelStateValue As ModelState = Nothing
For Each Field In Fields
If ModelState.TryGetValue(Field, modelStateValue) Then
ModelState.SetModelValue(Field, New ValueProviderResult(Nothing, Nothing, Nothing))
End If
Next
End Sub
https://stackoverflow.com/questions/1848586
复制相似问题