28 votes

ASP.NET MVC - Définir ViewData pour la page principale dans le contrôleur de base

Je suis à l'aide d'une masterpage dans mon ASP.NET projet MVC. Cette masterpage s'attend à une certaine ViewData d'être présent, ce qui les affiche sur chaque page.

Si je ne définissez pas cette ViewData clé dans ma contrôleurs, j'obtiens une erreur qu'il ne peut pas le trouver. Cependant, je ne veux pas définir la ViewData dans chaque contrôleur (je ne veux pas dire ViewData["foo"] = GetFoo(); dans chaque contrôleur).

Donc, je pensais à la définition de cette dans un contrôleur de base, et ont chaque contrôleur qui héritent de ce contrôleur de base. Dans le contrôleur de base par défaut constructur, j'ai mis le ViewData. J'ai trouvé une approche similaire ici: http://www.asp.net/learn/MVC/tutorial-13-cs.aspx. C'est très bien, cela fonctionne... mais le problème est que ces données proviennent d'une base de données quelque part.

Maintenant, quand je veux Unité de Tester mes contrôleurs, ceux qui héritent de la base de contrôleur fait appel à son constructeur par défaut. Dans le constructeur par défaut, j'initialise ma classe de dépôt pour obtenir ces données à partir de la base de données. Résultat: mon unité tests échouent, car il ne peut pas accéder aux données (et je ne veux l'accès à ces données).

Je n'ai pas envie de passer à la correcte Référentiel (ou DataContext, quelle que soit la marque) classe à chaque contrôleur qui, à son tour transmettre au contrôleur par défaut, sur lequel j'ai pu ensuite se moquer de mes tests unitaires. Les contrôleurs à son tour compter sur d'autres classes de dépôt, et j'ai passé plusieurs paramètres du constructeur. Trop de travail pour mon sentiment, ou je me trompe? Est-il une autre solution?

J'ai essayé à l'aide de StructureMap mais à la fin je n'ai pas l'impression que ça va régler mon problème, étant donné que chaque contrôleur de toujours appeler le constructeur de base qui permet d'initialiser la classe de référentiel, donc je ne peux pas s'en moquer.

C' est une question similaire, mais je ne trouve aucune réponse satisfaisante n'a été donnée. Puis-je résoudre ce une façon soignée, peut-être à l'aide de StructureMap comme une solution? Ou devrais-je simplement le sucer et le passage d'un Référentiel à chaque contrôleur et de passer encore une fois pour le contrôleur de base? De nouveau, Il se sent comme autant de travail pour quelque chose de si simple. Merci!

44voto

eu-ge-ne Points 17847

Je vois deux options:

Premier:

Définissez ViewData pour MasterPage dans YourBaseController.OnActionExecuting () ou YourBaseController.OnActionExecuted ():

 public class YourBaseController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // Optional: Work only for GET request
        if (filterContext.RequestContext.HttpContext.Request.RequestType != "GET")
            return;

        // Optional: Do not work with AjaxRequests
        if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
            return;

        ...

        filterContext.Controller.ViewData["foo"] = ...
    }
}
 

Seconde:

Ou créez un filtre personnalisé:

 public class DataForMasterPageAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // Optional: Work only for GET request
        if (filterContext.RequestContext.HttpContext.Request.RequestType != "GET")
            return;

        // Optional: Do not work with AjaxRequests
        if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
            return;

        ...

        filterContext.Controller.ViewData["foo"] = ...
    }
}
 

puis appliquez à vos contrôleurs:

 [DataForMasterPage]
public class YourController : YourBaseController
{
    ...
}
 

Je pense que la deuxième solution est exactement pour votre cas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X