Asp.net mvc 创建自定义301重定向页面
我正在尝试使用自定义路由(从RouteBase派生的类)编写301重定向方案,类似于。我正在使用reflector查看RedirectPermanent()方法中的HttpResponse类,注意到该代码既设置了状态,又输出了一个简单的HTML页面Asp.net mvc 创建自定义301重定向页面,asp.net-mvc,asp.net-mvc-4,asp.net-mvc-routing,url-routing,httpresponse,Asp.net Mvc,Asp.net Mvc 4,Asp.net Mvc Routing,Url Routing,Httpresponse,我正在尝试使用自定义路由(从RouteBase派生的类)编写301重定向方案,类似于。我正在使用reflector查看RedirectPermanent()方法中的HttpResponse类,注意到该代码既设置了状态,又输出了一个简单的HTML页面 this.StatusCode = permanent ? 0x12d : 0x12e; this.RedirectLocation = url; if (UriUtil.IsSafeScheme(url)) {
this.StatusCode = permanent ? 0x12d : 0x12e;
this.RedirectLocation = url;
if (UriUtil.IsSafeScheme(url))
{
url = HttpUtility.HtmlAttributeEncode(url);
}
else
{
url = HttpUtility.HtmlAttributeEncode(HttpUtility.UrlEncode(url));
}
this.Write("<html><head><title>Object moved</title></head><body>\r\n");
this.Write("<h2>Object moved to <a href=\"" + url + "\">here</a>.</h2>\r\n");
this.Write("</body></html>\r\n");
如何将视图的输出写入响应流
其他信息
在过去,我们在从mydomain.com到www.mydomain.com的301重定向中遇到了问题,随后从用户那里收到了大量关于SSL证书无效的报告。搜索引擎做了他们的工作,但是用户有问题,直到我切换到302重定向。我实际上无法复制它,但我们收到了大量的报告,因此必须采取一些措施
我计划让视图执行元重定向和javascript重定向,以帮助提高可靠性,但对于那些仍停留在301页面上的用户,我希望他们感到宾至如归。我们已经有自定义404和500页,为什么不也有自定义主题301页?假设您可以访问
HttpContextBase
以下是如何将控制器操作的内容呈现给响应:
private void RedirectPermanent(string destinationUrl, HttpContextBase httpContext)
{
var response = httpContext.Response;
response.Clear();
response.StatusCode = 301;
response.RedirectLocation = destinationUrl;
// Output a Custom View Here (HomeController/SomeAction in this example)
var routeData = new RouteData();
routeData.Values["controller"] = "Home";
routeData.Values["action"] = "SomeAction";
IController homeController = new HomeController();
var rc = new RequestContext(new HttpContextWrapper(context), routeData);
homeController.Execute(rc);
response.End();
}
这将在
HomeController
上向响应呈现SomeAction
。假设您有权访问HttpContextBase
以下是如何向响应呈现控制器操作的内容:
private void RedirectPermanent(string destinationUrl, HttpContextBase httpContext)
{
var response = httpContext.Response;
response.Clear();
response.StatusCode = 301;
response.RedirectLocation = destinationUrl;
// Output a Custom View Here (HomeController/SomeAction in this example)
var routeData = new RouteData();
routeData.Values["controller"] = "Home";
routeData.Values["action"] = "SomeAction";
IController homeController = new HomeController();
var rc = new RequestContext(new HttpContextWrapper(context), routeData);
homeController.Execute(rc);
response.End();
}
这将在
HomeController
上对响应执行SomeAction
。结果表明,我只是过度思考了问题,解决方案比我预想的要简单得多。我真正需要做的就是使用routeData将请求推送到另一个控制器操作。让我不高兴的是需要附加到请求中的额外301状态信息
private RouteData RedirectPermanent(string destinationUrl, HttpContextBase httpContext)
{
var response = httpContext.Response;
response.CacheControl = "no-cache";
response.StatusCode = 301;
response.RedirectLocation = destinationUrl;
var routeData = new RouteData(this, new MvcRouteHandler());
routeData.Values["controller"] = "Home";
routeData.Values["action"] = "Redirect301";
routeData.Values["url"] = destinationUrl;
return routeData;
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
// Do stuff here...
if (this.IsDefaultUICulture(cultureName))
{
var urlWithoutCulture = url.ToString().ToLowerInvariant().Replace("/" + cultureName.ToLowerInvariant(), "");
return this.RedirectPermanent(urlWithoutCulture, httpContext);
}
// Get the page info here...
if (page != null)
{
result = new RouteData(this, new MvcRouteHandler());
result.Values["controller"] = page.ContentType.ToString();
result.Values["action"] = "Index";
result.Values["id"] = page.ContentId;
}
return result;
}
我只需要返回RoutedData,这样路由器就可以处理它了
注意,我还添加了一个CacheControl头,以防止IE9和Firefox以无法清除的方式缓存重定向
现在,我有了一个很好的页面,当浏览器无法遵循301时,它会向用户显示一个链接和消息,我会向视图添加一个元重定向和javascript重定向,以引导-很可能浏览器会遵循其中之一
有关更全面的解决方案,请参见
事实证明,我只是过度思考了这个问题,解决方案比我想象的要简单得多。我真正需要做的就是使用routeData将请求推送到另一个控制器操作。让我不高兴的是需要附加到请求中的额外301状态信息
private RouteData RedirectPermanent(string destinationUrl, HttpContextBase httpContext)
{
var response = httpContext.Response;
response.CacheControl = "no-cache";
response.StatusCode = 301;
response.RedirectLocation = destinationUrl;
var routeData = new RouteData(this, new MvcRouteHandler());
routeData.Values["controller"] = "Home";
routeData.Values["action"] = "Redirect301";
routeData.Values["url"] = destinationUrl;
return routeData;
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
// Do stuff here...
if (this.IsDefaultUICulture(cultureName))
{
var urlWithoutCulture = url.ToString().ToLowerInvariant().Replace("/" + cultureName.ToLowerInvariant(), "");
return this.RedirectPermanent(urlWithoutCulture, httpContext);
}
// Get the page info here...
if (page != null)
{
result = new RouteData(this, new MvcRouteHandler());
result.Values["controller"] = page.ContentType.ToString();
result.Values["action"] = "Index";
result.Values["id"] = page.ContentId;
}
return result;
}
我只需要返回RoutedData,这样路由器就可以处理它了
注意,我还添加了一个CacheControl头,以防止IE9和Firefox以无法清除的方式缓存重定向
现在,我有了一个很好的页面,当浏览器无法遵循301时,它会向用户显示一个链接和消息,我会向视图添加一个元重定向和javascript重定向,以引导-很可能浏览器会遵循其中之一
有关更全面的解决方案,请参见
哪些浏览器不支持301重定向?@jrummell:我知道有很多插件(随着tinyurl等的发展)会停止重定向。尽管浏览器支持它,但出于安全原因,用户选择退出。这是为了保护用户免受网络钓鱼吗?@jrummell:phishing并试图将用户转发到具有0天攻击的站点。(我个人有我的,以避免跳跃超过1)。@NightOwl:视图是固定的,基于重定向路线还是其他什么?你应该能够启动一个新的ViewContext并将其转储(假设你知道要显示什么)。哪些浏览器不支持301重定向?@jrummell:我知道有很多插件(随着tinyurl等的发展)会停止重定向。尽管浏览器支持它,但出于安全原因,用户选择退出。这是为了保护用户免受网络钓鱼吗?@jrummell:phishing并试图将用户转发到具有0天攻击的站点。(我个人有我的,以避免跳跃超过1)。@NightOwl:视图是固定的,基于重定向路线还是其他什么?您应该能够启动一个新的ViewContext并将其转储(假设您知道要显示什么)。正如上面我的方法签名所示,它接受HttpContextBase作为参数。然而,我很好奇请求上下文调用是否会再次击中路由器(请记住,此重定向代码本身将位于路由器中)。我不太确定,尝试它将为您提供一个明确的答案。没有乐趣。在尝试解析布局页面上的某些链接时,我得到了一个“System.Threading.LockRecursionException:此模式下不允许递归读取锁获取”。它是从MVC框架的RouteCollectionExtensions.FilterRouteCollectionByArea()方法中抛出的,该方法由ActionLink()调用。这看起来很有希望。正如上面我的方法签名所示,它接受HttpContextBase作为参数。然而,我很好奇请求上下文调用是否会再次击中路由器(请记住,此重定向代码本身将位于路由器中)。我不太确定,尝试它将为您提供一个明确的答案。没有乐趣。在尝试解析布局页面上的某些链接时,我得到了一个“System.Threading.LockRecursionException:此模式下不允许递归读取锁获取”。它是从MVC框架的RouteCollectionExtensions.FilterRouteCollectionByArea()方法中抛出的,该方法由ActionLink()调用。