点字符“。” 在MVC Web API 2中进行请求,例如api / people / STAFF.45287


106

我尝试使用的URL是以下格式的URL:http : //somedomain.com/api/people/staff.33311(就像LAST.FM的站点允许其RESTFul和WebPage url中包含各种符号一样,例如“ http://www.last.fm/artist/psy'aviah ”是LAST.FM的有效网址)。

在以下情况下有效:-http: //somedomain.com/api/people/-返回所有人-http: //somedomain.com/api/people/staff33311-也可以使用,但不是我所需要的我希望网址接受一个“点”之后的m,例如下面的示例-http: //somedomain.com/api/people/staff.33311-但这给了我一个

HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.

我已经设置了以下内容:

  1. 控制器“ PeopleController”

    public IEnumerable<Person> GetAllPeople()
    {
        return _people;
    }
    
    public IHttpActionResult GetPerson(string id)
    {
        var person = _people.FirstOrDefault(p => p.Id.ToLower().Equals(id.ToLower()));
        if (person == null)
            return NotFound();
    
        return Ok(person);
    }    
  2. WebApiConfig.cs

    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
    
        // Web API routes
        config.MapHttpAttributeRoutes();
    
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }

我已经尝试按照该博客文章的所有提示进行操作,网址为http://www.hanselman.com/blog/ExperimentsInWackinessAllowingPercentsAnglebracketsAndOtherNaughtyThingsInTheASPNETIISRequestURL.aspx,但仍然无法使用。更好,更安全的方式。

我们的ID在内部是这样的,因此我们将不得不找到一种解决方案,以一种或另一种方式来匹配点,最好采用“”样式。但如果需要的话,我愿意接受有关网址的替代建议...


10
不是答案,而是关于为什么为什么要获得somedomain.com/api/people/staff.33311的404- 默认情况下,IIS会查看此URL并看到。作为文件扩展名,并绕过您的MVC API调用静态文件处理程序。您接受的答案(针对所有请求运行所有托管模块)之所以起作用,是因为您迫使对IIS的每个请求都要通过ASP.NET管道(因此,是您的控制器)
Henry C

密切相关的帖子在这里
RBT

Answers:


104

web.config文件中进行以下设置应该可以解决您的问题:

<configuration>
    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true" />

4
它成功了。但是,通过设置此选项是否存在任何漏洞?为什么这不是标准行为?
Yves Schelpe 2014年

2
好了,任何人的兴趣:我看到我上面正在此间回答了公认的答案。在写本(答案由卡皮尔Khandelwal)在时间上的问题:stackoverflow.com/questions/11048863/...
伊夫Schelpe

2
是的,它起作用了,其他总线,我想知道该功能需要哪个特定的模块?
Greg Z.

3
当我尝试此操作时,只有在路径的末尾添加“ /”,它才会起作用。有什么建议为什么呢?附带说明一下,下面的答案专门添加了“ UrlRoutingModule”而不是运行所有模块,这对我也有用,尽管仍然存在最后需要“ /”才能工作的问题。
Nikolaj Dam Larsen 2014年

10
stackoverflow.com/a/12151501/167018是值得看的,如果你担心(这是理所当然的)有关启用runAllManagedModulesForAllRequests对性能的影响。
亨利C

140

后缀以斜线例如URL http://somedomain.com/api/people/staff.33311/代替http://somedomain.com/api/people/staff.33311


3
@AgustinMeriles可以将我的答案视为一种替代方法,而不是实际答案,这取决于您对问题的解释。
丹尼·瓦罗德

5
但是,当点位于/ people / member中时,该点在URL部分的末尾是不起作用的。
eYe 2015年

2
不,如果我不希望最后一个斜杠怎么办?它不是必需的。
Josh M.

1
@JoshM。这是一种解决方法,我没有编写ASP.NET。同样,斜杠不会影响请求。它,然而,帮助让你的意图,如更清晰google.com/my query goes here/对比google.com/subDomain my query goes here
Danny Varod '16

1
是的,这是最好的方法,您无需修改​​web.config。
蒂莫西·冈萨雷斯

35

我发现在标准之前添加以下内容可以为我解决问题:ExtensionlessUrlHandler

<add name="ExtensionlessUrlHandler-Integrated-4.0-ForApi"
     path="api/*"
     verb="*"
     type="System.Web.Handlers.TransferRequestHandler"
     preCondition="integratedMode,runtimeVersionv4.0" />

我认为名称实际上并没有那么重要,除非您的IDE(在我的情况下为Visual Studio)正在管理您的站点配置,这可能会有所帮助。

H / T到https://stackoverflow.com/a/15802305/264628


我在标准线“之后”添加了它,并且效果也不错。
Jalal El-Shaer

这应该是公认的答案。不需要/在uri结束时
daudihus 17-4-3

2
在此之前,感谢您的支持,因为它在之后无法正常工作!
Mese

我相信模块按声明的顺序运行,因此始终将更具体(或更重要)的模块放在更通用的模块之前。
BrianS

24

