gpt4 book ai didi

asp.net-mvc - 使用模型对象更新 ModelState

转载 作者:行者123 更新时间:2023-12-04 00:18:45 25 4
gpt4 key购买 nike

问题:如何在发布+验证场景中更新 ModelState。

我有一个简单的表格:

<%= Html.ValidationSummary() %>
<% using(Html.BeginForm())%>
<%{ %>
<%=Html.TextBox("m.Value") %>
<input type="submit" />
<%} %>

当用户提交时,我想验证输入,在某些情况下我想为用户修复错误,让他知道他犯了一个已经修复的错误:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(M m)
{
if (m.Value != "a")
{
ModelState.AddModelError("m.Value", "should be \"a\"");
m.Value = "a";
return View(m);
}
return View("About");
}

问题是,MVC 将简单地忽略传递给 View 的模型,并将重新呈现用户输入的任何内容——而不是我的值(“a”)。
发生这种情况是因为 TextBox 渲染器会检查是否存在 ModelState 以及它是否不为 null - 使用 ModelState 的值。该值当然是发布前输入的一个用户。

由于我无法更改 TextBox 渲染器的行为,因此我找到的唯一解决方案是自己更新 ModelState。最简单的方法是(ab)使用 DefaultModelBinder 并通过简单地更改分配方向来覆盖将值从表单分配给模型的方法;)。使用 DefaultModelBinder 我不必解析 ID。
以下代码(基于 DefaultModelBinder 的原始实现)是我的解决方案:
/// <summary>
/// Updates ModelState using values from <paramref name="order"/>
/// </summary>
/// <param name="order">Source</param>
/// <param name="prefix">Prefix used by Binder. Argument name in Action (if not explicitly specified).</param>
protected void UpdateModelState(object model, string prefix)
{
new ReversedBinder().BindModel(this.ControllerContext,
new ModelBindingContext()
{
Model = model,
ModelName = prefix,
ModelState = ModelState,
ModelType = model.GetType(),
ValueProvider = ValueProvider
});
}

private class ReversedBinder : DefaultModelBinder
{
protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
{
string prefix = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name);
object val = typeof(Controller)
.Assembly.GetType("System.Web.Mvc.DictionaryHelpers")
.GetMethod("DoesAnyKeyHavePrefix")
.MakeGenericMethod(typeof(ValueProviderResult))
.Invoke(null, new object[] { bindingContext.ValueProvider, prefix });
bool res = (bool)val;
if (res)
{

IModelBinder binder = new ReversedBinder();//this.Binders.GetBinder(propertyDescriptor.PropertyType);
object obj2 = propertyDescriptor.GetValue(bindingContext.Model);

ModelBindingContext context2 = new ModelBindingContext();
context2.Model = obj2;
context2.ModelName = prefix;
context2.ModelState = bindingContext.ModelState;
context2.ModelType = propertyDescriptor.PropertyType;
context2.ValueProvider = bindingContext.ValueProvider;
ModelBindingContext context = context2;
object obj3 = binder.BindModel(controllerContext, context);

if (bindingContext.ModelState.Keys.Contains<string>(prefix))
{
var prefixKey = bindingContext.ModelState.Keys.First<string>(x => x == prefix);
bindingContext.ModelState[prefixKey].Value
= new ValueProviderResult(obj2, obj2.ToString(),
bindingContext.ModelState[prefixKey].Value.Culture);
}
}
}
}

所以问题仍然存在:我是在做一些非常不寻常的事情还是我错过了什么?如果是前者,那么我怎样才能以更好的方式实现这样的功能(使用现有的 MVC 基础设施)?

最佳答案

我知道这篇文章已经很老了,但这是我以前遇到的一个问题,我只是想到了一个我喜欢的简单解决方案 - 在获得发布的值后清除 ModelState。

UpdateModel(viewModel);
ModelState.Clear();

viewModel.SomeProperty = "a new value";
return View(viewModel);

并且 View 必须使用(可能修改过的) View 模型对象而不是 ModelState。

也许这真的很明显。事后看来似乎如此!

关于asp.net-mvc - 使用模型对象更新 ModelState,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/719390/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com