2016-11-08 62 views
0

的可变数量我创建了一个GET动作控制器的API:通查询字符串参数为单控制器动作

[Route("api/xxxxx/{param1:int}/{param1:int}")] 
public IHttpActionResult Get(int param1, int param2) { 
    // method body... 
} 

的网址,将在以下格式:

/api/xxxxx/1/1?p1=5&p2=hello&p3=20161108 
/api/xxxxx/1/1?p1=active 

查询字符串参数的数量和名称将有所不同。

我想将查询字符串参数传递给控制器​​方法,但由于名称和数字不同,我无法将它们硬编码到方法签名中。有没有办法做到这一点?我尝试过拨打var qsParams = ControllerContext.Request.GetQueryNameValuePairs();,但在尝试使用查询字符串请求任何网址时,如果给出上述Route属性,则会收到资源未找到错误。

我已经想出了一个替代方案:使用路由值,而不是查询字符串参数,然后使用捕获所有{*tags},并把它作为一个方法参数:

[Route("api/xxxxx/{param1:int}/{param1:int}/{*tags}")] 
public IHttpActionResult Get(int param1, int param2, string tags) { 
    // method body... 
} 

随着格式

网址
/api/xxxxx/1/1/5/john/20161108 
/api/xxxxx/1/1/active 

这个工作,但我宁愿使用查询字符串,以便能够使用命名的键,而不是依赖于参数的排序(也使用查询字符串似乎更好的概念匹配,正在做)。

那么,如何将变量查询字符串参数传递给控制器​​操作?我说“传递”了参数,但它们不一定需要作为方法参数传递,只要我可以从方法体中访问查询字符串参数,同时获取带有查询字符串的URL以解析为有问题的行动。

编辑:

值得一提的是,每一个可能的参数集创建多个操作方法是不是一种选择。

编辑2:

我看到两个直接的解决方案,如果他们能够:

  1. 传递整个查询字符串的操作方法作为单个字符串 参数。然后我可以手动解析查询字符串。
  2. 能够在方法体内使用ControllerContext.Request.GetQueryNameValuePairs() ,而不添加相应的参数到 方法签名。

但是,我还没有想出如果这两件事情是可能的,但它似乎可能是一个或两个都可能。

回答

0

如果你想发送一个实体到你的控制器,你可以通过[FromBody] 得到它认为一个实体是最简单的方式来传递它。

F.e.

[HttpPost] 
[Route("api/xxxxx/send")] 
public void SendReuqest([FromBody] Entity name) 

希望能理解你的问题。

+0

我没有任何职位,只得到。此外,这似乎只是将问题转移到实体。也就是说,现在框架将尝试将参数映射到实体,但实体必须将参数定义为属性。因此,实体必须具有不同的名称和数量的属性才能映射到,这与以前相同,但现在尝试在实体类中寻址。顺便说一句,我没有使用实体框架。 – neizan

0

我发布了一个文档替代方案的答案我已经拿出来了。我知道一些(所有?)这些将会是hacky。尽管如此...

ANSWER
使用方法GetQueryNameValuePairs。这是我尝试的第一件事,但我必须在路由属性或方法签名中有不同的东西,因为我之前收到了“未找到”错误。但是,现在,这是完美的。这使得整个问题和答案对我来说基本没有意义。

实例网址:

/api/xxxxx/1/1?p1=5&p2=john&p3=20161108 

操作:

[Route("api/xxxxx/{param1:int}/{param1:int}")] 
public IHttpActionResult Get(int param1, int param2) { 
    var qsParams = ControllerContext.Request.GetQueryNameValuePairs(); 
    // rest of method body... 
} 

选项1
使用与控制器理解并能够解析自定义格式的单个查询字符串参数。

例URL:

/api/xxxxx/1/1?qs=p1~5|p2~john|p3~20161108 

操作:

[Route("api/xxxxx/{param1:int}/{param1:int}")] 
public IHttpActionResult Get(int param1, int param2, string qs) { 
    string[] qsParamsArray = qs.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries); 
    IDictionary<string, string> qsParams = new Dictionary<string, string>(); 
    foreach (string p in qsParamsArray) { 
     string[] kv = p.Split(new string[] { "~" }, StringSplitOptions.None); 
     if (String.IsNullOrWhiteSpace(kv[0])) { 
      return NotFound(); 
     } 
     qsParams.Add(kv[0], kv[1]); 
    } 
    // Use qsParams as desired... 
} 

选项2
把查询字符串参数中的路由,而不是查询字符串。必须依赖于参数的排序。

实例网址:

/api/xxxxx/1/1/5/john/20161108 

操作:

[Route("api/xxxxx/{param1:int}/{param1:int}/{*tags}")] 
public IHttpActionResult Get(int param1, int param2, string tags) { 
    // parse the "tags" parameter here... 
    // rest of method body... 
} 

选项3
硬代码的通用名称的可选参数的最大数量,具体为这两个名字的查询字符串参数和参数值。

实例网址:

/api/xxxxx/1/1?name1=p1&value1=5&name2=p2&value2=john&name3=p3&value3=20161108 

操作:

[Route("api/xxxxx/{param1:int}/{param1:int}")] 
public IHttpActionResult Get(
    int param1, 
    int param2, 
    string name1 = null, 
    string value1 = null, 
    string name2 = null, 
    string value2 = null, 
    string name3 = null, 
    string value3 = null, 
    string name4 = null, 
    string value4 = null, 
    ..., 
    string nameNMAX = null, 
    string valueNMAX = null 
) { 
    // method body... 
} 
相关问题