[英]C# ASP.NET Core ModelBinder not Updating Model
I have created a ModelBinder, which only gets triggered if an object has a [Decimal]
attribute assigned, yet for some reason, despite it actually sanitising the data it does not seem to update the posted model. 我创建了一个ModelBinder,它仅在为对象分配了[Decimal]
属性时才触发,尽管出于某种原因,尽管它实际上已经清理了数据,但似乎并没有更新发布的模型。
I wonder if someone could see from my code below, where I maybe going wrong. 我想知道是否有人可以从下面的代码中看到我可能出错的地方。
Startup.cs 启动文件
public void ConfigureServices(IServiceCollection serviceCollection)
{
serviceCollection.AddMvc(config => config.ModelBinderProviders.Insert(0, new DecimalModelBinderProvider()));
}
DecimalModelBinderProvider.cs DecimalModelBinderProvider.cs
public class DecimalModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext modelBinderProviderContext)
{
if (modelBinderProviderContext == null)
{
throw new ArgumentNullException(nameof(modelBinderProviderContext));
}
if (!modelBinderProviderContext.Metadata.IsComplexType)
{
try
{
var propertyName = modelBinderProviderContext.Metadata.PropertyName;
var property = modelBinderProviderContext.Metadata.ContainerType.GetProperty(propertyName);
if (property != null)
{
var attribute = property.GetCustomAttributes(typeof(DecimalAttribute), false).FirstOrDefault();
if (attribute != null)
{
return new DecimalModelBinder(modelBinderProviderContext.Metadata.ModelType, attribute as IDecimalAttribute);
}
}
}
catch (Exception exception)
{
var message = exception.Message;
return null;
}
}
return null;
}
}
DecimalModelBinder.cs DecimalModelBinder.cs
public class DecimalModelBinder : IModelBinder
{
private readonly IDecimalAttribute _decimalAttribute;
private readonly SimpleTypeModelBinder _simpleTypeModelBinder;
public DecimalModelBinder(Type type, IDecimalAttribute decimalAttribute)
{
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
_decimalAttribute = decimalAttribute;
_simpleTypeModelBinder = new SimpleTypeModelBinder(type);
}
public Task BindModelAsync(ModelBindingContext modelBindingContext)
{
if (modelBindingContext == null)
{
throw new ArgumentNullException(nameof(modelBindingContext));
}
var valueProviderResult = modelBindingContext.ValueProvider.GetValue(modelBindingContext.ModelName);
if (valueProviderResult != ValueProviderResult.None)
{
modelBindingContext.ModelState.SetModelValue(modelBindingContext.ModelName, valueProviderResult);
var value = valueProviderResult.FirstValue;
bool success;
var result = _decimalAttribute.Decimal(value, out success);
if (success)
{
modelBindingContext.Result = ModelBindingResult.Success(result);
return Task.CompletedTask;
}
}
return _simpleTypeModelBinder.BindModelAsync(modelBindingContext);
}
}
IDecimalAttribute.cs IDecimalAttribute.cs
public interface IDecimalAttribute
{
object Decimal(string value, out bool success);
}
DecimalAttribute.cs DecimalAttribute.cs
[AttributeUsage(AttributeTargets.Property)]
public class DecimalAttribute : Attribute, IDecimalAttribute
{
public object Decimal(string value, out bool success)
{
var tryModelValue = string.IsNullOrEmpty(value) ? "0.00" : value.Replace("£", "").Replace("%", "");
decimal @decimal;
success = decimal.TryParse(tryModelValue, out @decimal);
return @decimal;
}
}
Test.cs Test.cs
public class Test
{
[Display(Name = "Name", Description = "Name")]
public string Name { get; set; }
[Decimal]
[Display(Name = "Amount", Description = "Amount")]
public double Amount { get; set; }
}
HomeController 家庭控制器
[ValidateAntiForgeryToken]
[HttpPost]
public IActionResult Index(Test test)
{
if (ModelState.IsValid)
{
}
return View(test);
}
For the purpose of testing I will enter the value £252.83 into the Amount field and submit the form. 为了进行测试,我将在“金额”字段中输入值252.83英镑并提交表格。
If I then place a brakepoint on the line var value = valueProviderResult.FirstValue;
如果然后在行上放置制动点var value = valueProviderResult.FirstValue;
I can see that value is £252.83 and if I place a breakpoint on the line modelBindingContext.Result = ModelBindingResult.Success(result);
我可以看到该值为252.83英镑,如果我在modelBindingContext.Result = ModelBindingResult.Success(result);
行上放置一个断点, modelBindingContext.Result = ModelBindingResult.Success(result);
I can see that the result is 252.83M
. 我可以看到结果是252.83M
。
However if I step through the code further and place a breakpoint on the line if (ModelState.IsValid)
the valid state is false and if I inspect the model test
the object Amount
is 0. 但是,如果我进一步单步执行代码并在if (ModelState.IsValid)
有效状态为false的情况下在该行上放置一个断点,并且如果我检查模型test
的对象Amount
为0。
If anyone can help it would be much appreciated :-) 如果有人可以帮助,将不胜感激:-)
Try inspect further on the ModelState Error, the Amount property should be invalid and there must be an exception. 尝试进一步检查ModelState错误,Amount属性应该无效,并且必须存在异常。
I am guessing it should be InvalidCastException. 我猜应该是InvalidCastException。 I notice that the Amount property in Test class is Double while you are producing Decimal in your DecimalAttribute. 当您在DecimalAttribute中生成Decimal时,我注意到Test类中的Amount属性为Double。
So the build-in Model Binder that processing the Test class (should be ComplexTypeModelBinder) unable to set the Amount property as it is different type. 因此,处理Test类(应为ComplexTypeModelBinder)的内置Model Binder无法设置Amount属性,因为它是另一种类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.