MVC: как направить /sitemap.xml в ActionResult?

У меня есть SitemapActionResult, который переопределяет ActionResult и предоставляет SEO sitemap.xml, когда http://www.sprelle.no/Home/SiteMap попал под удар. Все идет нормально.

Однако я хотел бы, чтобы sitemap.xml обслуживался, когда Google посещает /sitemap.xml. Чтобы это работало, мне нужен маршрут, который видит "sitemap.xml" и ведет к /Home/Sitemap.

Как создать это сопоставление (в таблице Routes)?


person HaakonL    schedule 05.01.2010    source источник


Ответы (3)


Добавьте карту для:

routes.MapRoute(
            "Sitemap",
            "sitemap.xml",
            new { controller = "Home", action = "SiteMap" }
            );

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

person bendewey    schedule 05.01.2010
comment
На самом деле я пробовал это ранее сегодня, но не смог заставить его работать, потому что я добавил маршрут после маршрута по умолчанию. Для работы его необходимо вставить перед маршрутом по умолчанию. Спасибо. - person HaakonL; 05.01.2010
comment
Также не забудьте добавить runAllManagedModulesForAllRequests=true для конфигурации ваших модулей внутри system.webServer, иначе он попытается использовать обработчик staticfile и вернет ошибку 404. - person Raul Vejar; 04.04.2013
comment
@RaulVejar Спасибо! Я искал в Интернете больше часа, и вы первый, кто упомянул часть модулей. Это решило мою проблему. - person ddilsaver; 03.06.2013
comment
runAllManagedModulesForAllRequest повлияет на вашу производительность. Возможно, вы можете добавить запись для sitemap.xml только внутри system.webServer.modules: - person Radu D; 20.12.2013
comment
@RaduD Это должно быть в system.webServer.handlers, а не в .modules. - person quentin-starin; 07.05.2014
comment
Я разработал утилиту для создания карты сайта для моего веб-сайта mrnams.com. У меня возникла проблема: «когда код генерирует sitemap.xml и пытается сохранить его в \wwwroot\sitemap.xml, происходит сбой с отказом в доступе». Поскольку я использую plesk, Я не могу получить доступ к IIS, а также не хочу давать разрешения на запись всем другим статическим файлам. Пожалуйста помоги. - person MrNams; 01.12.2018

Вы можете использовать это.

Шаг 1. Сопоставление расширения файла с TransferRequestHandler

Интегрированный режим IIS 7 использует сопоставления обработчиков HTTP, которые указывают комбинации пути/команды на обработчик HTTP. Например, существует сопоставление обработчика по умолчанию, которое указывает path="*.axd" verb="GET,HEAD,POST,DEBUG" на соответствующий модуль ISAPI для версии среды выполнения .NET, под которой работает сайт. Самый простой способ увидеть обработчики по умолчанию в IIS Express — запустить сайт в IIS Express, щелкнуть правой кнопкой мыши значок IIS Express на панели задач, нажать «показать все приложения» и щелкнуть сайт. Ссылка applicationhost.config внизу связана, поэтому вы можете просто щелкнуть по ней, и она должна загрузиться в Visual Studio.

Если вы прокрутите страницу вниз, вы увидите, что для path="*" verb="*" есть универсальное сопоставление StaticFile, которое указывает на StaticFileModule,DefaultDocumentModule,DirectoryListingModule. Это то, что обработает ваш запрос .html, если вы ничего не сделаете. Итак, первый шаг — добавить обработчик в файл web.config, который будет направлять *.html запросов к TransferRequestHandler. TransferRequestHandler — это обработчик, который заботится о URL-адресах без расширения, которые вы привыкли видеть в маршрутах MVC, например. /store/details/5.

Добавить сопоставление обработчика очень просто — просто откройте файл web.config и добавьте его в узел <system.webServer/handlers>.

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

Обратите внимание, что вы можете сделать путь более конкретным, если хотите. Например, если вы хотите перехватить только один конкретный запрос, вы можете использовать path="sample.html"

