Question

Je veux éviter d'avoir beaucoup de if Request.IsAjaxRequest() dans mes contrôleurs. Je pensais que si je pouvais condenser cette logique à un ActionFilter il serait facile d'adopter une convention dans ma demande de fournir une deuxième action pour toute demande que peut utiliser Ajax, tout en offrant une chute en arrière si JavaScript est désactivé.

public ActionResult Details(int id)
{
  // called normally, show full page
}

public ActionResult Details_Ajax(int id)
{
  // called through ajax, return a partial view
}

Je pensais que je pouvais d'abord faire quelque chose comme ceci:

public class AjaxRenameAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RouteData.Values["action"] = filterContext.RouteData.Values["action"] + "_Ajax";

    }

Mais ça ne marchera pas parce que l'action d'invoquer est décidé et les filtres sur elle sont traitées.

Je ne veux pas vraiment retourner un RedirectResult chaque fois que quelqu'un appelle une action, il semble un peu inutile de doubler le nombre de demandes de Http.

Y at-il une autre façon d'acheminer par la demande d'une autre action? Ou est-ce que je fais déconseillés et je chercher une meilleure façon de faire?

Vive

Était-ce utile?

La solution

AcceptAjaxAttribute est probablement ce qui est nécessaire ici; cependant, je voudrais proposer une autre façon de penser à ce problème.

Toutes les requêtes Ajax sont égales. Une requête Ajax pourrait essayer d'accomplir l'une des choses suivantes:

  • Liaison de données JSON à un réseau riche (comme jqGrid);
  • Parsing / transformation de données XML, comme un flux RSS;
  • Chargement en cours HTML partiel dans une zone de la page;
  • chargement de manière asynchrone un script (google.load peut le faire);
  • Manutention un message à sens unique à partir du client;
  • Et sans doute un peu plus que j'oublie.

Lorsque vous «sélectionnez » une « action alternative » spécifique basée uniquement sur la méthode de IsAjaxRequest, vous liez quelque chose de très générique - une requête asynchrone - à des fonctionnalités spécifiques sur le serveur. Il va finalement rendre votre conception plus fragile et également rendre votre contrôleur plus difficile à tester l'unité (bien qu'il existe des façons de le faire, vous pouvez moquez le contexte).

Un bien conçu Action devrait être cohérente , il ne devrait se soucier ce la demande était et pas comment la demande a été faite. On pourrait pointer vers d'autres attributs tels que AuthorizeAttribute comme des exceptions, mais je ferais une distinction pour les filtres, qui la plupart du temps décrivent le comportement qui doit se produire soit un « avant » ou « après » l'action se déroule, non « au lieu de. «

Obtenir au point ici, l'objectif déclaré dans la question est bonne; vous devriez certainement ont des méthodes différentes pour ce qui est décrit comme correctement les différentes actions:

public ActionResult Details(int id)
{
    return View("Details", GetDetails(id));
}

public ActionResult JsonDetails(int id)
{
    return Json(GetDetails(id));
}

public ActionResult PartialDetails(int id)
{
    return PartialView("DetailTable", GetDetails(id));
}

Et ainsi de suite. Cependant, à l'aide d'un sélecteur d'action Ajax pour choisir entre ces méthodes suit la pratique de « dégradation gracieuse » , qui a essentiellement été remplacé (au moins OMI) par amélioration progressive .

Voilà pourquoi, bien que j'aime ASP.NET MVC, j'évitons surtout les AjaxHelper, parce que je ne trouve pas qu'il exprime ce concept bien; il essaie de se cacher trop de vous. Au lieu d'avoir le concept d'un « formulaire Ajax » ou une « action Ajax », nous allons en finir avec la distinction et le bâton à HTML droite, puis injecter la fonctionnalité Ajax séparément une fois que nous sommes certains que le client peut gérer .

Voici un exemple dans jQuery - bien que vous pouvez le faire dans MS AJAX trop:

$(function() {
    $("#showdetails").click(function() {
        $("#details").load("PartialDetails", { id: <%= Record.ID %> });
        return false;
    }
});

Ceci est tout ce qu'il faut pour injecter Ajax dans une page MVC. Commencez par un lien ancien HTML brut et la remplacer par un appel Ajax qui va à une action de contrôleur différent .

Maintenant, si quelque part ailleurs sur votre site, vous décidez que vous voulez utiliser à la place une grille, mais ne voulez pas casser les pages en utilisant le rendu partiel, vous pouvez écrire quelque chose comme ça (disons que vous avez un seul maître- page de détail avec une liste des « commandes » sur le côté gauche et une table de détail à droite):

$(".detaillink").click(function() {
    $('#detailGrid').setGridParam({
        url: $(this).attr("href").replace(/\/order\/details/i,
            "/order/jsondetails")
    }); 
    $("#detailGrid").trigger("reloadGrid");  
});

Cette approche découple complètement le comportement des clients du comportement du serveur. Le serveur est effectivement dit au client: Si vous voulez la version JSON, demander pour la version JSON, et oh, en passant, voici un script pour convertir vos liens si vous savez comment pour l'exécuter. pas sélecteurs d'action et finagling avec surcharges de méthode, pas moqueur spécial que vous devez faire pour exécuter un test simple, pas de confusion sur l'action qui fait quoi et quand. Juste quelques lignes de JavaScript. Les actions du contrôleur sont courts et doux, exactement comme ils devraient être.

Ce n'est pas la seule approche. De toute évidence, des classes telles que AcceptAjaxAttribute existent parce qu'ils attendaient certains développeurs d'utiliser la méthode de détection demande. Mais après avoir expérimenté un peu avec les deux, je trouve cette façon beaucoup plus facile à raisonner et donc plus facile à concevoir / code correctement.

Autres conseils

Qu'en est-il accepter l'Ajax attribut dans Mvc Futures?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top