Làm cách nào để nhận được phản hồi ASP.NET MVC Ajax để chuyển hướng đến trang mới thay vì chèn chế độ xem vào UpdateTargetId?


88

Tôi đang sử dụng Ajax.BeginForm để tạo một biểu mẫu sẽ thực hiện đăng lại ajax cho một hành động nào đó của bộ điều khiển và sau đó nếu hành động thành công, người dùng sẽ được chuyển hướng đến một trang khác (nếu hành động không thành công thì thông báo trạng thái sẽ được hiển thị bằng cách sử dụng 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]
   }

Nếu xóa thành công, tôi sẽ trả về kết quả Chuyển hướng:

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

Nhưng chế độ xem Chỉ mục Bộ điều khiển Trang chủ đang được tải vào UpdateTargetId và do đó tôi kết thúc với một trang trong một trang. Hai điều tôi đang nghĩ đến:

  1. Hoặc tôi đang kiến ​​trúc sai và nên xử lý loại hành động này theo cách khác (không sử dụng ajax).
  2. Thay vì trả về kết quả Chuyển hướng, hãy trả về một dạng xem có javascript trong đó thực hiện chuyển hướng ở phía máy khách.

Có ai có ý kiến ​​về # 1 không? Hoặc nếu # 2 là một giải pháp tốt, thì "chế độ xem javascript chuyển hướng" sẽ như thế nào?

Câu trả lời:


171

Bạn có thể sử dụng JavascriptResultđể đạt được điều này.

Để chuyển hướng:

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

Để tải lại trang hiện tại:

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

Có vẻ là lựa chọn đơn giản nhất.


4
Tuyệt vời .. Đã giúp tôi ra ngoài.
CrazyCoderz

1
Tôi đồng ý, đây là cách tiếp cận đúng. Câu trả lời này stackoverflow.com/a/2841608/498969 hiển thị cách bạn có thể áp dụng chức năng này theo mặc định bằng bộ điều khiển cơ sở.
Adam Spicer

@Ben Foster: Sử dụng trình duyệt này sẽ cố gắng mở url http :: window.location ... Tôi đã đăng câu hỏi này dưới dạng câu hỏi riêng trong stackoverflow.com/questions/13896307/…
Andrus,

30
Nếu bạn muốn chuyển hướng đến một bộ điều khiển trong dự án của mình, bạn có thể sử dụng trình trợ giúp Url cho bạn. Ví dụ:return JavaScript( "window.location = '" + Url.Action("Edit","Dispatch") + "'" );
Chris Morgan,

2
Ngắn. Đơn giản. Thông minh. Tuyệt quá!
Vikram

30

Bạn có thể trả về một JSON với URL và thay đổi window.location bằng JavaScript ở phía máy khách. Tôi thích cách này hơn là gọi một hàm JavaScript từ máy chủ, điều mà tôi nghĩ rằng nó phá vỡ sự phân tách của các mối quan tâm.

Phía máy chủ:

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

Phía khách hàng:

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

Tất nhiên, bạn có thể thêm nhiều logic hơn vì có thể có lỗi ở phía máy chủ và trong trường hợp đó, thuộc tính kết quả có thể chỉ ra tình huống này và tránh chuyển hướng.


12

Hành vi bạn đang cố gắng tạo ra không thực sự được thực hiện tốt nhất bằng AJAX. AJAX sẽ được sử dụng tốt nhất nếu bạn chỉ muốn cập nhật một phần của trang, không chuyển hướng hoàn toàn đến một số trang khác. Điều đó thực sự đánh bại toàn bộ mục đích của AJAX.

Tôi khuyên bạn không nên sử dụng AJAX với hành vi mà bạn đang mô tả.

Ngoài ra, bạn có thể thử sử dụng jquery Ajax, nó sẽ gửi yêu cầu và sau đó bạn chỉ định một lệnh gọi lại khi yêu cầu hoàn tất. Trong cuộc gọi lại, bạn có thể xác định xem nó không thành công hay thành công và chuyển hướng đến một trang khác thành công. Tôi thấy jquery Ajax dễ sử dụng hơn nhiều, đặc biệt là vì dù sao thì tôi cũng đã sử dụng thư viện cho những thứ khác.

Bạn có thể tìm tài liệu về jquery ajax tại đây , nhưng cú pháp như sau:

jQuery.ajax( options )  

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

jQuery.getJSON( url, data, callback )

jQuery.getScript( url, callback )

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

Vì vậy, sau đó chỉ cần thực hiện một ĐĂNG thông thường cho hành động Xóa và trong hầu hết các trường hợp, nó sẽ thành công và sau đó tôi có thể chuyển hướng đến trang Chỉ mục trang chủ. Trong trường hợp không thành công, hãy hiển thị một dạng xem khác với các thông báo lỗi và hành động thích hợp để người dùng thực hiện. Nghe ổn chứ?
Jeff Widmer

Vâng, điều đó nghe có vẻ như nó sẽ có ý nghĩa hơn.
Joseph

Tôi đã tiếp tục chuyển đổi điều này từ một bản gửi Ajax thành một BÀI ĐĂNG thông thường theo khuyến nghị của Joseph. Điều này thực sự hoạt động tốt hơn vì nó cung cấp cho tôi một cách rõ ràng hơn để xử lý thông báo xác nhận xóa.
Jeff Widmer

12

Mặc dù không thanh lịch nhưng phù hợp với tôi trong một số tình huống nhất định.

Bộ điều khiển

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

Mô hình

    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
Tại sao không thanh lịch? Nó được gõ mạnh và có cảm giác rõ ràng. Tôi thích cách tiếp cận đó. +1
T-moty

