Точки в URL-адресі викликають 404 за допомогою ASP.NET mvc та IIS


303

У мене є проект, який вимагає, щоб мої URL-адреси мали точки на шляху. Наприклад, у мене може бути така URL-адреса, як www.example.com/people/michael.phelps

URL-адреси з крапкою генерують 404. Моя маршрутизація нормальна. Якщо я проходжу в michaelphelps, без крапки, то все працює. Якщо додати крапку, я отримаю помилку 404. Зразок сайту працює на Windows 7 за допомогою IIS8 Express. URLScan не працює.

Я спробував додати наступне до своєї web.config:

<security>
  <requestFiltering allowDoubleEscaping="true"/>
</security>

На жаль, це не змінило значення. Я щойно отримую помилку 404.0 Not Found.

Це проект MVC4, але я не думаю, що це актуально. Моя маршрутизація працює добре, і параметри, які я очікую, є, поки вони не включають крапку.

Що мені потрібно налаштувати, щоб у моїй URL-адресі були точки?


93
Не можу повірити, що я витратив стільки часу на цей. URL-адреса працює добре, якщо я додаю косу рису. Наприклад, www.example.com/people/michael.phelps/ однак без останньої косої коси IIS видає помилку 404.
Марк

15
Позначити - це тому, що без останньої косої риси IIS вважає, що це файл, який він повинен перейти і знайти. Додавання косої риси призводить до ... це не справжній файл. Крім того, параметр конфігурації, наведений нижче, повідомляє IIS, що якщо це не файл, спробуйте його направити.
Томмі

У мене виникає така ж проблема, коли я оновив проект на mvc 4 + asp.net 4.5.
Tadeu Maia

Як обхід, я використовую IIS Rewrite, щоб додати косую косу рису до своїх URL-адрес.
Марк

4
Це не працює для мене. URL-адреса працює з "." в URL-адресі, але коли він знаходиться в самому кінці, він дає помилку
Аркадян

Відповіді:


379

Я працював над цим, редагуючи HTTP-обробники мого сайту. Для моїх потреб це добре працює і вирішує мою проблему.

Я просто додав новий обробник HTTP, який шукає конкретні критерії шляху. Якщо запит збігається, він правильно відправляється в .NET для обробки. Я набагато щасливіше з цим рішенням, що хакер URLRewrite або включення RAMMFAR.

Наприклад, щоб .NET обробив URL-адресу www.example.com/people/michael.phelps, додайте наступний рядок до веб-сайту web.config вашого system.webServer / handlersелемента в межах елемента:

<add name="ApiURIs-ISAPI-Integrated-4.0"
     path="/people/*"
     verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
     type="System.Web.Handlers.TransferRequestHandler"
     preCondition="integratedMode,runtimeVersionv4.0" />

Редагувати

Є й інші повідомлення, що дозволяють вирішити це питання RAMMFARабо RunAllManagedModulesForAllRequests. Якщо ввімкнути цю опцію, ви зможете використовувати всі керовані модулі для всіх запитів. Це означає, що статичні файли, такі як зображення, PDF-файли та все інше, будуть оброблятися .NET, коли вони цього не потребують. Цей варіант найкраще припинити, якщо у вас немає конкретного випадку.


3
ось повний приклад stackoverflow.com/a/16607685/801189 на основі цієї відповіді
VB

10
після додавання цього за допомогою [path = "*"] всіх запитів до будь-яких статичних файлів, таких як .css, .js. У мене є власний маршрут, який обробляє URL-адреси, схожі на цей " домен / ABCDE.FGHIJ ". Всі мої статичні файли знаходяться в моєму каталозі / Вміст. Чи є спосіб виключити з цього весь каталог? встановлення RAMMFAR на справжні роботи, але я хотів би уникнути цих витрат.
ламаран

2
Локальний IIS працює з початковою косою рисою, але IIS8 розуміє маршрут лише без першого косого кута.
Павло Воронін

