[英]ASP.NET Core modelbinder binding request body to one property of model
[英]How can I enhance ModelBinder in ASP.NET Core (update property values for a model class)
我想增强ModelBinder
返回的最终结果。
例如:
public class MyModel
{
public int Order {get;set;}
[MyUpperCaseAttribute]
public string Title {get;set;}
}
在API方法中,我希望MyModel
中具有MyUpperCaseAttribute
所有字符串属性都是大写的。
例如:
[HttpPost("AddRecord")]
public async Task<ActionResult<int>> AddRecord(MyModel model)
{
model.Title should be upper case, even if send from client in lower case.
}
我的想法是覆盖默认的ModelBinder
并枚举所有属性,并检查属性是否为字符串并且具有MyUpperCaseAttribute
并将属性值更正为大写。 我检查文档,但是没有示例没有正确填写,因为它们完全重新设计了返回的内容。 我想修改结果属性。
什么是实现理想行为的最佳选择?
重要:(已编辑):
如果可以堆叠指令属性,那将是很好的:
public class MyModel
{
public int Order {get;set;}
[MyUpperCaseAttribute]
[RemoveSpacesAttribute]
public string Title {get;set;}
}
编辑:
它看起来与此类似,但如果不是其他,则这是ASP.NET Core,而链接上只是ASP.NET。 方法,属性,接口......不一样。
我应该说,如果JSON案例规则可行,那将是很好的:
public class MyModel
{
public int Order {get;set;}
public string Title {get;set;}
}
如果从JavaScript发送{order: 1, title: "test"}
(通知小写),则应该有效。
这可能不是“最佳”选项,但我只使用.ToUpper()
扩展方法而不是自定义属性过滤器。
public class MyModel
{
private string _title;
public int Order {get;set;}
public string Title { get => _title.ToUpper(); set => _title = value.ToUpper(); }
}
您可以在MyUpperCaseAttribute
中执行以下操作:
public class MyUpperCaseAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if(value != null)
{
validationContext.ObjectType
.GetProperty(validationContext.MemberName)
.SetValue(validationContext.ObjectInstance, value.ToString().ToUpper(), null);
}
return null;
}
}
在Model Binding
期间,属性值将转换为UpperCase
。 我已经在我身边检查了它,它完美无缺。
这里有一个大红鲱鱼,这就是看起来这是可以而且应该通过模型绑定完成的事情。 不幸的是,在ASP.Net Core Web API中并非如此:因为传入的数据是JSON,它实际上是由输入格式化程序处理的,而不是模型绑定程序。 因此,为了达到预期的效果,您需要创建自己的自定义输入格式化程序来替换标准的JsonInputFormatter
。
首先是属性:
[AttributeUsage(AttributeTargets.Property)]
public class ToUppercaseAttribute : Attribute
{
}
然后我们用它装饰我们的模型类:
public class MyModel
{
public int Order { get; set; }
[ToUppercase]
public string Title { get; set; }
}
现在创建我们的自定义输入格式化程序,检查该属性并在必要时转换输出。 在这种情况下,它只是包装并委托给JsonInputFormatter
来正常执行繁重的操作,然后在任何string
属性上找到ToUppercaseAttribute
属性时修改结果:
public class ToUppercaseJsonInputFormatter : TextInputFormatter
{
private readonly JsonInputFormatter _jsonInputFormatter;
public ToUppercaseJsonInputFormatter(JsonInputFormatter jsonInputFormatter)
{
_jsonInputFormatter = jsonInputFormatter;
foreach (var supportedEncoding in _jsonInputFormatter.SupportedEncodings)
SupportedEncodings.Add(supportedEncoding);
foreach (var supportedMediaType in _jsonInputFormatter.SupportedMediaTypes)
SupportedMediaTypes.Add(supportedMediaType);
}
public override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
{
var result = _jsonInputFormatter.ReadRequestBodyAsync(context, encoding);
foreach (var property in context.ModelType.GetProperties().Where(p => p.PropertyType.IsAssignableFrom(typeof(string))
&& p.CustomAttributes.Any(a => a.AttributeType.IsAssignableFrom(typeof(ToUppercaseAttribute)))))
{
var value = (string)property.GetValue(result.Result.Model);
property.SetValue(result.Result.Model, value.ToUpper());
}
return result;
}
}
接下来,我们创建一个扩展方法,使用我们的自定义格式化程序替换默认的JsonInputFormatter
变得简单:
public static class MvcOptionsExtensions
{
public static void UseToUppercaseJsonInputFormatter(this MvcOptions opts)
{
if (opts.InputFormatters.FirstOrDefault(f => f is JsonInputFormatter && !(f is JsonPatchInputFormatter)) is JsonInputFormatter jsonInputFormatter)
{
var jsonInputFormatterIndex = opts.InputFormatters.IndexOf(jsonInputFormatter);
opts.InputFormatters[jsonInputFormatterIndex] = new ToUppercaseJsonInputFormatter(jsonInputFormatter);
}
}
}
最后,调用该方法来实现Startup.cs
的替换:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc(options => options.UseToUppercaseJsonInputFormatter());
}
}
Etvoilà!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.