ビューをUpdateTargetIdに挿入する代わりに、ASP.NET MVC Ajax応答を取得して新しいページにリダイレクトするにはどうすればよいですか?


88

Ajax.BeginFormを使用してフォームを作成し、特定のコントローラーアクションにajaxポストバックを行い、アクションが成功した場合、ユーザーは別のページにリダイレクトされる必要があります(アクションが失敗した場合、ステータスメッセージが表示されます。 AjaxOptions UpdateTargetId)。

using (Ajax.BeginForm("Delete", null,
        new { userId = Model.UserId },
        new AjaxOptions { UpdateTargetId = "UserForm", LoadingElementId = "DeletingDiv" },
        new { name = "DeleteForm", id = "DeleteForm" }))
   {
    [HTML DELETE BUTTON]
   }

削除が成功した場合、リダイレクト結果を返します。

[Authorize]
public ActionResult Delete(Int32 UserId)
{
    UserRepository.DeleteUser(UserId);
    return Redirect(Url.Action("Index", "Home"));
}

しかし、Home Controller IndexビューがUpdateTargetIdに読み込まれているため、ページ内のページになってしまいます。私が考えている2つのこと:

  1. 私はこれを間違って設計していて、このタイプのアクションを異なる方法で処理する必要があります(ajaxは使用しません)。
  2. Redirectの結果を返す代わりに、クライアント側でリダイレクトを行うJavaScriptを含むビューを返します。

#1についてコメントはありますか?または、#2が適切なソリューションである場合、「リダイレクトJavaScriptビュー」はどのようになりますか?

回答:


171

JavascriptResultこれを達成するために使用できます。

リダイレクトするには:

return JavaScript("window.location = 'http://www.google.co.uk'");

現在のページをリロードするには:

return JavaScript("location.reload(true)");

最も単純なオプションのようです。


4
すばらしい..助けてくれた。
CrazyCoderz 2011

1
これは正しいアプローチです。この回答stackoverflow.com/a/2841608/498969は、デフォルトでベースコントローラを使用してこの機能を適用する方法を示しています。
Adam Spicer

@Ben Foster:このブラウズを使用すると、URL http :: window.location ..を開こうとします。これを個別の質問としてstackoverflow.com/questions/13896307/…
Andrus

30
プロジェクトのコントローラーにリダイレクトする場合は、URLヘルパーを使用できます。例:return JavaScript( "window.location = '" + Url.Action("Edit","Dispatch") + "'" );
Chris Morgan

2
ショート。シンプル。優れた。すごい!
Vikram

30

URLを含むJSONを返し、クライアント側でJavaScriptを使用してwindow.locationを変更できます。私は、サーバーからJavaScript関数を呼び出すよりもこの方法を好みます。これは、懸念の分離を壊していると思います。

サーバ側:

return Json(new {result = "Redirect", url = Url.Action("ActionName", "ControllerName")});

クライアント側:

if (response.result == 'Redirect')
    window.location = response.url;

もちろん、サーバー側でエラーが発生する可能性があるため、さらにロジックを追加できます。その場合、resultプロパティがこの状況を示し、リダイレクトを回避できます。


12

あなたが作り出そうとしている振る舞いは、AJAXを使用して本当に最善に行われるわけではありません。他のページに完全にリダイレクトせずに、ページの一部のみを更新する場合は、AJAXが最適です。これは、AJAXの目的全体を実際に無効にします。

あなたが説明している振る舞いでAJAXを使用しないことをお勧めします。

または、リクエストを送信するjquery Ajaxを使用して、リクエストが完了したときにコールバックを指定することもできます。コールバックでは、失敗したか成功したかを判断し、成功時に別のページにリダイレクトできます。特にとにかく既に他のライブラリを使用しているので、jquery Ajaxの方がはるかに使いやすいことがわかりました。

jquery ajaxに関するドキュメントはここにありますが、構文は次のとおりです。

jQuery.ajax( options )  

jQuery.get( url, data, callback, type)

jQuery.getJSON( url, data, callback )

jQuery.getScript( url, callback )

jQuery.post( url, data, callback, type)

削除アクションに対して通常のPOSTを実行するだけで、ほとんどの場合成功し、ホームインデックスページにリダイレクトできます。失敗する場合は、エラーメッセージとユーザーが実行する適切なアクションを含む別のビューを表示します。いいですか?
ジェフウィドマー、

うん、それはもっと理にかなっているように聞こえる。
ジョセフ

Josephの推奨に従って、これをAjax送信から通常のPOSTに変換しました。削除確認メッセージを処理するためのよりクリーンな方法を提供してくれたので、これは実際にはうまくいきました。
Jeff Widmer、

