Символ точки "." у MVC Web API 2 для запиту, наприклад api / people / STAFF.45287


106

URL-адреса, яку я намагаюся дозволити працювати, є такою у стилі: http://somedomain.com/api/people/staff.33311 (так само, як сайти як LAST.FM дозволяють усілякі знаки у своїх RESTFul & WebPage URL-адресах , наприклад, " 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.

Я створив такі речі:

  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/ExperimentInWackinessAllowingPercentsAnglebracketsAndOtherNaughtyThingsInTheASPNETIISRequestURL.aspx, але він все ще не буде працювати .. Я також думаю, що це досить втомливо, і мені цікаво, чи немає іншого, кращий і безпечніший спосіб.

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


10
Не відповідь, але чому ви отримуєте 404 для somedomain.com/api/people/staff.33311 - за замовчуванням IIS дивиться цю URL-адресу і бачить. як розширення файлу і викликає статичний обробник файлів, минаючи API MVC. Відповідь, яку ви прийняли (запускаючи всі керовані модулі для всіх запитів), працює тому, що ви змушуєте кожен запит до IIS пройти через конвеєр ASP.NET (отже, ваші контролери)
Генрі С

Тісно пов'язані з постом тут .
RBT

Відповіді:


104

Наступне налаштування у вашому web.configфайлі має вирішити вашу проблему:

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

4
Це зробило трюк. Хоча, чи є вразливості, встановивши цю опцію? Чому це не стандартна поведінка?
Ів Шельпе

2
Добре, для чийого інтересу: я бачу моє запитання вище бути тут відповідь на загальноприйнятому відповідь на момент написання (відповідь по Капіл Ханделвал): stackoverflow.com/questions/11048863 / ...
Ів Schelpe

2
Так, це спрацювало, автобус інших, я хотів би знати, який саме модуль потрібен, щоб ця функціональність працювала?
Грег З.

3
Коли я спробував це, це спрацювало б лише в тому випадку, якщо я поставив '/' в кінці шляху. Будь-які пропозиції, чому це? З іншого боку, відповідь нижче, що спеціально додає 'UrlRoutingModule' замість запуску всіх модулів, також працював для мене, хоча все ще з проблемою, що для завершення роботи потрібен '/'.
Микола Дам Ларсен

10
stackoverflow.com/a/12151501/167018 варто переглянути, якщо ви стурбовані (і це справедливо) про вплив на ефективність включення runAllManagedModulesForAllRequests.
Генріх С

140

Додайте URL-адресу з косою рисою, наприклад, http://somedomain.com/api/people/staff.33311/замість http://somedomain.com/api/people/staff.33311.


3
@AgustinMeriles мою відповідь можна вважати скоріше вирішенням, ніж реальною відповіддю, залежить від вашого тлумачення питання.
Денні Варод

5
Це не працює, хоча точка знаходиться в кінці розділу URL, як в / люди / член.
eYe

2
Ні, що робити, якщо я не хочу в кінці косої риски ?! Це не повинно вимагати.
Джош М.

1
@JoshM. Це вирішення, я не писав ASP.NET. Також коса риса не впливає на запит. Це, однак, допоможе зробити ваші наміри більш ясно , як і в google.com/my query goes here/VS. google.com/subDomain my query goes here.
Денні Варод

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


Я додав його "після" до стандартної лінії, і він також чудово працював.
Джалал Ель-Шейр

Це має бути прийнятою відповіддю. Не вимагає / наприкінці uri
daudihus

2
Дякуємо ЗА ПЕРЕД, адже це не спрацювало після!
Месьє

Я вважаю, що модулі працюють у порядку декларування, тому завжди ставте більш конкретні (або більш важливі) модулі перед більш загальними.
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, принаймні, У НАВІДКІ
James Manning

1
Це не переїзд до кінця списку, це вилучення умовою за замовчуванням, яку цей модуль запускає лише для керованих обробників. Конфігурація за замовчуванням використовує такий формат:<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler" />
theta-fish

Спасибі - це пояснило б поведінку.
Грег З.

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.0has pathвстановлений на *відміну від *.(наприклад).


Мене просто покусали path="*.". Просто цікаво, з якої причини це ставлять люди path="*."?
JustinP8

Насправді я змінив це path="*"і виникло проблема, оскільки ми розміщуємо сайт документації поряд з нашим WebAPI, і на цьому веб-сайті виникли проблеми з .jpg, .png та іншими файлами з розширеннями.
JustinP8

@ JustinP8 Ви також встановили <modules runAllManagedModulesForAllRequests="true" />? Це повинно змусити .NET обробляти ці статичні файли.
Джош М.

1
Так. Я завершив це. Мені це не дуже подобається, тому що зараз всі статичні файли проходять через .NET трубопровід. На щастя, оскільки це сервіс webAPI, це стосується лише речей Swagger і Swashbuckle для веб-сайту Документів API / помічників.
JustinP8

Я виявив, що це порушило всі запити статичних файлів. помилка 500. У мене був runAllManaged ... встановлено значення true.
Сем

2

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

тому просто додайте нижче в тег web.config, handlers і вам буде добре піти.

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

Чи можете ви пояснити, що таке Ненсі і чи варто бібліотеку включати в проект? Дякую!
синюватий

1

Я виявив, що обидва способи для мене працюють: або встановіть runAllManagedModulesForAllRequests на істинне, або додайте 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-адреси, щоб передавати якийсь аргумент параметрам у методі дії вашого контролера.

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

Подивіться нижче URL-адресу, де користувач вводить свій ідентифікатор користувача, щоб отримати його особисті дані:

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

Оскільки вам потрібно просто отримати деякі дані з сервера, ми використовуємо http GETverb. Під час використання GETдзвінків будь-які вхідні параметри можуть передаватися лише у фрагментах URL-адреси.

Тому, щоб вирішити свою проблему, я змінив http дієслова своєї дії на POST. POSTДієслово Http також має можливість передавати будь-якому користувачеві чи некористувацькі дані. Тому я створив дані JSON і передав їх у тіло http POSTзапиту:

{
  "userid" : "foo.bar"
}

Змініть визначення методу, як показано нижче:

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

Примітка . Детальніше про те, коли використовувати GETдієслово та коли використовувати POSTдієслово тут .


Не підходяще рішення, якщо ви будуєте API REST.
Мустафа Озтурк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.