dotnet core webapi json-api 兼容查询字符串路由
Posted
技术标签:
【中文标题】dotnet core webapi json-api 兼容查询字符串路由【英文标题】:dotnet core webapi json-api compliant querystring route 【发布时间】:2017-03-26 11:58:11 【问题描述】:我试图从请求的 URL 中获取“状态”和“全部”键、值,但不知道如何构建我的类对象。
我所指的 JSON API 规范可以在这里找到: http://jsonapi.org/recommendations/#filtering
// requested url
/api/endpoint?filter[status]=all
// my attempt at model binding
public class FilterParams
public Dictionary<string, string> Filter get; set;
[HttpGet]
public string Get([FromUri] FilterParams filter)
// never gets populated...
var filterStatus = filter.Filter["status"];
【问题讨论】:
【参考方案1】:如果您在 .Net Core 上构建 json:api 应用程序,我强烈建议您查看这个库:https://github.com/json-api-dotnet/JsonApiDotNetCore
它为您处理所有繁重的工作,对于这个特定示例,(您需要获取过滤器值)解决方案如下所示:
public FooController : JsonApiController<Foo>
private readonly IQueryAccessor _queryAccessor;
public FooController(IQueryAccessor queryAccessor, /* ... */)
: base(/* ... */)
_queryAccessor = queryAccessor;
[HttpGet]
public override async Task<IActionResult> GetAsync()
var status = _queryAccessor.GetRequired<string>("status");
// ...
【讨论】:
【参考方案2】:您可以为此使用IModelBinder:
定义模型绑定器:
public class FilterParamsModelBinder : IModelBinder
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
if (bindingContext.ModelType != typeof(FilterParams)) return false;
Dictionary<string, string> result = new Dictionary<string, string>();
var parameters = actionContext.Request.RequestUri.Query.Substring(1);
if(parameters.Length == 0) return false;
var regex = new Regex(@"filter\[(?<key>[\w]+)\]=(?<value>[\w^,]+)");
parameters
.Split('&')
.ToList()
.ForEach(_ =>
var groups = regex.Match(_).Groups;
if(groups.Count == 0)
bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Cannot convert value.");
result.Add(groups["key"].Value, groups["value"].Value);
);
bindingContext.Model = new FilterParams Filter = result;
return bindingContext.ModelState.IsValid;
使用它:
[HttpGet]
public string Get([ModelBinderAttribute(typeof(FilterParamsModelBinder))] FilterParams filter)
//your code
如果您可以定义类似“/api/endpoint?filter=status,all”的路由,则可以使用TypeConverter:
定义一个转换器:
public class FilterConverter : TypeConverter
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
if (!(value is string)) return base.ConvertFrom(context, culture, value);
var keyValue = ((string)value).Split(',');
return new FilterParams
Filter = new Dictionary<string, string> [keyValue[0]] = keyValue[1]
;
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
使用它:
[TypeConverter(typeof(FilterConverter))]
public class FilterParams
public Dictionary<string, string> Filter get; set;
[HttpGet]
public string Get(FilterParams filter)
var filterStatus = filter.Filter["status"];
【讨论】:
不,我正在尝试遵守位于以下位置的 JSON API 标准:jsonapi.org/recommendations/#filtering @CarlSagan 添加了使用模型绑定器的替代解决方案。以上是关于dotnet core webapi json-api 兼容查询字符串路由的主要内容,如果未能解决你的问题,请参考以下文章
将 JSON 数据发布到 Dotnet Core webapi
dotnet core webapi json-api 兼容查询字符串路由
如何为 dotnet core(web Api) 代码更改以及 TypeScript 代码更改启用实时重新加载
Asp.Net Core WebAPI [dotnet publish --self-contained -r linux-64] 放入Docker容器后是不是真的自包含