dotnet核心webapi json-api兼容查询字符串路由

时间:2016-11-12 10:12:34

标签: c# asp.net-web-api asp.net-web-api2 json-api .net-core

我正在尝试从请求的URL中获取“status”和“all”键值,并且无法弄清楚如何构建我的类对象。

我所指的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"];
}

2 个答案:

答案 0 :(得分:1)

  1. 您可以使用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
      }
      
  2. 如果您可以定义类似&#34; / api / endpoint?filter = status的路线,那么&#34;相反,你可以使用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"]; 
      }
      

答案 1 :(得分:1)

如果您要在.Net Core上构建json:api应用,我强烈建议您检出以下库:https://github.com/json-api-dotnet/JsonApiDotNetCore

它为您处理了所有繁重的工作,对于此特定示例,(需要获取过滤器值),解决方案如下:

ggplot(data.frame(x = c(-2, 2)), aes((x),xname ='wind') ) +
    stat_function(fun = dnorm, args = list(mean = -0.05116279, sd = 0.5725349),                                                  aes(colour = "1 hour"))  +xlab("wind_speed_Error",cex.lab=1.5, cex.axis=1.5) +
    stat_function(fun=dnorm, args = list(mean = -0.355, sd = 0.6602059),  aes(colour = "4 hour"))  +
    scale_colour_manual("Predictions",values=c("blue","red"))