Маршруты .AppendTrailingSlash исключают некоторые маршруты
В MVC 5.2.2 я могу установить Routes.AppendTrailingSlash
в true, чтобы конечная косая черта была добавлена к URL-адресам.
Однако у меня также есть контроллер роботов, который возвращает содержимое файла robots.txt.
Как я могу запретить добавление Slash к маршруту robots.txt и вызвать ли его с помощью косой черты?
Код моего контроллера:
[Route("robots.txt")]
public async Task<ActionResult> Robots()
{
string robots = getRobotsContent();
return Content(robots, "text/plain");
}
My Route Config выглядит так:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home",
action = "Index",
id = UrlParameter.Optional }
);
RouteTable.Routes.AppendTrailingSlash = true;
Ответы
Ответ 1
Как о фильтре действий. Я написал это быстро, а не для эффективности. Я тестировал его по URL-адресу, где я вручную размещал и вел "/" , и работал как шарм.
public class NoSlash : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
var originalUrl = filterContext.HttpContext.Request.Url.ToString();
var newUrl = originalUrl.TrimEnd('/');
if (originalUrl.Length != newUrl.Length)
filterContext.HttpContext.Response.Redirect(newUrl);
}
}
Попробуйте использовать его таким образом
[NoSlash]
[Route("robots.txt")]
public async Task<ActionResult> Robots()
{
string robots = getRobotsContent();
return Content(robots, "text/plain");
}
Ответ 2
Если вы перейдете к статическому файлу .txt, поведение ASP.NET должно вернуть 404 Not Found, если URL-адрес имеет завершающую косую черту.
Я взял подход @Dave Alperovich (спасибо!) и вернул HttpNotFoundResult вместо перенаправления на URL без конечной косой черты. Я думаю, что любой из этих подходов полностью действителен.
/// <summary>
/// Requires that a HTTP request does not contain a trailing slash. If it does, return a 404 Not Found.
/// This is useful if you are dynamically generating something which acts like it a file on the web server.
/// E.g. /Robots.txt/ should not have a trailing slash and should be /Robots.txt.
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class NoTrailingSlashAttribute : FilterAttribute, IAuthorizationFilter
{
/// <summary>
/// Determines whether a request contains a trailing slash and, if it does, calls the <see cref="HandleTrailingSlashRequest"/> method.
/// </summary>
/// <param name="filterContext">An object that encapsulates information that is required in order to use the <see cref="System.Web.Mvc.RequireHttpsAttribute"/> attribute.</param>
/// <exception cref="System.ArgumentNullException">The filterContext parameter is null.</exception>
public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
string url = filterContext.HttpContext.Request.Url.ToString();
if (url[url.Length - 1] == '/')
{
this.HandleTrailingSlashRequest(filterContext);
}
}
/// <summary>
/// Handles HTTP requests that have a trailing slash but are not meant to.
/// </summary>
/// <param name="filterContext">An object that encapsulates information that is required in order to use the <see cref="System.Web.Mvc.RequireHttpsAttribute"/> attribute.</param>
protected virtual void HandleTrailingSlashRequest(AuthorizationContext filterContext)
{
filterContext.Result = new HttpNotFoundResult();
}
}