我想增强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;}
}
已编辑:
它看起来与this类似,但是如果不是其他的话,那就是ASP.NET Core,并且在链接上也只是ASP.NET。方法,属性,接口...都不相同。
我应该说,如果JSON大小写规则可以工作,那就太好了
public class MyModel
{
public int Order {get;set;}
public string Title {get;set;}
}
如果{order: 1, title: "test"}
(注意小写)是从JavaScript发送的,则应该起作用。
答案 0 :(得分:1)
这可能不是“最佳”选项,但是我只会使用.ToUpper()
扩展方法而不是自定义属性过滤器。
public class MyModel
{
private string _title;
public int Order {get;set;}
public string Title { get => _title.ToUpper(); set => _title = value.ToUpper(); }
}
答案 1 :(得分:0)
您可以在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;
}
}
在UpperCase
期间,属性值将转换为Model Binding
。我已经检查过它,并且效果很好。
答案 2 :(得分:0)
这里有一个大红鲱鱼,这是事实,这似乎是可以并且应该通过模型绑定来完成的事情。不幸的是,在ASP.Net Core Web API中并非如此:由于传入的数据是JSON,因此实际上是由input formatters而不是模型绑定程序处理的。因此,为了获得理想的效果,您需要创建自己的自定义输入格式化程序,以替换标准的JsonInputFormatter
。
第一个属性:
[AttributeUsage(AttributeTargets.Property)]
public class ToUppercaseAttribute : Attribute
{
}
然后我们用它装饰模型类:
public class MyModel
{
public int Order { get; set; }
[ToUppercase]
public string Title { get; set; }
}
现在创建我们的自定义输入格式器,以检查该属性并在必要时转换输出。在这种情况下,它只是包装并委托给JsonInputFormatter
来照常进行繁重的工作,如果在任何ToUppercaseAttribute
属性上找到我们的string
属性,则修改结果:
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());
}
}
等等!