2009-01-27 6 views
7

J'ai un filtre ISAPI pour IIS 6 qui effectue un traitement personnalisé en utilisant le champ bytes-send de la réponse. Je voudrais mettre à jour cela pour IIS 7, mais je rencontre un problème. Aucun des événements IIS 7 ne semble avoir accès à la longueur du contenu, aux octets envoyés ou aux données qui me permettraient de calculer la longueur du contenu ou les octets envoyés. (Je sais que l'en-tête de contenu et les octets envoyés ne sont pas les mêmes, mais ils fonctionneront dans ce but.)Le module géré IIS 7 ne peut pas recevoir Content-Length ou les octets envoyés

D'après ce que je peux dire, l'en-tête content-length est ajouté par HTTP.SYS après les modules gérés ont fini d'exécuter. À l'heure actuelle, j'ai un gestionnaire d'événements qui s'exécute sur EndRequest. Si je pouvais obtenir le flux de sortie, je pourrais calculer ce dont j'ai besoin moi-même, mais le pipeline géré ne semble pas avoir accès à cela non plus.

Existe-t-il un moyen d'obtenir la longueur de contenu ou les octets envoyés dans le pipeline géré? A défaut, est-il possible de calculer la longueur du contenu ou les octets envoyés à partir d'objets disponibles dans le pipeline géré?

+0

Y at-il quelque chose que je peux ajouter qui aiderait à répondre à cette question? –

Répondre

7

Pour obtenir les octets envoyés, vous pouvez utiliser la propriété HttpResponse.Filter. Comme les documents MSDN disent que cette propriété obtient ou définit un objet de filtre de retour qui est utilisé pour modifier le corps d'entité HTTP avant la transmission.

Vous pouvez créer un nouveau System.IO.Stream qui encapsule le flux existant HttpResponse.Filter et compte les octets transmis à la méthode Write avant de les transmettre. Par exemple:

public class ContentLengthModule : IHttpModule 
{ 
    public void Init(HttpApplication context) 
    { 
     context.BeginRequest += OnBeginRequest; 
     context.EndRequest += OnEndRequest; 
    } 

    void OnBeginRequest(object sender, EventArgs e) 
    { 
     var application = (HttpApplication) sender; 
     application.Response.Filter = new ContentLengthFilter(application.Response.Filter); 
    } 

    void OnEndRequest(object sender, EventArgs e) 
    { 
     var application = (HttpApplication) sender; 
     var contentLengthFilter = (ContentLengthFilter) application.Response.Filter; 
     var contentLength = contentLengthFilter.BytesWritten; 
    } 

    public void Dispose() 
    { 
    } 
} 

public class ContentLengthFilter : Stream 
{ 
    private readonly Stream _responseFilter; 

    public int BytesWritten { get; set; } 

    public ContentLengthFilter(Stream responseFilter) 
    { 
     _responseFilter = responseFilter; 
    } 

    public override void Flush() 
    { 
     _responseFilter.Flush(); 
    } 

    public override long Seek(long offset, SeekOrigin origin) 
    { 
     return _responseFilter.Seek(offset, origin); 
    } 

    public override void SetLength(long value) 
    { 
     _responseFilter.SetLength(value); 
    } 

    public override int Read(byte[] buffer, int offset, int count) 
    { 
     return _responseFilter.Read(buffer, offset, count); 
    } 

    public override void Write(byte[] buffer, int offset, int count) 
    { 
     BytesWritten += count; 
     _responseFilter.Write(buffer, offset, count); 
    } 

    public override bool CanRead 
    { 
     get { return _responseFilter.CanRead; } 
    } 

    public override bool CanSeek 
    { 
     get { return _responseFilter.CanSeek; } 
    } 

    public override bool CanWrite 
    { 
     get { return _responseFilter.CanWrite; } 
    } 

    public override long Length 
    { 
     get { return _responseFilter.Length; } 
    } 

    public override long Position 
    { 
     get { return _responseFilter.Position; } 
     set { _responseFilter.Position = value; } 
    } 
} 
+0

Merci pour la réponse très complète et l'exemple de code. Maintenant j'ai juste besoin d'une chance pour le brancher et l'essayer. –

+0

C'est exactement ce dont j'avais besoin. Merci encore. –

Questions connexes