我不知道我实际上在做什么,但是在听了前面的答案之后,我想出了另一个也许更合适的解决方案:

<system.webServer>
<modules>
    <remove name="UrlRoutingModule-4.0" />
    <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
</modules>
</system.webServer>

谢谢,我也不知道它在做什么,但是看起来比其他解决方案好。
托马斯

1
似乎将url路由模块(正在捕获请求包含扩展名,然后尝试将其作为文件处理)移动到模块列表的末尾,这足以将其放在处理api请求的模块之后。恕我直言,这是我在SO上看到的最好的解决方法,至少是ATTOW
James Manning

1
这不是重定位到列表的末尾,而是删除了该模块仅针对托管处理程序运行的默认前提条件。默认配置使用以下格式:<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler" />
theta-fish

谢谢-这将解释行为。
Greg Z.

8

我发现我需要做的不仅仅是将runAllManagedModulesForAllRequests属性设置为true。我还必须确保将无扩展名URL处理程序配置为查看所有路径。此外,您还可以添加一个额外的奖励配置设置,在某些情况下会有所帮助。这是我的工作Web.config:

<system.web>
    <httpRuntime relaxedUrlToFileSystemMapping="true" />
</system.web>
<system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <handlers>
        <remove name="WebDAV" />
        <remove name="OPTIONSVerbHandler" />
        <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
        <add name="ExtensionlessUrlHandler-Integrated-4.0"  path="*" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
</system.webServer>

请特别注意,ExtensionlessUrlHandler-Integrated-4.0path属性设置*为而不是*.(例如)。


我只是被咬住了path="*."。只是好奇,人们将其设置为什么原因path="*."
JustinP8 '16

实际上,我将其更改为path="*"并出现了问题,因为我们与WebAPI并排托管了一个文档站点,并且该站点的.jpg,.png和其他带有扩展名的文件存在问题。
JustinP8 '16

@ JustinP8您还设置了<modules runAllManagedModulesForAllRequests="true" />吗?那应该使.NET处理那些静态文件。
Josh M.

1
是。我结束了。我不是很喜欢,因为现在所有静态文件都通过.NET管道。幸运的是,由于这是一个webAPI服务,因此仅影响API docs / helper网站的Swagger和Swashbuckle内容。
JustinP8 '16

我发现这破坏了所有静态文件请求。错误500。我将runAllManaged ...设置为true。
山姆

2

我陷入了这种情况,但是/ 在URL末尾添加对我来说看起来并不干净。

因此,只需在web.config handlers标记中添加以下内容,就可以了。

<add name="Nancy" path="api" verb="*" type="Nancy.Hosting.Aspnet.NancyHttpRequestHandler" allowPathInfo="true" />

您能否解释一下Nancy是什么,以及它是否要包含在项目中的图书馆?谢谢!
蓝色

1

我发现这两种方式都对我有用:将runAllManagedModulesForAllRequests设置为true或添加ExtentionlessUrlHandler如下所示。最后,我选择添加extensionUrLHandler,因为runAllManagedModulesForAllRequests确实会对站点产生性能影响。

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <remove name="WebDAV" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*" verb="*" 
       type="System.Web.Handlers.TransferRequestHandler" 
       preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

1

我会在Web.config文件中使用它:

<add name="ManagedSpecialNames" path="api/people/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

在标准“ ExtensionlessUrlHandler”之前。

例如,在我的情况下,我将其放在此处:

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <add name="ManagedFiles" path="api/people/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

因此,您可以强制由您管理此类模式的URL,而不是将标准管理作为应用程序目录树中的文件进行管理。


0

我遇到了同样的问题,而且我所处的环境不适合我使用IIS和与网站配置相关的设置。因此,我只能通过在代码级别进行更改来使其正常工作。

很简单,最常见的情况是您最终从URL中获得点字符,是当您从用户那里获得一些输入并将其作为查询字符串或url片段传递时,将一些参数传递给action方法中的参数您的控制器。

public class GetuserdetailsbyuseridController : ApiController
{
     string getuserdetailsbyuserid(string userId)
     {
        //some code to get user details
     }
}

在用户输入其用户ID以获得其个人详细信息的URL下方查看:

http://mywebsite:8080/getuserdetailsbyuserid/foo.bar

由于您只需从服务器获取一些数据,因此我们使用http GET动词。在使用GET调用时,任何输入参数只能在URL片段中传递。

因此,为了解决我的问题,我将操作的http动词更改为POST。Http POST动词还可以在正文中传递任何用户或非用户输入的功能。因此,我创建了一个JSON数据并将其传递到http POST请求的正文中:

{
  "userid" : "foo.bar"
}

如下更改方法定义:

public class GetuserdetailsbyuseridController : ApiController
{
     [Post]
     string getuserdetailsbyuserid([FromBody] string userId)
     {
        //some code to get user details
     }
}

注意:更多关于何时使用GET动词以及何时使用POST动词的信息


如果要构建REST API,则不合适的解决方案。
Mustafa Ozturk
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.