1

MVCの任意のレベルのレガシーURLの処理と同様のカスタムルート(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リダイレクトに従うように構成されているわけではないため、これは望ましいことです(検索エンジンはそうしますが)。したがって、ブラウザが自動的にそこに移動しない場合に備えて、ユーザーにページへのリンクを提供することも理にかなっています。

私がやりたいのは、これを次のレベルに引き上げることです。応答にハードコーディングされた醜い汎用HTMLを使用する代わりに、MVCビューの結果を(テーマのあるレイアウトページとともに)出力したいと思います。何かのようなもの:

    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ページもありませんか?

4

2 に答える 2

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 を返すだけで済みました。

また、IE9 と Firefox がクリアできない方法でリダイレクトをキャッシュするのを防ぐために、CacheControl ヘッダーを追加したことにも注意してください。

これで、ブラウザーが 301 を追跡できない場合にユーザーにリンクとメッセージを表示する素敵なページができました。メタ リダイレクトと JavaScript リダイレクトをビューに追加して起動します。ブラウザーはそれらのいずれかに従う可能性があります。 .

より包括的なソリューションについては、この回答も参照してください。

于 2013-03-06T01:53:26.337 に答える
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

于 2013-03-05T22:23:44.557 に答える