我正在尝试使用类似于Handling legacy url's for any level in MVC的自定义路由(源自RouteBase的类)编写301重定向方案。我正在使用反射器在RedirectPermanent()方法中窥视HttpResponse类,并注意到代码既设置状态又输出一个简单的HTML页面。
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");
这是可取的,因为根据我的经验,并非所有浏览器都配置为遵循301重定向(尽管搜索引擎会这样做)。因此,如果浏览器没有自动转到该页面,也可以为用户提供指向该页面的链接。
我想要做的是将其提升到一个新的水平 - 我想输出MVC视图的结果(以及它的主题布局页面),而不是在响应中输入硬编码的丑陋通用HTML。类似的东西:
private void RedirectPermanent(string destinationUrl, HttpContextBase httpContext)
{
var response = httpContext.Response;
response.Clear();
response.StatusCode = 301;
response.RedirectLocation = destinationUrl;
// Output a Custom View Here
response.Write(The View)
response.End();
}
如何将视图的输出写入响应流?
其他信息
过去,我们遇到了从mydomain.com到www.mydomain.com的301重定向问题,随后有很多用户报告SSL证书无效。搜索引擎完成了他们的工作,但用户遇到了问题,直到我切换到302重定向。我实际上无法重现它,但我们得到了大量的报告,因此必须要做些什么。
我计划让视图执行元重定向以及javascript重定向以帮助提高可靠性,但对于那些仍然在301页面结束的用户,我希望他们有宾至如归的感觉。我们已经有自定义的404页和500页,为什么不是自定义主题301页呢?
答案 0 :(得分:1)
事实证明我只是过度思考问题而且解决方案比我想象的要简单得多。我真正需要做的就是使用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;
}
我只需要返回RouteData,以便路由器处理它!
另请注意,我添加了一个CacheControl标头,以防止IE9和Firefox以无法清除的方式缓存重定向。
现在我有一个很好的页面,当浏览器无法跟踪301时,会向用户显示链接和消息,我将添加元重定向和javascript重定向到视图以启动 - 浏览器将遵循的几率其中之一。
另请参阅this answer了解更全面的解决方案。
答案 1 :(得分:0)
假设您可以访问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();
}
这会在SomeAction
上将HomeController
呈现给回复。