2
У мене така ж проблема, як і @lamarant ... Він блокує статичні файли. Ти знаєш чому? Використовуючи MVC4 тут.
eestein

3
Вона працює в MVC5, але якщо ви ставите косу рису на початку шляху, вона працює лише тоді, коли шлях знаходиться відразу після імені хоста (це не стосується папки додатків). Наприклад, path / people / * буде працювати для www.example.com/people/michael.phelps, але не для www.example.com/app/people/michael.phelps. AFAIK немає способу зробити шлях відносно додатка.
Хоган

46

Після деякого роздуму я виявив, що розслабленийUrlToFileSystemMapping для мене зовсім не працює, те, що працювало в моєму випадку, було встановити RAMMFAR на істинне, те саме стосується (.net 4.0 + mvc3) і (.net 4.5 + mvc4).

<system.webserver>
    <modules runAllManagedModulesForAllRequests="true">

Будьте в курсі, встановлюючи RAMMFAR справжній пост Hanselman про RAMMFAR та продуктивність


5
Будьте в курсі під час встановлення RAMMFAR ... Чи є якісь втрати продуктивності, якщо я використовую це <модулі runAllManagedModulesForAllRequests = "true">
Shanker Paudel,

1
Що стосується оригінального плаката, він не повинен бути потрібним, оскільки він використовує IIS7 і вище. Там він за замовчуванням, і встановлення RAMMFAR дійсно коштує ваших екстатів. Дивіться msdn.microsoft.com/en-us/library/…
Річард

Хоча це корисно, цього було недостатньо, щоб отримати періоди, щоб зупинити повернення 404s у MVC5 / IIS7 для мене.
Кріс Москіні

Просто щоб повторити. Хочете уникнути включення цієї опції
страйк

Не робіть цього на реальному веб-сайті, хоча це можливо.
NickG

27

Я вважаю, що ви повинні встановити властивість relaxUrlToFileSystemMapping у своєму web.config. Haack написав статтю про це трохи раніше тому (і є деякі інші публікації SO, які задають однакові запитання)

<system.web>
<httpRuntime relaxedUrlToFileSystemMapping="true" />

Редагувати З коментарів нижче, пізніші версії .NET / IIS можуть вимагати, щоб це було в system.WebServerелементі.

<system.webServer>
<httpRuntime relaxedUrlToFileSystemMapping="true" />

2
Це те, що у мене було з mvc3 + .net4.0 і прекрасно працював, але більше не працюю з mvc4 + .net4.5.
Тадеу Майя

4
Я безрезультатно спробував розслабленуUrlToFileSystemMapping. Я не думаю, що це працює з новітніми версіями MVC.
Марк

Це дозволило мені зафіксувати URL /WEB-INF./web.xml і перенаправити його на користувацьку сторінку помилок, коли дуже багато інших способів, які я намагався, не працювали.
квентин-зірин

3
Цікаво. Враховуючи, що це не працювало для вас, я збирався припустити, що це не спрацює для мене ... враховуючи, що я перебуваю на MVC4 з .NET4.5. Але бінго, це все одно спрацювало. У моєму випадку я просто мав URL-адресу з періодом ". як останній персонаж. Я отримував 404, але це виправило.
PandaWood

Чи має його захисні наслідки?
Paesano2000

23

Я довго зациклювався на цьому питанні, дотримуючись усіх різних засобів безрезультатно.

Я зауважив, що додаючи прорізну косу риску [/] до кінця URL-адреси, що містить крапки [.], Вона не викинула помилку 404 і вона фактично спрацювала.

Нарешті я вирішив проблему, використовуючи переписувач URL-адрес, як IIS Rewrite URL-адреси, щоб слідкувати за певним шаблоном і додавати тренувальну косу рису.

