在ASP.NET CORE 1.1项目中,我有以下模型:
public class GetProductsModel {
public OrderExpression OrderBy { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
OrderExpression是一个具有以下方法的类:
Boolean TryParse(String value, out OrderExpression expression)
Run Code Online (Sandbox Code Playgroud)
该方法OrderExpression从a 创建一个实例String并可以使用:
OrderExpression expression;
Boolean parsed = OrderExpression.TryParse(value, out expression);
Run Code Online (Sandbox Code Playgroud)
如何为类型属性创建自定义模型绑定器OrderExpression?
我假设在您的请求数据中有一个orderBy您想要绑定到OrderExpression使用的属性OrderExpression.TryParse.
我们假设你的OrderExpression类看起来如下,我提供了一个非常简单的TryParse方法实现:
public class OrderExpression
{
public string RawValue { get; set; }
public static bool TryParse(string value, out OrderExpression expr)
{
expr = new OrderExpression { RawValue = value };
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以创建一个模型绑定器,它基本上获取原始字符串值并调用OrderExpression.TryParse:
public class OrderExpressionBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
var values = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (values.Length == 0) return Task.CompletedTask;
// Attempt to parse
var stringValue = values.FirstValue;
OrderExpression expression;
if (OrderExpression.TryParse(stringValue, out expression))
{
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, expression, stringValue);
bindingContext.Result = ModelBindingResult.Success(expression);
}
return Task.CompletedTask;
}
}
Run Code Online (Sandbox Code Playgroud)
您还需要一个新的模型绑定程序提供程序,它只返回OrderExpression类型的新绑定程序:
public class OrderExpressionBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
return context.Metadata.ModelType == typeof(OrderExpression) ? new OrderExpressionBinder() : null;
}
}
// It should be registered in your Startup class, adding it to the ModelBinderProviders collection:
services.AddMvc(opts => {
opts.ModelBinderProviders.Insert(0, new OrderExpressionBinderProvider());
});
Run Code Online (Sandbox Code Playgroud)
有了这个,您将能够绑定OrderExpression控制器操作的参数.类似于以下示例中的内容:
[HttpPost]
public IActionResult Products([FromBody]OrderExpression orderBy)
{
return Ok();
}
$.ajax({
method: 'POST',
dataType: 'json',
url: '/home/products',
data: {orderby: 'my orderby expression'}
});
Run Code Online (Sandbox Code Playgroud)
但是,还需要做一些事情才能发送json并将其绑定到GetProductsModel内部包含的复杂模型OrderExpression.我在谈论这样的场景:
[HttpPost]
public IActionResult Products([FromBody]GetProductsModel model)
{
return Ok();
}
public class GetProductsModel
{
public OrderExpression OrderBy { get; set; }
}
$.ajax({
method: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
url: '/home/products',
data: JSON.stringify({orderby: 'my orderby expression'})
});
Run Code Online (Sandbox Code Playgroud)
在那种情况下,ASP.Net Core将使用Newtonsoft.Json作为InputFormatter并将接收到的json转换为GetProductsModel模型的实例,而不尝试将new OrderExpressionBinderProvider用于内部属性.
幸运的是,您还可以OrderExpression通过创建JsonConverter 告诉Newtonsoft.Json如何格式化类型的属性:
public class OrderExpressionJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(OrderExpression);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var stringValue = reader.Value?.ToString();
OrderExpression expression;
if (OrderExpression.TryParse(stringValue, out expression))
{
return expression;
}
return null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Run Code Online (Sandbox Code Playgroud)
哪个应该在您的Startup类中注册:
services.AddMvc(opts => {
opts.ModelBinderProviders.Insert(0, new OrderExpressionBinderProvider());
}).AddJsonOptions(opts => {
opts.SerializerSettings.Converters.Add(new OrderExpressionJsonConverter());
});
Run Code Online (Sandbox Code Playgroud)
现在你终于可以处理这两种情况:)
| 归档时间: |
|
| 查看次数: |
2023 次 |
| 最近记录: |