HttpContext.Items avec ASP.NET MVC
-
16-09-2019 - |
Question
J'implimenting ma propre classe ApplicationContext qui utilise le pattern singleton. Je veux conserver mon exemple de celui-ci dans HttpContext.Items, car il est accessible dans toutes les parties de la demande. J'ai lu sur l'utilisation HttpContext avec ASP.NET MVC et l'une des principales douleurs est qu'il introduit la complexité des tests. J'ai essayé de faire des recherches sur la testabilité de HttpContext.Items, mais tout ce que je peux trouver est une chose sur session. L'une des seules choses que je connaisse est celui d'un chapitre de l'échantillon dans le Professional ASP.NET MVC 3.5 livre sur Wrox ( lien pdf ). A la page 15, il dit ceci:
Quelque chose vous ne pouvez pas utiliser: HttpContext.Items Au-dessus de cette section, nous vous sommes propre et dit que nous vous a menti: HttpContext n'est pas partagé entre ASP.NET MVC et ASP.NET Web Forms. En raison de cela, vous ne pouvez pas utiliser la collection HttpContext.Items pour stocker et récupérer des morceaux de données.
La raison de cela est parce qu'une fois que vous redirigez à un contrôleur, votre HttpHandler devient le System.Web.Mvc.MvcHandler, qui est créée en utilisant HttpContextWrapper, qui aura sa propre définition de HttpContext.Current. Malheureusement, au cours de cette poignée de main, des choses comme HttpContext.Items ne sont pas transférés.
Ce que cela se résume à dire que les types de HttpContext, en dépit recherche et de sondage très bien même, ne sont pas les mêmes, et vous ne pouvez pas transmettre des données de cette façon.
Maintenant, je l'ai essayé de tester ceci, et pour autant que je peux dire, si vous rediriger vers un autre contrôleur en utilisant RedirectToAction, HttpContext.Items ne reste. J'utilise le projet par défaut ASP.NET MVC pour tester. Ce que je l'ai fait est, ajouter cette méthode pour Global.asax.cs:
protected void Application_BeginRequest()
{
Context.Items["Test"] = "Hello World";
}
Et dans HomeController.cs, j'ai changé la méthode Index:
public ActionResult Index()
{
return RedirectToAction("About");
}
Et changé la méthode A propos de:
public ActionResult About()
{
Response.Write(Convert.ToString(HttpContext.Items["Test"]));
return View();
}
Quand je lance l'application, la page réoriente correctement / Accueil / A propos et Response.Writes la bonne chaîne « Bonjour tout le monde » situé dans les Global.asax.cs.
Alors, il me semble que si je ne comprends pas non plus ce que le livre est le sens quand ils disent « Les choses comme HttpContext.Items ne sont pas transférés » ou il ne transfère ce genre de choses et il est acceptable d'utiliser HttpContext.Items.
Si vous les gars que je recommande éviter HttpContext.Items, est-il une autre alternative pour stocker un objet à travers une demande sur une base par demande?
La solution
Votre question pose un certain nombre de choses, mais je pense que le point 1 est la réponse que vous recherchez.
-
Est-il bon d'utiliser
Context.Items
pour la mise en cache sur une base par demande? Oui. Si en cours, par demande, par machine dans la batterie de serveurs Web est à vos critères puis Context.Items vous donne cela. -
est difficile
Context.Items
à tester avec? En ce qui concerne la testabilité, je me cachais derrièreContext.Items
une interface de quelque sorte. De cette façon, vous obtenez des capacités de tests unitaires sans faire référenceContext.Items
directement. Sinon, qu'est-ce que vous avez besoin de tester sur lesContext.Items
? Que le cadre stocker et récupérer des valeurs? Gardez votre code ignorantSystem.Web
et vous serez un campeur heureux. -
Est-ce que
Context.Items
survivreRedirectToAction
? Non. Votre test est invalide. Il est le réglage « Bonjour, monde » à chaque requête web et votre test couvre deux requêtes Web. La première est lorsque l'action index est appelée. Le second est lorsque l'action deRedirectToAction
est appelé (c'est un HTTP 302). Pour le faire échouer, définir une nouvelle valeur dans l'action Index et voir si elle est retenue dans l'action A propos.
Autres conseils
Utilisez le TempData Dictionnaire, il est principalement pour le stockage d'objets entre les actions réoriente:
public ActionResult Index()
{
TempData.Add("Test", "Hello world");
return RedirectToAction("About");
}
public ActionResult About()
{
ViewData["Test"] = TempData["Test"];
return View();
}
Ensuite, récupérer la valeur de votre point de vue:
<%=ViewData["Test"] %>
Je l'ai fait un test et TempData ne, en effet, avec l'état de exploserai séance désactivé. Mon seul conseil serait de ne pas stocker l'objet lui-même dans les données temporaires, mais stocker les simples champs typés comme cela a été suggéré. Puisque vous n'êtes pas sérialisation arbres objet, il ne devrait pas être un gros impact sur les performances en cours d'exécution hors processus.