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容器后是不是真的自包含

使用 xunit 在 webapi 应用程序上运行 dotnet 测试

dotnet core docker web api没有连接