2010-12-13 24 views
1

Nous disposons d'une plate-forme en blanc construite sur Asp.Net MVC2. À l'heure actuelle, le site dispose de 6 contrôleurs, ainsi que de toutes les vues de base, etc., qui peuvent lui permettre de fonctionner dès la sortie de la boîte. Jusqu'à présent, nous avons construit 5 sites et tout a été génial.Etendez le site MVC existant pour transmettre de nouvelles données dans ViewData pour chaque action

Maintenant, cependant, j'ai une exigence qui signifie que je dois être en mesure de passer un nouveau morceau de données (dans le dictionnaire ViewData sera bien) à toutes les vues de toute action. Ces données sont ensemencées à partir d'une chaîne de requête, puis d'un cookie. L'une des principales raisons à cela est de pouvoir ajouter une image supplémentaire à la page maître du site en fonction de la valeur de ces données. Je pourrais bien sûr être vraiment sale et placer le code de désérialisation dans la page maître; mais je préfère trouver un moyen de s'assurer qu'il est ajouté à la ViewData pour chaque requête qui n'implique pas l'héritage du contrôleur et la méthode d'action remplaçant (!).

Toutes les idées grandement grandement appréciées!

Répondre

4

Vous pouvez écrire un attribut de filtre d'action personnalisé et appliquer cet attribut à un contrôleur de base ou toutes les actions qui ont besoin d'avoir ces informations injectées:

public class AdditionalViewDataInjectorAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     base.OnActionExecuted(filterContext); 
     filterContext.Controller.ViewData["foo"] = "bar"; 
    } 
} 

Et puis décorer votre contrôleur de base avec cet attribut:

[AdditionalViewDataInjector] 
public class BaseController: Controller { } 

Dans ASP.NET MVC 3, il existe une notion de global action filters afin que vous n'ayez même pas besoin d'un contrôleur de base ou de décorer toutes vos actions avec ce filtre. Il y a un workaround allowing you to achieve the same in ASP.NET MVC 2. Maintenant, toutes vos vues obtiennent cette propriété supplémentaire dans les données de la vue. Cela étant dit, le précédent est une solution de contournement laide et pas quelque chose que je recommanderais (ViewData is laid). Vous pouvez jeter un oeil à Html.Action and Html.RenderAction helpers. Voici comment cela pourrait ressembler:

public class MySpecialController: Controller 
{ 
    public ActionResult Index() 
    { 
     // Here you have access to the request, cookies, session, routes, ... 
     var someModel = GetSomeModel(); 
     return View(someModel); 
    } 
} 

ont alors une qui partielle fortement typé contiendra le code HTML requis (~/Views/MySpecial/Index.ascx) et enfin inclure dans votre page maître:

<%= Html.Action("index", "myspecial") %> 
+0

Genius - la dernière solution d'utilisation des actions enfants fonctionne absolument parfaitement et s'intègre parfaitement avec la façon dont le site se cumule déjà. J'ai les données en tant que paramètre de méthode d'action qui utilise un classeur de modèle personnalisé (qui interagit avec les cookies et la chaîne de requête), qui déclenche alors une vue partielle pour le contenu, passant simplement l'objet lié en tant que modèle. Le maître utilise alors simplement une seule ligne Html.RenderAction() et maintenant il fonctionne sur toutes les pages. Merci :) –

0

Remplacer OnResultExecuting dans votre contrôleur de base et ajouter les données requises à la propriété ViewData ..

public override void OnResultExecuting(ResultExecutingContext ctx) { 
    ViewData["title"] = "Hello world!"; 
    base.OnResultExecuting(ctx); 
}