【发布时间】:2017-09-11 22:04:02
【问题描述】:
我想在原始数据分配给模型属性之前对其进行一些预处理。即用点替换逗号以允许将此字符串“324.32”和“324,32”都转换为双精度。所以我写了这个模型活页夹
public class MoneyModelBinder: IModelBinder
{
private readonly Type _modelType;
public MoneyModelBinder(Type modelType)
{
_modelType = modelType;
}
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
string modelName = bindingContext.ModelName;
ValueProviderResult providerResult = bindingContext.ValueProvider.GetValue(modelName);
if (providerResult == ValueProviderResult.None)
{
return TaskCache.CompletedTask;
}
bindingContext.ModelState.SetModelValue(modelName, providerResult);
string value = providerResult.FirstValue;
if (string.IsNullOrEmpty(value))
{
return TaskCache.CompletedTask;
}
value = value.Replace(",", ".");
object result;
if(_modelType == typeof(double))
{
result = Convert.ToDouble(value, CultureInfo.InvariantCulture);
}
else if(_modelType == typeof(decimal))
{
result = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
}
else if(_modelType == typeof(float))
{
result = Convert.ToSingle(value, CultureInfo.InvariantCulture);
}
else
{
throw new NotSupportedException($"binder doesn't implement this type {_modelType}");
}
bindingContext.Result = ModelBindingResult.Success(result);
return TaskCache.CompletedTask;
}
}
然后是适当的提供者
public class MoneyModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if(context.Metadata?.ModelType == null)
{
return null;
}
if (context.Metadata.ModelType.In(typeof(double), typeof(decimal), typeof(float)))
{
return new MoneyModelBinder(context.Metadata.ModelType);
}
return null;
}
}
并在 Startup.cs 中注册它
services.AddMvc(options =>
{
options.ModelBinderProviders.Insert(0, new MoneyModelBinderProvider());
});
但我注意到一些奇怪的行为,或者我错过了一些东西。如果我使用这种动作
public class Model
{
public string Str { get; set; }
public double Number { get; set; }
}
[HttpPost]
public IActionResult Post(Model model)
{
return Ok("ok");
}
并在查询字符串中提供参数一切正常:首先为模型本身调用提供程序,然后为模型的每个属性调用。 但是如果我使用 [FromBody] 属性并通过 JSON 提供参数,则为模型调用提供程序,但从未调用此模型的属性。但为什么?如何在 FromBody 中使用活页夹?
【问题讨论】:
-
无法评论您所描述的问题,但作为一种简单的解决方法,您可以接受视图模型(将这些属性作为字符串),然后使用 AutoMapper 将其映射到您的实体模型/dto在您的控制器操作中。
-
您在发帖时是否明确设置了内容类型标头?仅仅因为它看起来像 JSON 并不意味着它会被解释为 JSON。
标签: c# asp.net-core asp.net-core-mvc