C# 符合dotnet core webapi json api的查询字符串路由

C# 符合dotnet core webapi json api的查询字符串路由,c#,asp.net-web-api,asp.net-web-api2,json-api,.net-core,C#,Asp.net Web Api,Asp.net Web Api2,Json Api,.net Core,我试图从请求的URL中获取“status”和“all”键、值,但无法确定如何构建我的类对象 我所指的JSON API规范可以在这里找到: //请求的url /api/端点?过滤器[状态]=全部 //我对模型绑定的尝试 公共类筛选器参数 { 公共字典筛选器{get;set;} } [HttpGet] 公共字符串Get([FromUri]FilterParams筛选器) { //永远不会有人居住。。。 var filterStatus=filter.filter[“状态”]; } 您可以使用:

我试图从请求的URL中获取“status”和“all”键、值,但无法确定如何构建我的类对象

我所指的JSON API规范可以在这里找到:

//请求的url
/api/端点?过滤器[状态]=全部
//我对模型绑定的尝试
公共类筛选器参数
{
公共字典筛选器{get;set;}
}
[HttpGet]
公共字符串Get([FromUri]FilterParams筛选器)
{
//永远不会有人居住。。。
var filterStatus=filter.filter[“状态”];
}
  • 您可以使用:

    • 定义模型绑定器:

      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;
          }
      }
      
  • 如果可以定义“/api/endpoint?filter=status,all”这样的路由,则可以使用:

    • 定义转换器:

      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);
          }            
      }
      
      公共类过滤器转换器:类型转换器
      {
      公共重写对象ConvertFrom(ITypeDescriptorContext上下文、CultureInfo区域性、对象值)
      {
      if(!(值为字符串))返回base.ConvertFrom(上下文、区域性、值);
      var keyValue=((字符串)值).Split(',');
      返回新的FilterParams
      {
      筛选器=新字典{[keyValue[0]]=keyValue[1]}
      };
      }
      公共覆盖布尔CanConvertFrom(ITypeScriptorContext上下文,类型sourceType)
      {
      return sourceType==typeof(string)| | base.CanConvertFrom(context,sourceType);
      }            
      }
      
    • 使用它:

      [HttpGet]
      public string Get([ModelBinderAttribute(typeof(FilterParamsModelBinder))] FilterParams filter)
      {
        //your code
      }
      
      [TypeConverter(typeof(FilterConverter))]
      public class FilterParams
      {
          public Dictionary<string, string> Filter { get; set; }
      }
      
      [HttpGet]
      public string Get(FilterParams filter)
      {
          var filterStatus = filter.Filter["status"]; 
      }
      
      [TypeConverter(typeof(FilterConverter))]
      公共类筛选器参数
      {
      公共字典筛选器{get;set;}
      }
      [HttpGet]
      公共字符串获取(FilterParams筛选器)
      {
      var filterStatus=filter.filter[“状态”];
      }
      

  • 如果您正在.Net Core上构建json:api应用程序,我强烈建议您查看以下库:

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

    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");
            // ...
        }
    }
    
    公共FooController:JSONAPicController{
    专用只读IQueryAccessor _queryAccessor;
    公共FooController(IQueryAccessor查询加载器,/*…*/)
    :base(/*…*/){
    _queryAccessor=queryAccessor;
    }
    [HttpGet]
    公共重写异步任务GetAsync(){
    var状态=_queryAccessor.GetRequired(“状态”);
    // ...
    }
    }
    
    No,我正在尝试遵守JSON API标准:@CarlSagan添加了一个使用model binder的替代解决方案。
    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");
            // ...
        }
    }