2010-11-03 14 views
10

Dies scheint wie eine einfache Operation.HttpModule zum Hinzufügen von Kopfzeilen zur Anfrage

Wir haben in unserer Entwicklungsumgebung (unter XP/IIS 5) die Notwendigkeit, einige Header zu jedem HttpRequest hinzuzufügen, das in unserer Anwendung ankommt. (Dies ist eine Produktionsumgebung zu simulieren, die wir in dev nicht verfügbar haben). Auf dem ersten Blick schien dies wie eine einfache Httpmodule, entlang der Linien von:

public class Dev_Sim: IHttpModule 
{ 
    public void Init(HttpApplication app) 
    { 
     app.BeginRequest += delegate { app.Context.Request.Headers.Add("UserName", "XYZZY"); }; 
    } 

    public void Dispose(){} 
} 

Aber zu versuchen, das zu tun, finde ich, dass die Header Sammlung des Antrags ist schreibgeschützt, und die Add-Methode nicht mit eine OperationNotSupported-Ausnahme.

Wenn ich ein paar Stunden damit verbringe, dies auf Google zu recherchieren, habe ich keine einfache Antwort gefunden, was ein relativ unkompliziertes Problem sein sollte.

Hat jemand irgendwelche Zeiger?

+0

Es besteht die Möglichkeit, den Antwortstream zu ändern. Haben Sie etwas Bestimmtes, das Sie in den Griff bekommen und ersetzen können? – brumScouse

+0

Ich möchte die Antwort nicht ändern. Ich muss die Anfrage ändern und sie an den Rest der Kette senden, bis sie schließlich in meiner MVC-Anwendung endet. Wenn es in meine App gelangt, muss meine App die Header sehen können, die ich in dieses Modul einfügen möchte. –

Antwort

15

Okay, mit Hilfe eines Kollegen und einigen Experimenten, fand ich, dass dies mit der Hilfe von einigen geschützten Eigenschaften und Methoden durch Reflexion zugänglich gemacht werden:

var headers = app.Context.Request.Headers; 
Type hdr = headers.GetType(); 
PropertyInfo ro = hdr.GetProperty("IsReadOnly", 
    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase | BindingFlags.FlattenHierarchy); 
// Remove the ReadOnly property 
ro.SetValue(headers, false, null); 
// Invoke the protected InvalidateCachedArrays method 
hdr.InvokeMember("InvalidateCachedArrays", 
    BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, 
    null, headers, null); 
// Now invoke the protected "BaseAdd" method of the base class to add the 
// headers you need. The header content needs to be an ArrayList or the 
// the web application will choke on it. 
hdr.InvokeMember("BaseAdd", 
    BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, 
    null, headers, 
    new object[] { "CustomHeaderKey", new ArrayList {"CustomHeaderContent"}}); 
// repeat BaseAdd invocation for any other headers to be added 
// Then set the collection back to ReadOnly 
ro.SetValue(headers, true, null); 

Dies funktioniert für mich, mindestens.

+0

Wir haben einen Gewinner! –

+0

Das ist so falsch. Ich habe es verwendet, um der Anfrage Parameter hinzuzufügen (sie sind auch schreibgeschützt). Es ist nicht nötig, in diesem Fall den Wert einer ArrayList anzugeben - nur eine Zeichenkette. +1 – iandisme

+0

Super! Ich benutzte dies, um eine Erweiterungsmethode zu erstellen, wenn ich für meine Tests einen Header zu einem HttpRequest hinzufügen musste. https://gist.github.com/mrstebo/81288a96f55c0b74f6c5b37ee17533a6 – mrstebo

0

Sie können auf diese Weise zum Header hinzufügen. Auf diese Weise können Sie der Anforderung Anmeldeinformationen hinzufügen, bevor sie in die Authentifizierungssequenz eintreten.

string cred = "UN:PW"; 
System.Web.HttpContext.Current.Request.Headers.Add("Authorization", "Basic " +Convert.ToBase64String(Encoding.ASCII.GetBytes(cred))); 
+2

Ich bin mir nicht sicher, und da es anderthalb Jahre später ist, habe ich noch keine Testumgebung, um es zu versuchen, aber ich glaube, Sie werden finde heraus, dass Headers.Add mit der Ausnahme "OperationNotSupported" wie in meinem ursprünglichen Beispiel fehlschlägt. Ich könnte falsch liegen ... –

+0

Ich habe diese Methode versucht und habe die gleiche OperationNotSupported Ausnahme Dave Hanna Lösung für mich gearbeitet – Franklin

Verwandte Themen