2009-06-17 25 views
4

J'utilise la propriété UserData du FormsAuthenticationTicket pour stocker des informations spécifiques à l'utilisateur. J'ai une HelperClass qui désérialise cette UserData en un objet personnalisé pour un accès fortement typé. J'ai la configuration de mon contrôleur comme suitAccès à Request.Cookies à partir d'un constructeur de contrôleur

public class SomeController : Controller 
{ 
    private CookieData _cookieData; 

    public SomeController() 
    { 
     _service = new ForderungsStellerService(new ModelStateWrapper(this.ModelState)); 
     HttpCookie cookie = Request.Cookies[FormsAuthentication.FormsCookieName]; 
     FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value); 
     _cookieData= GetSessionData.FromCookie(ticket); 
    } 
} 

Le problème semble être que la demande est nulle au moment de la construction du contrôleur. Lorsque vous accédez à Request.Cookies à partir d'une méthode ActionMethod, cet extrait fonctionne.

Je souhaite que l'objet _cookieData soit rempli dans le constructeur pour des raisons DRY.

Est-ce que quelqu'un a un indice sur ce problème?

meilleures salutations ...

Répondre

6

Je voudrais créer un ModelBinder qui comprend CookieData et comment sortir de l'objet de la requête. Je crains le code de création de test unitaire nécessaire pour rendre le constructeur heureux. Si vous le prenez comme paramètre pour le contrôleur avec un classeur modèle, vous pouvez éviter ce surcoût de test.

public class SomeController : Controller 
{ 
    // only need to pass in the data object for unit testing. 
    // ModelBinder takes care of DRY 
    public ActionResult Index(CookieData cookieData) 
    { 
    } 
} 

La réponse à pourquoi il ne fonctionne pas dans le constructeur est que le contrôleur n'a pas été initialisé avec le ControllerContext à ce moment-là.

public HttpContextBase HttpContext { 
    get { 
    return ControllerContext == null 
     ? null 
     : ControllerContext.HttpContext; 
    } 
} 

Si vous vraiment voulez le faire dans le constructeur (ne pas) puis utilisez HttpContext.Request au lieu de l'emballage. Mais en faisant cela, vous aurez rendu votre code impossible à tester et votre alignement diminuera de 3 points.

+0

Merci pour cela. Résolu mon problème ... – Gordon

0

Il est bon d'être DRY mais dans le cas de ASP.NET MVC, il signifie le plus souvent l'utilisation d'un attribut de filtre personnalisé ou comme talljoe a montré un modèle de classeur.

public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     HttpCookie cookie = filterContext.HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName]; 
     FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value); 
     filterContext.ActionParameters["CookieData"] = GetSessionData.FromCookie(ticket); 


     base.OnActionExecuting(filterContext); 
    } 
5

Remplacer Controller.Initialize():

protected override void Initialize(RequestContext requestContext) { 
    base.Initialize(requestContext); 
    // do further initialization here 
} 

propriétés comme demande, etc. sera disponible pour vous après l'appel à base.Initialize(). L'utilisation d'un ModelBinder est une bonne idée.

+0

Aussi une bonne solution. Cela fonctionnerait, mais rendit unittests plus difficile comme il se doit. – Gordon

+0

Gordon a raison. Préférez utiliser la solution de Talljoe pour une solution plus faiblement couplée et plus facilement testable au problème. –

Questions connexes