Шаг 2. Настройка маршрута

Далее вам понадобится новый маршрут. Откройте App_Start/RouteConfig.cs и вызовите RegisterRoutes. Мой полный RegisterRoutes выглядит так:

  routes.MapRoute(
       name: "XMLPath",
       url: "sitemapindex.xml",
       defaults: new { controller = "Home", action = "Html", page = UrlParameter.Optional }
   );

Шаг 3. Маршрутизация существующих файлов

Это почти покрывает его, но есть еще одна вещь, о которой нужно позаботиться — переопределение запросов, которые соответствуют существующему файлу. Если у вас есть реальный файл с именем myfile.html, система маршрутизации не позволит запустить ваш маршрут. Я забыл об этом, получил ошибку HTTP 500 (переполнение рекурсии) и был вынужден обратиться за помощью к Эйлону Липтону.

В любом случае, это легко исправить — просто добавьте route.RouteExistingFiles = true в регистрацию маршрута. Мой завершенный вызов RegisterRoutes выглядит так:

public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.RouteExistingFiles = true;

        routes.MapRoute(
            name: "CrazyPants",
            url: "{page}.html",
            defaults: new { controller = "Home", action = "Html", page = UrlParameter.Optional }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
    }

Вот и все.

Я проверил, добавив это действие контроллера:

public FileResult Html()
{
    var stringBuilder = new StringBuilder();
    stringBuilder.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
    stringBuilder.AppendLine("<sitemapindex xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">");
    stringBuilder.AppendLine("<sitemap>");
    stringBuilder.AppendLine("<loc>http://sprint-newhomes.move.com/sitemaps/sitemap_01.xml</loc>");
    stringBuilder.AppendLine("<lastmod>" + DateTime.Now.ToString("MMMM-dd-yyyy HH:mm:ss tt") + "</lastmod>");
    stringBuilder.AppendLine("</sitemap>");
    stringBuilder.AppendLine("<sitemap>");
    stringBuilder.AppendLine("<loc>http://sprint-newhomes.move.com/sitemaps/sitemap_02.xml</loc>");
    stringBuilder.AppendLine("<lastmod>" + DateTime.Now.ToString("MMMM-dd-yyyy HH:mm:ss tt") + "</lastmod>");
    stringBuilder.AppendLine("</sitemap>");
    stringBuilder.AppendLine("</sitemapindex>");

    var ms = new MemoryStream(Encoding.ASCII.GetBytes(stringBuilder.ToString()));



    Response.AppendHeader("Content-Disposition", "inline;filename=sitemapindex.xml");
    return new FileStreamResult(ms, "text/xml");
}
person Pablo Andres Barrantes    schedule 19.05.2015
comment
Хотя этот ответ может быть правильным, было бы лучше включить сюда соответствующий код. Ответы, содержащие только ссылки, могут стать неверными, если веб-сайт перемещается или удаляется. - person Jonathan; 19.05.2015

Чтобы заставить это работать, вам нужно сделать 2 вещи:

  1. Укажите IIS, чтобы запрос статического файла "/sitemap.xml" попадал на ваш контроллер. В противном случае IIS будет обходить ваше приложение и напрямую искать файл с таким именем. Добавьте следующую строку в ваш web.config:
<system.webServer>
    <handlers>

        <!-- add the following line -->
        <add name="SitemapXml" path="sitemap.xml" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>

    </handlers>
</system.webServer>
  1. Поместите маршрут в свое приложение MVC, который соответствует этому запросу, к ActionResult (убедитесь, что вы поместили его перед маршрутом по умолчанию):
routes.MapRoute(
    name: "Sitemap",
    url: "sitemap.xml",
    defaults: new { controller = "YourControllerName", action = "YourActionName" }
);
person Rune Vejen Petersen    schedule 10.12.2017
comment
этот ответ тоже очень полезен, но он внизу - person cwhsu; 12.08.2020