12

エレガントではありませんが、特定の状況で機能します。

コントローラ

if (RedirectToPage)
    return PartialView("JavascriptRedirect", new JavascriptRedirectModel("http://www.google.com"));
else
   ... return regular ajax partialview

型番

    public JavascriptRedirectModel(string location)
    {
        Location = location;
    }

    public string Location { get; set; }

/Views/Shared/JavascriptRedirect.cshtml

@model Models.Shared.JavascriptRedirectModel

<script type="text/javascript">
    window.location = '@Model.Location';
</script>

2
なぜエレガントではないのですか?それは強く型付けされており、明確に感じます。私はそのアプローチが好きです。+1
Tモーティー

6

使用JavaScriptすることは間違いなく仕事をします。

Contentこれがあなたのスタイルならもっと使うこともできます。

例:

MVCコントローラー

[HttpPost]
public ActionResult AjaxMethod()
{
    return Content(@"http://www.google.co.uk");
}

Javascript

$.ajax({
    type: 'POST',
    url: '/AjaxMethod',
    success: function (redirect) {
        window.location = redirect;
    }
});

ありがとうございました!これは本当に役に立ちました。
ディー

5

以下のようにAjax Successで簡単に書くことができます:

 $.ajax({
            type: "POST",
            url: '@Url.Action("GetUserList", "User")',
            data: { id: $("#UID").val() },
            success: function (data) {
                window.location.href = '@Url.Action("Dashboard", "User")';
            },
            error: function () {
                $("#loader").fadeOut("slow");
            }
});

2

これはどう :

public ActionResult GetGrid()
{
   string url = "login.html";
   return new HttpStatusCodeResult(System.Net.HttpStatusCode.Redirect,url)
}

その後

$(document).ajaxError(function (event, jqxhr, settings, thrownError) { 
   if (jqxhr.status == 302) {
      location.href = jqxhr.statusText;
   }           
});

または

error: function (a, b, c) {
       if (a.status == 302) {
         location.href = a.statusText;
       }  
}

1

私はajaxログインフォームを持っているので、これを行う必要がありました。ユーザーが正常にログインすると、新しいページにリダイレクトし、前の要求を終了します。これは、他のページが依存パーティへのリダイレクトを処理するためです(それがSTS SSOシステムであるため)。

しかし、私はまた、JavaScriptを無効にして、中央ログインホップなどすべてで動作するようにしたかったので、これを思いつきました。

    public static string EnsureUrlEndsWithSlash(string url)
    {
        if (string.IsNullOrEmpty(url))
            throw new ArgumentNullException("url");
        if (!url.EndsWith("/"))
            return string.Concat(url, "/");
        return url;
    }

    public static string GetQueryStringFromArray(KeyValuePair<string, string>[] values)
    {
        Dictionary<string, string> dValues = new Dictionary<string,string>();
        foreach(var pair in values)            
            dValues.Add(pair.Key, pair.Value);            
        var array = (from key in dValues.Keys select string.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(dValues[key]))).ToArray();
        return "?" + string.Join("&", array);
    }

    public static void RedirectTo(this HttpRequestBase request, string url, params KeyValuePair<string, string>[] queryParameters)
    {            
        string redirectUrl = string.Concat(EnsureUrlEndsWithSlash(url), GetQueryStringFromArray(queryParameters));
        if (request.IsAjaxRequest())
            HttpContext.Current.Response.Write(string.Format("<script type=\"text/javascript\">window.location='{0}';</script>", redirectUrl));
        else
            HttpContext.Current.Response.Redirect(redirectUrl, true);

    }

1

$ .ajaxSetupを使用して、着信応答に対して何らかのajax応答フィルターを単純に実行できます。応答にMVCリダイレクトが含まれている場合は、JS側でこの式を評価できます。以下のJSのコード例:

$.ajaxSetup({
    dataFilter: function (data, type) {
        if (data && typeof data == "string") {
            if (data.indexOf('window.location') > -1) {
                eval(data);
            }
        }
        return data;
    }
});

データが:「window.location = '/ Acount / Login'」の場合、上記のフィルターはそれをキャッチし、評価してリダイレクトを行います。


0

正しい問題を修正するのではなく、ジョセフによる最良の回答に満足していません、これは間違った使用例であると彼は言いました。実際、たとえば、古いコードベースをajax化されたコードに変換していて、それが必要な場合は、必要になります。プログラミングには言い訳はありません。すべての悪い開発者と良い開発者をコーディングしているのはあなただけではなく、並べて作業する必要があるからです。したがって、ajaxでリダイレクトをコード化しない場合、私の開発者仲間は私にそれに対する解決策を強制することができます。AMDのパターン化されたすべてのサイトまたはmvc4を使用したいのと同じように、私の会社は1年間それから遠ざけることができます。

