J'ai un comportement étrange lorsque j'essaie de modifier mes en-têtes avec un fichier de type EndRequest
dans un gestionnaire d'événement imbriqué HttpModule
sur MVC 5.2.2 et .NET 4.6.2. Si je ne modifie pas EndRequest
dans mon niveau supérieur HttpModule
il semble que le gestionnaire d'événements dans le module imbriqué HttpModule
jamais de feu, même si je sais Init
a été appelé sur les éléments imbriqués HttpModule
.
Ma question est la suivante : qu'est-ce qui se passe dans mon code ci-dessous pour empêcher l'en-tête "TestNested" d'apparaître dans les en-têtes de réponse, à moins que je n'inclue le code commenté qui ajoute une balise de type EndRequest
un gestionnaire d'événement qui ne fait rien ?
Enregistrer dynamiquement mon niveau supérieur HttpModule
[assembly: PreApplicationStartMethod(typeof(PreApplicationStartClass), "Start")]
namespace MyNamespace
{
public class PreApplicationStartClass
{
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(TopHttpModule));
}
}
}
Appelez Init
sur tous mes autres HttpModules
à partir d'un seul module de premier niveau
namespace MyNamespace
{
public class TopHttpModule: IHttpModule
{
private readonly Lazy<IEnumerable<IHttpModule>> _modules =
new Lazy<IEnumerable<IHttpModule>>(RetrieveModules);
private static IEnumerable<IHttpModule> RetrieveModules()
{
return DependencyResolver.Current.GetServices<IHttpModule>();
}
public void Init(HttpApplication context)
{
var modules = _modules.Value;
foreach (var module in modules
.Where(module => module.GetType() != typeof(TopHttpModule)))
{
module.Init(context);
}
context.BeginRequest += (sender, e) =>
{
var app = sender as HttpApplication;
if (app != null)
{
//This shows that NestedHttpModule was found
app.Context.Response.Headers.Add(
"TestModules",
string.Join(",", modules.Select(_ => _.GetType().ToString())));
}
};
//Add this and the NestedHttpModule EndRequest handler works
//context.EndRequest += (sender, e) =>
//{
// //Do Nothing
//};
}
public void Dispose()
{
var modules = _modules.Value;
foreach (var disposable in modules
.Where(disposable => disposable.GetType() != typeof(TopHttpModule)))
{
disposable.Dispose();
}
}
}
}
Modifier certaines informations d'en-tête dans un EndRequest
gestionnaire d'événement
namespace MyNamespace
{
public class NestedHttpModule: IHttpModule
{
public void Init(HttpApplication context)
{
//This gets called whether or not the TopHttpModule modifies context.EndRequest
MvcHandler.DisableMvcResponseHeader = true;
context.EndRequest += Application_EndRequest;
}
public void Application_EndRequest(object sender, EventArgs e)
{
var app = sender as HttpApplication;
if (app != null && app.Context != null)
{
//This doesn't appear to be called unless TopHttpModule modifies context.EndRequest
app.Context.Response.Headers.Add("TestNested", "Found");
}
}
public void Dispose()
{
//Do Nothing
}
}
}
13 votes
Je suppose que la question évidente est la suivante : pourquoi utilisez-vous un HttpModule pour changer les en-têtes au lieu d'utiliser des API MVC telles que filtres pour faire ça ? Pourquoi utiliser une technologie ASP.NET ancienne et complexe pour quelque chose qui est déjà facilement modifiables dans MVC ?
1 votes
Quelle version d'Asp.Net MVC et du framework .NET utilisez-vous ? Le NestedHttpModule.EndRequest se déclenche pour moi.
0 votes
@CodingDawg MVC 5.2.2 et .NET 4.6.2
0 votes
@NightOwl888 Je veux que ce changement se produise sur chaque requête, pas seulement pour les actions MVC. HttpModule ou Global.asac semble être le bon choix selon la question posée ici : stackoverflow.com/questions/11507496/
0 votes
@ThomasLangston - Vous avez raison, si vous souhaitez que l'en-tête soit présent dans les requêtes d'images, les fichiers css, les erreurs IIS, les pages ASP.NET, etc., il est généralement préférable d'opter pour l'une de ces options (plutôt que d'utiliser l'option
runAllManagedModulesForAllRequests
). Je vérifiais simplement si cela valait vraiment la peine de se lancer dans cette aventure si vos besoins ne le justifiaient pas.0 votes
@NightOwl888 Ouais, j'ai déjà un travail fonctionnel ici, et j'ai en fait abandonné HttpModule pour Global.asax pour mon projet. Cette question est juste pour satisfaire ma curiosité sur la façon dont HttpModule fonctionne réellement dans ce scénario. C'est un comportement très étrange pour moi.
0 votes
@ThomasLangston Avez-vous un échantillon que vous pouvez mettre en ligne quelque part ? Je n'arrive pas à trouver où cela est reproductible.
1 votes
@ThomasLangston, est-ce toujours actif ? Pouvez-vous répondre à votre propre question en indiquant ce que vous avez fait ?
0 votes
@PSGuy pas un domaine actif de préoccupation pour moi pratiquement. J'ai opté pour ma solution de contournement en effectuant mes modifications d'en-tête directement dans le fichier Global.asax à la place.
5 votes
@ThomasLangston : Pouvez-vous répondre à votre question avec la solution que vous avez utilisée ?
2 votes
Vous pouvez consulter
Context.ApplicationInstance.CompleteRequest()
. Il y a quelques années, j'ai rencontré une situation où l'application prenait la demande, faisait autre chose et redirigeait sans laisser la demande se terminer. Je crois que c'est ce que j'ai utilisé pour gérer cela.1 votes
J'ai mis au point une solution pour cela et elle fonctionne parfaitement pour moi, comme il se doit. Je ne sais pas quel problème vous avez rencontré, mais il n'est pas lié au code que vous avez montré ici.