如何获得ASP.NET MVC Ajax响应以重定向到新页面,而不是将视图插入UpdateTargetId?


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中,因此我最终在页面中找到一个页面。我在考虑两件事:

  1. 我要么在构造这个错误,要么应该以不同的方式处理这种类型的操作(不使用ajax)。
  2. 而不是返回重定向结果,而是返回其中包含JavaScript的视图,该视图在客户端进行重定向。

有人对#1有意见吗?或者,如果#2是一个好的解决方案,那么“重定向javascript视图”会是什么样?

Answers:


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显示了如何默认情况下使用基本控制器来应用此功能。
亚当·斯派塞

@Ben Foster:使用此浏览器尝试打开URL http :: window.location ..。我张贴这在单独的问题stackoverflow.com/questions/13896307/...
安德鲁斯

30
如果要重定向到项目中的控制器,则可以使用Url帮助器。例如:return JavaScript( "window.location = '" + Url.Action("Edit","Dispatch") + "'" );
克里斯·摩根

2
短。简单。优秀的。大!
维克拉姆

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,在大多数情况下它将成功,然后我可以重定向到“主页索引”页面。在失败的情况下,请显示不同的视图,并显示错误消息和用户应采取的适当措施。听起来还好吗?
杰夫·威德默

是的,听起来更有意义。
约瑟夫

我按照约瑟夫的建议,将其从Ajax提交转换为常规POST。这实际上效果更好,因为它为我提供了一种处理删除确认消息的更简洁的方法。
杰夫·威德默

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恤,2015年

6

使用JavaScript绝对可以完成工作。

Content如果这更符合您的风格,也可以使用。

例:

MVC控制器

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

Java脚本

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

我对约瑟夫的最佳答案并不满意,他没有解决正确的问题,而是说这是错误的用例。实际上,有很多地方,例如,如果您要将旧的代码库转换为Ajaxified代码,并且需要它,那么就需要它。在编程中没有任何借口,因为不仅是您在编码所有不好的开发人员,而且还必须一起工作。因此,如果我不使用ajax进行代码重定向,那么我的开发人员可以强迫我为此解决方案。就像我喜欢使用所有AMD模式的站点或mvc4一样,我的公司可以让我远离它一年。

现在让我们谈谈解决方案。

我已经完成了ajax请求和响应处理的工作,我发现的最简单的方法是将状态代码发送给客户端,并具有一个标准的javascript函数来理解这些代码。如果我仅发送例如代码13,则可能意味着重定向。

因此,像{statusCode:13,messsage:'/ home / logged-in}这样的json响应当然建议了很多变化,例如{status:'success',代码: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 intead,我很乐意使用Jquery ajax,但我在全世界范围内做出的决定并不是我本人拥有一个充满Ajax.BeginForm的应用程序,当然我没有这样做。但是我必须忍受它。

因此,begin形式中也有一个成功的回调,您无需使用jquery ajax来使用回调 。Ajax.BeginForm,调用Action,返回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”);

将javascript代码添加到任何全局javascript包含的文件或布局文件中,以拦截所有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

正如benoster所说,您可以返回Javascript,它将把您重定向到所需的页面。

要将页面加载到当前页面中:

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

要将页面加载到新标签中:

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

0

您可以通过放置这些元刷新标签之一来从ajax调用中获得基于非js的重定向。这似乎在工作: return Content("<meta http-equiv=\"refresh\" content=\"0;URL='" + @Url.Action("Index", "Home") + "'\" />");

注意:我发现Firefox会自动禁用元刷新,因此这不是很有用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.