MVC:如何将 /sitemap.xml 路由到 ActionResult?

发布于 2024-08-16 20:03:28 字数 335 浏览 7 评论 0原文

我有一个 SitemapActionResult 覆盖 ActionResult,并在 http://www.sitemap.xml 时提供 SEO sitemap.xml。 sprelle.no/Home/SiteMap 已被点击。到目前为止,一切都很好。

不过,我想要的是当 Google 访问 /sitemap.xml 时提供 sitemap.xml。为了实现这一点,我需要一条可以看到“sitemap.xml”并指向/Home/Sitemap 的路线。

如何创建此映射(在路由表中)?

I've got a SitemapActionResult that overrides the ActionResult, and delivers a SEO sitemap.xml when http://www.sprelle.no/Home/SiteMap is hit. So far so good.

What I would like, though, is to serve the sitemap.xml when Google visits /sitemap.xml. For that to work, I need a route that sees "sitemap.xml" and directs to /Home/Sitemap.

How do I create this mapping (in the Routes table)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

沩ん囻菔务 2024-08-23 20:03:28

添加地图:

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

请注意,路线、控制器和操作选项都是硬编码的。

Add a map for:

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

Notice that the route, controller, and action options are hard coded.

深海不蓝 2024-08-23 20:03:28

你可以用这个。

步骤 1. 将文件扩展名映射到 TransferRequestHandler

IIS 7 集成模式使用 HTTP 处理程序映射,将路径/动词组合指向 HTTP 处理程序。例如,有一个默认处理程序映射,它将 path="*.axd" verb="GET,HEAD,POST,DEBUG" 指向站点运行时的 .NET 运行时版本的相应 ISAPI 模块。查看 IIS Express 下的默认处理程序的最简单方法是在 IIS Express 下运行一个站点,右键单击系统托盘中的 IIS Express 图标,单击“显示所有应用程序”,然后单击一个站点。底部的 applicationhost.config 链接已链接,因此您只需单击它,它就会在 Visual Studio 中加载。

如果滚动到底部,您会看到 path="*" verb="*" 有一个包罗万象的 StaticFile 映射,它指向 StaticFileModule,DefaultDocumentModule,DirectoryListingModule 。如果您什么都不做,这就是处理您的 .html 请求的方法。因此,第一步是在 web.config 中添加一个处理程序,将 *.html 请求指向 TransferRequestHandlerTransferRequestHandler 是处理您在 MVC 路由中常见的无扩展 URL 的处理程序,例如 /store/details/5

添加处理程序映射非常简单 - 只需打开 web.config 并将其添加到 节点即可。

<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 错误(递归溢出),不得不向 Eilon Lipton 寻求帮助。

无论如何,这很容易修复 - 只需将 paths.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");
}

You can used this.

Step 1. Mapping the file extension to TransferRequestHandler

IIS 7 Integrated mode uses HTTP Handler mappings which point path / verb combinations to an HTTP Handler. For example, there's a default handler mapping which points path="*.axd" verb="GET,HEAD,POST,DEBUG" to the appropriate ISAPI module for the .NET runtime version the site's running under. The easiest way to see the default handlers under IIS Express is to run a site under IIS Express, right-click the IIS Express icon in the system tray, click "show all applications", and click on a site. The applicationhost.config link at the bottom is linked, so you can just click on it and it should load in Visual Studio.

If you scroll to the bottom, you'll see that there's a catchall StaticFile mapping for path="*" verb="*" which points to StaticFileModule,DefaultDocumentModule,DirectoryListingModule. That's what will handle your .html request if you do nothing. So the first step is to add a handler in your web.config that will point *.html requests to the TransferRequestHandler. TransferRequestHandler is the handler that takes care of the extensionless URLs you're used to seeing in MVC routes, e.g. /store/details/5.

Adding a handler mapping is really easy - just open up your web.config and add it to the <system.webServer/handlers> node.

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

Note that you can make the path more specific if you'd like. For instance, if you only wanted to intercept one specific request, you could use path="sample.html"

Step 2. Configuring the route

Next, you'll need a new route. Open up App_Start/RouteConfig.cs and it to the RegisterRoutes call. My complete RegisterRoutes looks like this:

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

Step 3. Route Existing Files

That almost covers it, but there's one more thing to take care of - overriding requests that match an existing file. If you've got an actual file called myfile.html, the routing system won't allow your route to run. I forgot about this, ended up with an HTTP 500 error (recursion overflow) and had to ask Eilon Lipton for help.

Anyways, that's easy to fix - just add routes.RouteExistingFiles = true to your route registration. My completed RegisterRoutes call looks like this:

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 }
            );
    }

That's it.

I tested by adding this controller action:

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");
}
俏︾媚 2024-08-23 20:03:28

要使其正常工作,您需要做两件事:

  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" }
);

To get this to work you need to do 2 things:

  1. Instruct the IIS to allow the static file request "/sitemap.xml" to hit your controller. Otherwise the IIS will bypass your application and look directly for a file with this name. Add the following line to your 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. Place a route in your MVC application that matches this request to an ActionResult (make sure you place it before your default route):
routes.MapRoute(
    name: "Sitemap",
    url: "sitemap.xml",
    defaults: new { controller = "YourControllerName", action = "YourActionName" }
);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文