それでは、解決策について話しましょう。

私はajax要求と応答の処理を一通り行っており、クライアントにステータスコードを送信して、それらのコードを理解するための1つの標準javascript関数を用意することが最も簡単な方法であることがわかりました。私が単にコード13の例を送信する場合、それはリダイレクトを意味するかもしれません。

したがって、{statusCode:13、messsage: '/ home / logged-in'}のようなjsonレスポンスはもちろん、{status: 'success'、code:13、url: '/ home / logged-inのようなさまざまなバリエーションが提案されています'、メッセージ:'現在ログインしています '}

など、標準メッセージの独自の選択まで

通常、基本のControllerクラスから継承し、このような標準的な応答を選択します

public JsonResult JsonDataResult(object data, string optionalMessage = "")
    {
        return Json(new { data = data, status = "success", message = optionalMessage }, JsonRequestBehavior.AllowGet);
    }

    public JsonResult JsonSuccessResult(string message)
    {
        return Json(new { data = "", status = "success", message = message }, JsonRequestBehavior.AllowGet);
    }

    public JsonResult JsonErrorResult(string message)
    {
        return Json(new { data = "", status = "error", message = message }, JsonRequestBehavior.AllowGet);
    }

    public JsonResult JsonRawResult(object data)
    {
        return Json(data, JsonRequestBehavior.AllowGet);
    }

Ajax.BeginFormの代わりに$ .ajaxを使用することについて、私はJquery ajaxを使用したいと思いますが、全世界で私がAjax.BeginFormでいっぱいのアプリケーションを持っていることを決定するのは私ではなく、もちろんそれはしませんでした。しかし、私はそれと一緒に暮らさなければなりません。

したがって、開始フォームにも成功コールバックがあります。コールバックを使用するためにjquery ajaxを使用する必要はありません 。Ajax.BeginForm、Calls Action、Return JSON、OnSuccess JS関数でJSONオブジェクトにアクセスするにはどうすればよいですか?

ありがとう


0

JavaScriptクラスからリダイレクトする場合

同じビュー-別のコントローラー

<strike>window.location.href = `'Home'`;</strike>

同じビューではありません

<strike>window.location.href = `'Index/Home'`;</strike>

0

ヘルパークラスを追加します。

public static class Redirector {
        public static void RedirectTo(this Controller ct, string action) {
            UrlHelper urlHelper = new UrlHelper(ct.ControllerContext.RequestContext);

            ct.Response.Headers.Add("AjaxRedirectURL", urlHelper.Action(action));
        }

        public static void RedirectTo(this Controller ct, string action, string controller) {
            UrlHelper urlHelper = new UrlHelper(ct.ControllerContext.RequestContext);

            ct.Response.Headers.Add("AjaxRedirectURL", urlHelper.Action(action, controller));
        }

        public static void RedirectTo(this Controller ct, string action, string controller, object routeValues) {
            UrlHelper urlHelper = new UrlHelper(ct.ControllerContext.RequestContext);

            ct.Response.Headers.Add("AjaxRedirectURL", urlHelper.Action(action, controller, routeValues));
        }
    }

次に、アクションを呼び出します。

this.RedirectTo( "Index"、 "Cement");

すべてのajaxリクエストをインターセプトするために、JavaScriptコードをグローバルJavaScriptに含まれるファイルまたはレイアウトファイルに追加します。

<script type="text/javascript">
  $(function() {
    $(document).ajaxComplete(function (event, xhr, settings) {
            var urlHeader = xhr.getResponseHeader('AjaxRedirectURL');

            if (urlHeader != null && urlHeader !== undefined) {
                window.location = xhr.getResponseHeader('AjaxRedirectURL');
            }
        });
  });
</script>


0

ben fosterが言うように、Javascriptを返すことができ、希望のページにリダイレクトされます。

現在のページにページをロードするには:

return JavaScript("window.location = 'http://www.google.co.uk'");'

新しいタブにページを読み込むには:

return JavaScript("window.open('http://www.google.co.uk')");

0

これらのメタリフレッシュタグの1つを配置することで、ajax呼び出しから非jsベースのリダイレクトを取得できます。これはここで機能しているようです: return Content("<meta http-equiv=\"refresh\" content=\"0;URL='" + @Url.Action("Index", "Home") + "'\" />");

注:メタリフレッシュがFirefoxによって自動的に無効にされていることを発見しました。これはあまり役に立ちません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.