Dot character '.' в MVC Web API 2 для запроса, например api/people/STAFF.45287

URL-адрес, который я пытаюсь разрешить, - это один из вариантов: http://somedomain.com/api/people/staff.33311 (так же, как сайты, такие как LAST.FM, позволяют все виды знаков в их URL-адреса RESTFul и WebPage, например "http://www.last.fm/artist/psy'aviah" является действительным URL для LAST.FM).

В чем работают следующие сценарии: - http://somedomain.com/api/people/ - который возвращает всех людей - http://somedomain.com/api/people/staff33311 - тоже будет работать, но это не то, что я после Я бы хотел, чтобы url принимал "точку", как пример ниже - 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.

Я установил следующие вещи:

  • Контроллер "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);
    }    
    
  • 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 }
        );
    }
    

Я уже пробовал следовать всем советам этого blogpost http://www.hanselman.com/blog/ExperimentsInWackinessAllowingPercentsAnglebracketsAndOtherNaughtyThingsInTheASPNETIISRequestURL.aspx, но он все равно не сработает. Я также думаю, что это довольно утомительно, и мне интересно, не является другим, лучшим и безопасным способом.

У нас есть внутренний идентификатор внутри, так что нам нужно будет найти решение, чтобы оно соответствовало точке так или иначе, предпочтительно в стиле ".". но я открыт для альтернативных предложений для URL-адресов, если это необходимо...

Ответ 1

После установки в файле web.config следует исправить вашу проблему:

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

Ответ 2

Суффикс URL с косой чертой, например. http://somedomain.com/api/people/staff.33311/ вместо http://somedomain.com/api/people/staff.33311.

Ответ 3

Я обнаружил, что добавление следующего до стандартного 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 - fooobar.com/questions/49369/...

Ответ 4

Я не знаю, что я делаю, но, немного поиграв с предыдущим ответом, я придумал другое, возможно более подходящее решение:

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

Ответ 5

Я обнаружил, что мне нужно сделать больше, чем просто установить атрибут 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.0 имеет свой атрибут path, установленный в *, в отличие от *. (например).

Ответ 6

Я застрял в этой ситуации, но добавление / в конце URL-адреса не выглядело чистым для меня.

поэтому просто добавьте ниже в тег handlers web.config, и вам будет хорошо идти.

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

Ответ 7

Я обнаружил, что для меня работает оба способа: либо установите для параметра runAllManagedModulesForAllRequests значение true, либо добавьте ExtentionlessUrlHandler как показано ниже. Наконец, я хочу добавить расширениеUrLHandler, поскольку 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>

Ответ 8

Я столкнулся с той же проблемой и обстоятельствами, в которых я был, где я не должен был играть с настройками IIS и настройками веб-сайта. Поэтому мне пришлось заставить его работать, внося изменения только на уровне кода.

Простая точка заключается в том, что наиболее распространенным случаем, когда вы в конечном итоге должны иметь точечный символ в URL-адресе, является получение пользователем от пользователя и передача его в виде строки запроса или фрагмента url для передачи некоторого аргумента параметрам в метод действия вашего контроллера.

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

Посмотрите ниже URL, где пользователь вводит свой идентификатор пользователя, чтобы получить его личные данные:

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

Поскольку вам нужно просто извлечь некоторые данные с сервера, мы используем http GET verb. При использовании вызовов 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 verb здесь.