在URL中使用斜杠“/”路由参数

时间:2015-06-22 05:23:28

标签: c# url asp.net-web-api asp.net-web-api-routing attributerouting

我知道您可以在路线属性中应用通配符以允许/,例如日期输入:

[Route("orders/{*orderdate}")]

通配符的问题仅适用于URI中的最后一个参数。如果要拥有以下URI,我该如何解决问题:

[Route("orders/{orderdate}/customers")]

更新

我知道通过重构代码来解决问题的选择很少,所以请不要提供类似的解决方案:

  1. 将路线模板更改为[Route("orders/customers/{orderdate}")]
  2. 将日期更改为其他格式(例如"dd-mm-yyyy"

4 个答案:

答案 0 :(得分:26)

@bet ..我认为genericUriParserOptions不再适用于.net 4.5或更高版本..

也正如@JotaBe所建议的那样,您可能需要正确解码网址请求。在大多数情况下,%2F将自动转换为斜杠' /'所以如果你需要逃避它,你需要解码'%' char首先..所以你的网址:看起来像:www.domain.com/api/orders/23%252F06%252F2015/customers

注意字符'%252F'将被翻译为实际的'%2F'

修改

好的,这是完整的解决方案(试过并为我工作):

  1. 假设你有一个像这样的API端点:

    [Route("orders/{date}/customers")]
    public HttpResponseMessage Get(string date)
    {
    }
    
  2. 在web.config中,您需要将requestPathInvalidCharacters设置为empty,告诉asp.net允许所有请求

    <system.web>
        <httpRuntime targetFramework="4.5" requestPathInvalidCharacters=""/>                
    </system.web>
    <system.webServer>
        <security>
          <requestFiltering allowDoubleEscaping="true" />
        </security>
    </system.webServer>
    
  3. 当客户向API发送请求时,您需要确保逃避&#39;%&#39;像这样:

    www.domain.com/api/orders/23%252F06%252F2015/customers

  4. 然后您需要解码请求

    [Route("orders/{date}/customers")]
    public HttpResponseMessage Get(string date)
    {
            DateTime actualDate = DateTime.Parse(System.Net.WebUtility.UrlDecode(date)); // date is 23/06/2015
    }
    

答案 1 :(得分:7)

如@AlexeiLevenkov的评论所述,这是错误的:

  

您不能在URL中有一个接受正斜杠的参数,因为这是一个分隔每个URL片段的特殊符号。因此,每当您在URL中包含此符号时,都会有新的片段,并且单个参数不能包含多个片段。

如果您想了解更多详情read this,但这些是最相关的摘录:

  • 网址路径在网址中找到的第一个?#中完成。因此,斜杠只会在出现之前的URL路径部分或其中一个符号中创建片段。
  • 从3.4节开始:查询组件由第一个问号(“?”)字符表示,并以数字符号(“#”)字符或URI末尾结束。

因此,如果需要,查询字符串可以包含正斜杠/,并且它们根本不会定义路径段。

这些是这个问题的一些解决方案:

  • 包括日,月和年的片段,如下所示:[Route("orders/{month}/{day}/{year}/customers")]然后在服务器端创建日期
  • 要求用户使用不同的分隔符,如破折号或点,这不会产生问题,以字符串形式接收它并自行解析(或使用您自己的自定义活页夹来支持该格式)
  • 在到达路由系统之前使用URL Rewrite extension更改URL,并按照上一个解决方案中的说明解析它(这需要在IIS中托管)
  • 将其作为查询字符串接收,例如:'?date = 02/03 / 2015'(您最好对其进行编码)

注意:您的原始问题是“查询字符串”,我对编码的评论是指查询字符串,它是问号后面的最后一段(如果存在)like &id=27。我更正了你的问题,所以它没有提到“查询字符串”,这不是你需要的正确名称

答案 2 :(得分:1)

您可以使用以下URI [Route("orders/{DD:int}/{MM:int}/{YY:int}}/customers")] 然后使用自定义模型绑定器获取DD/MM/YY并将它们转换为您可以在操作方法中绑定的日期。

您可以选择处理约束的方式(更严格地使用正则表达式)或使用验证并返回400,如果它不匹配。

更简单的方法是采用Day/Month/Year并将其放在代码中。

以下是dealing with modelbinding的链接。

答案 3 :(得分:0)

C#有自己的方法,它跳过转义序列的规则 方法的名称是 Uri.UnescapeDataString(您的查询字符串参数 您可以在获取参数值的同时使用它