6

Sử dụng JavaScriptchắc chắn sẽ làm công việc.

Bạn cũng có thể sử dụng Contentnếu đây là phong cách của bạn.

Thí dụ:

Bộ điều khiển MVC

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

Javascript

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

Cảm ơn bạn! Điều này thực sự đã giúp tôi.
dee

5

Bạn chỉ cần viết trong Ajax Success như sau:

 $.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

Còn cái này thì sao :

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

Và sau đó

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

Hoặc là

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

1

Tôi cần làm điều này vì tôi có biểu mẫu đăng nhập ajax. Khi người dùng đăng nhập thành công, tôi chuyển hướng đến một trang mới và kết thúc yêu cầu trước đó vì trang kia xử lý chuyển hướng trở lại bên phụ thuộc (vì đó là Hệ thống STS SSO).

Tuy nhiên, tôi cũng muốn nó hoạt động với javascript bị vô hiệu hóa, là bước đăng nhập trung tâm và tất cả, vì vậy tôi đã nghĩ ra điều này,

    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

Bạn có thể chỉ cần thực hiện một số loại bộ lọc phản hồi ajax để đưa ra các phản hồi với $ .ajaxSetup . Nếu phản hồi chứa chuyển hướng MVC, bạn có thể đánh giá biểu thức này ở phía JS. Mã mẫu cho JS bên dưới:

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

Nếu dữ liệu là: "window.location = '/ Acount / Login'", bộ lọc trên sẽ nắm bắt điều đó và đánh giá để thực hiện chuyển hướng.


0

Tôi không hài lòng với câu trả lời tốt nhất của Joseph, thay vì sửa chữa vấn đề chính xác, anh ấy nói rằng đây là trường hợp sử dụng sai. Trong thực tế, có rất nhiều nơi, ví dụ nếu bạn đang chuyển đổi một cơ sở mã cũ thành mã không chính xác và ở đó bạn CẦN nó, thì bạn CẦN nó. Trong lập trình không có lý do gì bởi vì không chỉ bạn viết mã mà tất cả các nhà phát triển tốt và xấu và bạn phải làm việc cùng nhau. Vì vậy, nếu tôi không chuyển hướng mã trong ajax, nhà phát triển đồng nghiệp của tôi có thể buộc tôi phải có giải pháp cho nó. Cũng giống như tôi thích sử dụng tất cả các trang web theo khuôn mẫu của AMD hoặc mvc4, và công ty của tôi có thể khiến tôi không sử dụng nó trong một năm.

Vì vậy, chúng ta hãy nói về giải pháp bây giờ.

Tôi đã thực hiện rất nhiều việc xử lý yêu cầu và phản hồi ajax và cách đơn giản nhất mà tôi tìm ra là gửi mã trạng thái đến máy khách và có một hàm javascript tiêu chuẩn để hiểu các mã đó. Nếu tôi chỉ gửi mã ví dụ 13, nó có thể có nghĩa là chuyển hướng.

Vì vậy, một phản hồi json như {statusCode: 13, messsage: '/ home / logged-in'}, tất nhiên có rất nhiều biến thể được đề xuất như {status: 'success', mã: 13, url: '/ home / logged-in ', message:' Bạn đã đăng nhập ngay bây giờ '}

vv, do đó tùy thuộc vào sự lựa chọn của riêng bạn về các thông báo tiêu chuẩn

Thông thường, tôi Kế thừa từ lớp Bộ điều khiển cơ sở và đặt lựa chọn của tôi về các phản hồi tiêu chuẩn như thế này

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);
    }

Về việc sử dụng $ .ajax intead của Ajax.BeginForm Tôi rất thích sử dụng Jquery ajax và tôi thì có, nhưng một lần nữa tôi không phải là người trên toàn thế giới để đưa ra quyết định Tôi có một ứng dụng đầy Ajax.BeginForm và tất nhiên là tôi đã không làm điều đó. Nhưng tôi phải sống với nó.

Vì vậy, cũng có một cuộc gọi lại thành công trong biểu mẫu bắt đầu, bạn không cần phải sử dụng jquery ajax để sử dụng lệnh gọi lại Một vài điều về nó ở đây Ajax.BeginForm, Hành động gọi, Trả về JSON, Làm cách nào để truy cập đối tượng JSON trong Hàm OnSuccess JS của tôi?

Cảm ơn


0

Nếu bạn chuyển hướng từ lớp JavaScript

cùng xem - bộ điều khiển khác nhau

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

không phải là cùng một quan điểm

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

0

Thêm một lớp người trợ giúp:

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));
        }
    }

Sau đó, hãy gọi hành động của bạn:

this.RedirectTo ("Chỉ mục", "Xi măng");

Thêm mã javascript vào bất kỳ tệp bố cục hoặc tệp được bao gồm javascript chung nào để chặn tất cả các yêu cầu ajax:

<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

Như ben nuôi nói rằng bạn có thể trả lại Javascrip và nó sẽ chuyển hướng bạn đến trang mong muốn.

Để tải trang trong trang hiện tại:

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

Để tải trang trong tab mới:

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

0

Bạn có thể nhận chuyển hướng không dựa trên js từ lệnh gọi ajax bằng cách đặt một trong các thẻ làm mới meta đó. Điều này ở đây dường như đang hoạt động: return Content("<meta http-equiv=\"refresh\" content=\"0;URL='" + @Url.Action("Index", "Home") + "'\" />");

Lưu ý: Tôi phát hiện ra rằng tính năng làm mới meta tự động bị vô hiệu hóa bởi Firefox, điều này không hữu ích lắm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.