我想添加一个robots.txt文件,我想根据域本地化robots.txt文件,但我知道我在站点的文件系统目录中只能有一个物理“robots.txt”文本文件。
使用ASP.NET MVC框架在每个域的基础上实现一个robots.txt文件是最简单/最好的方法(甚至是可能的),以便相同的站点安装向每个域提供内容,但内容的机器人文件是根据所请求的域进行本地化的?
解决方法
控制器/动作方式
>使用您的路线表,将您的robots.txt路径映射到控制器中的操作(我使用控制器和操作作为一个简单的例子来启动),就像给任何其他控制器和给定路径的视图一样。
>在Action中,检查请求中的域,然后为该域选择您的robots.txt内容。
>从磁盘返回相应的文件,如下所示:
> ContentResult
并将ContentType设置为“text / plain”
> FilePathResult
,如果您的机器人文件只是磁盘上的文件,通过Controller类上的一个帮助程序方法,如File(name,"text/plain")
以下示例假定单个顶级robots.txt文件:
// In App_Start/RouteConfig: public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "robots",url: "robots.txt",defaults: new { controller = "SEO",action = "Robots" } ); // The controller: public class SEOController : Controller { public ActionResult Robots() { var robotsFile = "~/robots-default.txt"; switch (Request.Url.Host.ToLower()) { case "stackoverflow.com": robotsFile = "~/robots-so.txt"; break; case "Meta.stackoverflow.com": robotsFile = "~/robots-Meta.txt"; break; } return File(robotsFile,"text/plain"); } }
那么最简单的方法之一就是确保使用web.config中的runAllManagedModulesForAllRequests来调用所有请求的路由模块(请不要使用它,请参见下一段):
<system.webServer> <handlers> ... </handlers> <modules runAllManagedModulesForAllRequests="true" /> </system.webServer>
这通常不是一件好事,现在所有的静态文件(css,js,txt)在被转移到静态文件处理程序之前经过托管处理程序。 IIS非常适用于快速提供静态文件(大部分静态文件网站将在cpu之前最大化磁盘I / O方式),因此为避免这种性能受到打击,推荐的方法如下面的web.config示例部分。请注意与Visual Studio MVC 4模板应用程序中的ExtensionlessUrlHandler-Integrated-4.0处理程序的相似性:
<system.webServer> <handlers> <add name="Robots-Integrated-4.0" path="/robots.txt" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> ... the original handlers ... </handlers> <modules runAllManagedModulesForAllRequests="false" /> </system.webServer>
优点/缺点
>您可以通过使用帮助程序生成Action url动态生成robots.txt文件,然后您可以将模板robots.txt文件的全部/部分添加到其中。
>您可以检查机器人用户代理,以便每个机器人用户代理返回不同的机器人文件
>您可以使用相同的控制器输出网页抓取工具的sitemap.xml文件
>您可以从容易由站点用户管理的数据库表中管理漫游器内容。
在缺点,
>您的漫游器文件现在使您的路由表复杂化,并不是真的需要
>您将需要优化缓存以防止持续的磁盘读取。但是,对于您采取的任何方式,这是一样的。
还要记住,不同的robots.txt文件可以用于不同的子目录。这通过路由和控制器方法变得棘手,所以IHttpHandler方法(下面)对于这种情况来说更容易。
IHttpHandler方法
您还可以使用自定义IHttpHandler registered in your web.config来实现此功能。我强调自定义,因为这样可以避免使所有控制器看到所有请求(使用runAllManagedModulesForAllRequests =“true”),这与在路由表中添加自定义路由处理程序不同。
这也可能是一个比控制器更轻便的方法,但您必须拥有巨大的网站流量才能注意到差异。其他好处是可以使用的代码段,可以用于所有的网站。您还可以添加自定义配置部分来配置机器人用户代理/域名/路径映射到漫游器文件。
<system.webServer> <handlers> <add name="Robots" verb="*" path="/robots.txt" type="MyProject.RobotsHandler,MyAssembly" preCondition="managedHandler"/> </handlers> <modules runAllManagedModulesForAllRequests="false" /> </system.webServer>
public class RobotsHandler: IHttpHandler { public bool IsReusable { get { return false; } } public void ProcessRequest(HttpContext context) { string domain = context.Request.Url.Host; // set the response code,content type and appropriate robots file here // also think about handling caching,sending error codes etc. context.Response.StatusCode = 200; context.Response.ContentType = "text/plain"; // return the robots content context.Response.Write("my robots content"); } }
robots.txt在子目录中
要为子目录和站点根目录提供机器人,您无法轻松使用控制器方法;在这种情况下,处理程序方法更简单。这可以配置为将robots.txt文件请求提取到任何子目录,并相应地处理它们。然后,您可以选择为某些目录返回404,或为其他目录返回机器人文件的子部分。
我特别提到这里,因为这种方法也可以用于sitemap.xml文件,为站点的不同部分提供不同的站点地图,多个彼此引用的站点地图等。
其他参考文献:
> Scott Hanselman: Back to Basics: Dynamic Image Generation,ASP.NET Controllers,Routing,IHttpHandlers,and runAllManagedModulesForAllRequests
> MSDN – How to: Register HTTP Handlers