Моя URL-адреса виглядає приблизно так: /Contact/~firstname.lastname, тому мій шаблон просто: /Contact/~(.*........

Цю ідею я отримав від Скотта Форсайта, дивіться посилання нижче: http://weblogs.asp.net/owscott/handing-mvc-paths-with-dots-in-the-path


Це працювало для мене (MVC5). Інші запропоновані вище пропозиції не спрацювали, і не були потрібні, а лише косою косою рисою. Я зміню свої маршрути, як запропонував @ jonduncan05 тут .
markau

Дякую, Леон. Врятував день для мене. Не впевнений про всі речі web.config, про які люди тут розмовляють, але додавання останнього / було потрібною відповіддю. У моєму випадку я маю контроль над контролером на стороні сервера та javascript, який його викликав, тому я просто оновив JavaScript і voila!
Жаба Pr1nce

21

Просто додайте цей розділ до Web.config, і всі запити до маршруту / {* pathInfo} буде оброблятися вказаним обробником, навіть якщо в pathInfo є точки. (взято з прикладу ServiceStack MVC Host Web.config і ця відповідь https://stackoverflow.com/a/12151501/801189 )

Це має працювати для обох IIS 6 та 7. Ви можете призначити конкретні обробники різним шляхам після 'route', змінивши path = "*" в елементах "add".

  <location path="route">
    <system.web>
      <httpHandlers>
        <add path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" />
      </httpHandlers>
    </system.web>
    <!-- Required for IIS 7.0 -->
    <system.webServer>
      <modules runAllManagedModulesForAllRequests="true" />
      <validation validateIntegratedModeConfiguration="false" />
      <handlers>
        <add name="ApiURIs-ISAPI-Integrated-4.0" path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" preCondition="integratedMode,runtimeVersionv4.0" />
      </handlers>
    </system.webServer>
  </location>

2
Остерігайтесь наслідків для продуктивності runAllManagedModulesForAllRequests (RAMMFAR). Це дозволить використовувати всі керовані модулі для кожного запиту. Статичні файли, такі як зображення, можуть бути оброблені IIS безпосередньо, але це обробляє їх через кожен модуль, додаючи накладні витрати до кожного запиту.
Марк

@MarkS. так, але я вважаю, що це вплине лише на запит на маршрут / ..., якщо ми будемо використовувати розділ <location> і не встановити runAllManagedModulesForAllRequests в головному розділі <system.webServer>.
VB

@VB Я думаю, що достатньо лише обробника, якщо у вас немає файлів у системі, які відповідають URL, який повинен обробити .NET. І чомусь RAMMFAR не працював на рівні <місцезнаходження>, але рішення обробника зробило.
webXL

@webXL <місцезнаходження>, необхідний, коли ви не хочете, щоб MVC обробляв запити до вказаного маршруту та додавав маршрути.IgnoreRoute ("route / {* pathInfo}"); Тоді IIS загляне в розділ розташування <location path = "route"> і використовуватиме вказані обробники в розділі розташування, але він повністю обійде маршрутизацію MVC та інші кроки конвеєра MVC. У моєму проекті ServiceStack api просто не працює без цього налаштування.
VB

Чому просто не додати роботу обробника? У моєму випадку я повинен додати RAMMFAR разом з обробником. Шукаєте тут хорошого пояснення. :)
Aditya Patil

6

Обхід MVC 5.0.

Багато з запропонованих відповідей, схоже, не працюють у MVC 5.0.

Оскільки проблему з 404 крапками в останньому розділі можна вирішити, закривши цей розділ косою косою рисою, ось маленький трюк, який я використовую, чистий і простий.

Зберігаючи у своєму розпорядженні зручним заповнювачем місця:

@Html.ActionLink("Change your Town", "Manage", "GeoData", new { id = User.Identity.Name }, null)

додайте трохи jquery / javascript, щоб виконати роботу:

<script>
    $('a:contains("Change your Town")').on("click", function (event) {
        event.preventDefault();
        window.location.href = '@Url.Action("Manage", "GeoData", new { id = User.Identity.Name })' + "/";
    });</script>

зверніть увагу на проділ, який відповідає за зміни

http://localhost:51003/GeoData/Manage/user@foo.com

в

http://localhost:51003/GeoData/Manage/user@foo.com/

5

Суперпроста відповідь для тих, хто має це лише на одній веб-сторінці. Відредагуйте посилання дій та позначку "/" на кінці.

  @Html.ActionLink("Edit", "Edit", new { id = item.name + "/" }) |

Вирішили це за мене! Просто і елегантно! Найбільше дратує те, що він працює без '/' в Windows 10 під час розробки, але для Windows 2012, здається, це потрібно.
Вім десять Бринк

2

Можливо, ви захочете подумати про використання тире замість періодів.

У Pro ASP MVC 3 Framework вони пропонують це щодо створення дружніх URL-адрес:

Уникайте символів, кодів та послідовностей символів. Якщо ви хочете розділити слово, використовуйте тире (/ my-great-article). Підкреслення недружні, а пробіли з кодовою URL-адресою є химерними (/ моя + велика + стаття) або огидними (/ мій% 20 зелений% 20сторінок).

Він також зазначає, що URL-адреси повинні бути зручними для читання та зміни для людей. Можливо, причина думати про використання тире замість крапки також є з тієї ж книги:

Не використовуйте розширення імен файлів для сторінок HTML (.aspx або .mvc), але використовуйте їх для спеціалізованих типів файлів (.jpg, .pdf, .zip тощо). Веб-браузери не цікавляться розширеннями імен файлів, якщо правильно встановити тип MIME, але люди все одно очікують, що файли PDF закінчуються .pdf

Отже, хоча період ще читається людям (хоча і менш читабельним, ніж тире, ІМО), він все ще може бути трохи заплутаним / оманливим залежно від того, що настає після періоду. Що робити, якщо хтось має прізвище zip? Тоді URL буде /John.zip замість / John-zip, що може ввести в оману навіть для розробника, який написав заявку.


Ймовірно, ім’я користувача або інше поле, яке по суті містить крапки. При цьому StackOverflow замінює всі пунктуації (включаючи .) тире в своїх URL-
адресах

Я зіткнувся з цим, тому що у мене є безпечна служба пошуку файлів, яка, очевидно, містить імена файлів у параметрі маршруту ...
FlavorScape

Захищений з зрозумілої причини: це не відповідає на питання. Якби я міг, я не дозволяв би періодам відображатися в моїй URL-адресі. Вони з'являються, тому що URL-адреса генерується і має бути читаною людиною.
mg30rg

2

Залежно від того, наскільки важливо для вас зберігати URI без запитів, ви також можете просто передати значення з крапками у складі запиту, а не URI.

Наприклад, www.example.com/people?name=michael.phelps працюватиме, не змінюючи жодних налаштувань і нічого.

Ви втрачаєте елегантність чистого URI, але це рішення не потребує зміни або додавання будь-яких налаштувань або обробників.


1

Чи можна було б змінити структуру URL-адреси?
Для чого я працював, я спробував маршрут

url: "Download/{fileName}"

але це не вдалося ні з чим, що мало. у цьому.

Я переключив маршрут на

    routes.MapRoute(
        name: "Download",
        url:  "{fileName}/Download",
        defaults: new { controller = "Home", action = "Download", }
    );

Тепер я можу поставити, localhost:xxxxx/File1.doc/Downloadі це прекрасно працює.

Мої помічники у погляді також підхопили на ньому

     @Html.ActionLink("click here", "Download", new { fileName = "File1.doc"})

що також робить посилання на localhost:xxxxx/File1.doc/Downloadформат.

Можливо, ви можете поставити непотрібне слово типу "/ view" або дію в кінці маршруту, щоб ваш ресурс міг закінчитись /чимось подібним/mike.smith/view


1

Це так само просто, як змінити шлях = " ." to path = " ". Просто видаліть крапку в шляху для ExensionlessUrlHandler-Integrated-4.0 в web.config.

Ось приємна стаття https://weblog.west-wind.com/posts/2015/Nov/13/Serving-URLs-with-File-Extensions-in-an-ASPNET-MVC-Application


Це посилання привело мене до найкращого вирішення моєї проблеми (сегмент містить символ ".", Але клієнти не переслідують "/"). Виправлено наявністю цього рядка в <system.webServer> web.config - <module runAllManagedModulesForAllRequests = "true" />
NickBeaugié

1

Спробував усі рішення вище, але жоден з них не працював на мене. Що я працював, я видалив версії .NET> 4.5, включаючи всі його багатомовні версії; Врешті-решт я додав новіші (лише англійською) версії по частинах. Зараз у моїй системі встановлені версії:

  • 2.0
  • 3.0
  • 3,5 4
  • 4.5
  • 4.5.1
  • 4.5.2
  • 4.6
  • 4.6.1

І це все ще працює на даний момент. Боюся встановити 4.6.2, тому що це може зіпсувати все.

Тож я міг лише припускати, що або 4.6.2, або всі ті, що не були англійською мовою, псували мою конфігурацію.


0

Мені вдалося вирішити свою конкретну версію цієї проблеми (довелося зробити /customer.html маршрут до / клієнта, не допускається прокручування косої риски) за допомогою рішення за адресою https://stackoverflow.com/a/13082446/1454265 та замінивши шлях = "*. html".


0

Як рішення можна також розглянути кодування до формату, який не містить символу ., як base64.

У js слід додати

btoa(parameter); 

У контролері

byte[] bytes = Convert.FromBase64String(parameter);
string parameter= Encoding.UTF8.GetString(bytes);

0

Додати правило перезапису URL-адреси в архів Web.config. Потрібно мати модуль перезапису URL-адреси вже встановлений у IIS. Використовуйте таке правило перезапису як натхнення для власного.

<?xml version="1.0" encoding="utf-8"?>
<configuration>

<system.webServer>
  <rewrite>
    <rules>
      <rule name="Add trailing slash for some URLs" stopProcessing="true">
        <match url="^(.*(\.).+[^\/])$" />
          <conditions>
              <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
              <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
          </conditions>
          <action type="Redirect" url="{R:1}/" />
      </rule>
    </rules>
    </rewrite>
</system.webServer>

</configuration> 

0

Крім того, (пов'язані) перевіряйте порядок відображення обробника. У нас був шлях .ashx з .svc (наприклад, /foo.asmx/bar.svc/path) на шляху після нього. Списання .svc спочатку було таким чином 404 для .svc шляху, який збігався перед .asmx. Не думав надто багато, але, можливо, про це подбає URL-адреса, що кодує шлях.


-3
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    [RoutePrefix("File")]
    [Route("{action=index}")]
    public class FileController : Controller
    {
        // GET: File
        public ActionResult Index()
        {
            return View();
        }

        [AllowAnonymous]
        [Route("Image/{extension?}/{filename}")]
        public ActionResult Image(string extension, string filename)
        {
            var dir = Server.MapPath("/app_data/images");

            var path = Path.Combine(dir, filename+"."+ (extension!=null?    extension:"jpg"));
           // var extension = filename.Substring(0,filename.LastIndexOf("."));

            return base.File(path, "image/jpeg");
        }
    }
}

1
Як це відповідає на питання ОП? Розумієте, будь ласка, описуючи це?
кайєс

це не рішення, це хак, який вимагає розміщення розширення файлу на шлях uri (без періоду), наприклад "~ / Image / jpg / cow", щоб отримати файл "/ app_data / images / cow / jpg" - - не рішення цього хлопця та всіх інших, хто знаходить це.
Шон Вілсон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.