web-dev-qa-db-fra.com

Comment obtenir une réponse ASP.NET MVC Ajax à rediriger vers une nouvelle page au lieu d'insérer une vue dans UpdateTargetId?

J'utilise Ajax.BeginForm pour créer un formulaire qui effectuera une publication ajax sur une action du contrôleur. Si l'action réussit, l'utilisateur doit être redirigé vers une autre page (si l'action échoue, un message d'état s'affiche à l'aide de 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]
   }

Si la suppression réussit, je retourne un résultat de redirection:

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

Mais la vue Index du contrôleur domestique est chargée dans UpdateTargetId et, par conséquent, je me retrouve avec une page dans une page. Deux choses auxquelles je pense:

  1. Soit je suis architecte de cette mauvaise et doit gérer ce type d'action différemment (ne pas utiliser ajax).
  2. Au lieu de renvoyer un résultat de redirection, retournez une vue contenant du code javascript qui effectue la redirection du côté client.

Est-ce que quelqu'un a des commentaires sur # 1? Ou si # 2 est une bonne solution, à quoi ressemblerait la "vue javascript redirigée"?

83
Jeff Widmer

Vous pouvez utiliser JavascriptResult pour y parvenir.

Pour rediriger:

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

Pour recharger la page en cours:

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

Semble l’option la plus simple.

167
Ben Foster

Vous pouvez renvoyer un JSON avec l'URL et modifier le window.location à l'aide de JavaScript côté client. Je préfère cette façon que d'appeler une fonction JavaScript à partir du serveur, ce qui, à mon avis, brise la séparation des préoccupations.

Du côté serveur:

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

Côté client:

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

Bien sûr, vous pouvez ajouter plus de logique car il pourrait y avoir une erreur côté serveur et dans ce cas, la propriété result pourrait indiquer cette situation et éviter la redirection.

24

Le comportement que vous essayez de produire n’est pas vraiment optimal avec AJAX. Il est préférable d'utiliser AJAX si vous souhaitez uniquement mettre à jour une partie de la page, sans la rediriger complètement vers une autre page. Cela va à l’encontre de l’objectif même de AJAX.

Je suggérerais simplement de ne pas utiliser AJAX avec le comportement que vous décrivez.

Vous pouvez également utiliser jquery Ajax pour soumettre la demande, puis spécifier un rappel lorsque la demande est terminée. Dans le rappel, vous pouvez déterminer s'il a échoué ou réussi et rediriger vers une autre page en cas de succès. Jquery Ajax est beaucoup plus facile à utiliser, d’autant plus que j’utilise déjà la bibliothèque pour d’autres tâches.

Vous pouvez trouver de la documentation sur jquery ajax here , mais la syntaxe est la suivante:

jQuery.ajax( options )  

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

jQuery.getJSON( url, data, callback )

jQuery.getScript( url, callback )

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

Bien que pas élégant, travaille pour moi dans certaines situations.

contrôleur

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

Modèle

    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>
11
Valamas

Utiliser JavaScript fera certainement le travail.

Vous pouvez également utiliser Content s'il s'agit davantage de votre style.

Exemple:

contrôleur 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
christo8989

Vous pouvez simplement écrire dans Ajax Success comme ci-dessous:

 $.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");
            }
});
3
Hiren Patel

Vous pouvez simplement faire une sorte de filtre de réponse ajax pour les réponses entrantes avec $. AjaxSetup. Si la réponse contient une redirection MVC, vous pouvez évaluer cette expression du côté JS. Exemple de code pour JS ci-dessous:

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

Si les données sont: "window.location = '/ Acount/Login'" ci-dessus, le filtre intercepte cela et évalue la redirection.

1

Que dis-tu de ça :

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

et ensuite

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

O

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

Je devais le faire parce que j'ai un formulaire de connexion ajax. Lorsque les utilisateurs se connectent avec succès, je redirige vers une nouvelle page et mets fin à la requête précédente car l'autre page gère la redirection vers la partie de confiance (car il s'agit d'un système STS SSO).

Cependant, je voulais aussi que cela fonctionne avec javascript désactivé, étant le saut de connexion central et tout, alors je suis venu avec cela,

    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
Ryan Mann

Comme Ben Foster dit que vous pouvez retourner les Javascripts et il vous redirigera vers la page souhaitée.

Pour charger la page dans la page en cours:

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

Pour charger la page dans le nouvel onglet:

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

Je ne suis pas satisfait de la meilleure réponse de Joseph, au lieu de résoudre le problème correct, il a dit que c'était un cas d'utilisation erroné. En fait, il existe de nombreux endroits, par exemple, si vous convertissez une ancienne base de code en code ajaxifié et que vous en A BESOIN, vous en avez BESOIN. En programmation, il n’ya aucune excuse car ce n’est pas seulement vous qui codez ses bons et mauvais développeurs et vous devez travailler côte à côte. Donc, si je ne redirige pas le code en ajax, mon collègue développeur peut me forcer à avoir une solution. Tout comme j'aime utiliser tous les sites AMD à motifs ou mvc4, et mon entreprise peut m'éloigner de ce site pendant un an.

Alors parlons de la solution maintenant.

J'ai fait énormément mal en matière de traitement des demandes et des réponses ajax et le moyen le plus simple que j'ai découvert consistait à envoyer des codes d'état au client et à disposer d'une fonction javascript standard pour comprendre ces codes. Si je vous envoie simplement par exemple le code 13, cela pourrait signifier une redirection.

Donc, une réponse json comme {statusCode: 13, message: '/ home/connecté'} bien sûr, il y a des tonnes de variations proposées comme {status: 'success', code: 13, url: '/ home/connecté ', message:' Vous êtes connecté maintenant '}

etc, donc jusqu'à votre choix de messages standard

Habituellement, je hérite de la classe de base Controller et mets mon choix de réponses standard comme ceci

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

À propos de l'utilisation de $ .ajax au lieu de Ajax.BeginForm J'aimerais utiliser Jquery ajax et moi, mais encore une fois, ce n'est pas moi dans le monde entier de prendre des décisions. J'ai une application complète d'Ajax.BeginForm et bien sûr je ne l'ai pas fait. Mais je dois vivre avec ça.

Donc, il y a aussi un rappel de succès dans le formulaire begin, vous n'avez pas besoin d'utiliser jquery ajax pour utiliser des rappels. Quelque chose à ce sujet ici Ajax.BeginForm, Appels Action, Retourne JSON, Comment puis-je accéder à l'objet JSON dans ma fonction OnSuccess JS ?

Merci

0
Asif Ashraf

Vous pouvez obtenir une redirection non basée sur js à partir d'un appel ajax en insérant l'une de ces balises meta refresh. Cela semble fonctionner ici: return Content("<meta http-equiv=\"refresh\" content=\"0;URL='" + @Url.Action("Index", "Home") + "'\" />");

Remarque: j'ai découvert que Firefox actualise automatiquement les méta-actualisations, ce qui n'est pas très utile.

0
Vasily Hall

Si vous êtes redirigé depuis la classe JavaScript

même vue - contrôleur différent

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

n'est pas la même vue

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

Ajouter une classe d'assistance:

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

alors appelez dans votre action:

this.RedirectTo ("Index", "Ciment");

Ajoutez du code javascript à n’importe quel fichier inclus de javascript ou de mise en page global pour intercepter toutes les requêtes 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
faisale