Создать пользовательскую страницу перенаправления 301
Я пытаюсь написать схему перенаправления 301, используя пользовательский маршрут (класс, производный от RouteBase), аналогичный обработке устаревших URL для любого уровня в MVC. Я заглянул в класс HttpResponse в методе RedirectPermanent() с помощью отражателя и заметил, что код устанавливает состояние и выводит простую 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();
}
Как я могу записать вывод представления в поток ответов?
Дополнительная информация
В прошлом у нас были проблемы с переадресацией 301 с mydomain.com на www.mydomain.com, и впоследствии многие пользователи получали сообщения о недействительности SSL-сертификата. Поисковые системы сделали свое дело, но у пользователей были проблемы, пока я не переключился на редирект 302. На самом деле я не смог воспроизвести его, но мы получили значительное количество отчетов, поэтому что-то нужно было сделать.
Я планирую заставить представление выполнять мета-перенаправление, а также перенаправление javascript, чтобы повысить надежность, но для тех пользователей, которые все еще попадают на страницу 301, я хочу, чтобы они чувствовали себя как дома. У нас уже есть пользовательские страницы 404 и 500, почему бы не создать пользовательскую страницу 301?
2 ответа
Оказывается, я просто обдумывал проблему, и решение оказалось намного проще, чем я предполагал. Все, что мне действительно нужно было сделать, это использовать 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 к представлению для загрузки - шансы, что браузер будет следовать одному из них,
Также смотрите этот ответ для более полного решения.
Предполагая, что у вас есть доступ к 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
на ответ.