CONNECTED Conference 2023 - Aufzeichnungen jetzt hier verfügbar +++                     

Suche

über alle News und Events

 

Alle News

 

Für Entwickler, Architekten, Projektleiter und...

Read more

In der Welt der Softwareentwicklung ist die...

Read more

QUIBIQ spendet für den guten Zweck – und für...

Read more

Eine bestimmte Antwort auf einen HTTP Request zu...

Read more

In einer Welt, die von stetigem Wandel geprägt...

Read more

In einem unserer Kundenprojekte, war das Ziel eine...

Read more

QUIBIQ Hamburg wird mit dem Hamburger...

Read more

Zwei Tage lang wurde vom 14.-15.11 wieder das...

Read more

Was ist ein Excel-Plugin – und wann ist es...

Read more

Wir expandieren, bringen Kunden und Talente besser...

Read more

How-to: http-Header mit WCF-Behavior manipulieren

Eine Kunde möchte an einem BasicHttp-Send-Port eine HTTP-Authentifizierung durchführen. Die Credentials sollen dabei über eine Pipeline-Komponente eingefügt werden. Der BasicHttp-Adapter unterstützt das aber nicht.

Die Lösung: Wir stecken den BasicHttp-Adapter als Binding in einen WCF-Adapter und schreiben für diesen ein Endpoint-Behavior.

Wir haben uns entschieden, dass das Behavior das Setzen von beliebigen HTTP-Headern erlauben soll.

Zuerst schreiben wir uns also einen IClientMessageInspector:

public class AddHttpHeaderInspector : IClientMessageInspector

{

Wir wollen ein Context-Property des WCF-Adapters setzen:

private const string HttpHeadersKey = "http://schemas.microsoft.com/BizTalk/2006/01/Adapters/WCF-properties#HttpHeaders";

 

public void AfterReceiveReply(ref Message reply, object correlationState) {}

public object BeforeSendRequest(ref Message request, IClientChannel channel)

{

if (!request.Properties.ContainsKey(HttpHeadersKey)) { return null; }

Für den WCF-Adapter muss die SOAP-Action angegeben werden; für den BasicHttp-Adapter aber nicht. Um dieses Verhalten beizubehalten, löschen wir die SOAP-Action im Behavior. Der Nutzer muss aber noch irgendetwas angeben.

request.Headers.Action = null;

Hier setzen wir jetzt die Header. Wir erwarten, dass die Header im normalen HTTP-Format angegeben werden, d. h. Name von Inhalt durch Doppelpunkt getrennt und jeder Header auf einer eigenen Zeile.

var headers = ((string)request.Properties[HttpHeadersKey])

.Split('\n')

.Select(str => str.Split(':'))

.Where(header => header.Length == 2)

.Select(header => new { Name = header[0].Trim(), Content = header[1].Trim() });

Jetzt holen wir uns das HTTP-Request-Property aus der Message:

HttpRequestMessageProperty httpRequestMessage;

object httpRequestMessageObject;

if (request.Properties.TryGetValue(HttpRequestMessageProperty.Nameout httpRequestMessageObject))

{

httpRequestMessage = (HttpRequestMessageProperty)httpRequestMessageObject;

}

else

{

httpRequestMessage = new HttpRequestMessageProperty();

request.Properties.Add(HttpRequestMessageProperty.NamehttpRequestMessage);

}

Anschließend setzen wir die Header, die in einem Dictionary übergeben werden:

foreach (var header in headers)

{

httpRequestMessage.Headers[header.Name] = header.Content;

}

return null;

}

}

}

Zudem benötigen wir zwei eher triviale Klassen, um das Behavior zu vervollständigen:

public class AddHttpHeaderBehavior : IEndpointBehavior

{

public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }

public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)

{

AddHttpHeaderInspector headerInspector = new AddHttpHeaderInspector();

clientRuntime.MessageInspectors.Add(headerInspector);

}

public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }

public void Validate(ServiceEndpoint endpoint) { }

}

 

public class AddHttpHeaderBehaviorExtensionElement : BehaviorExtensionElement

{

protected override object CreateBehavior()

{

return new AddHttpHeaderBehavior();

}

 

public override Type BehaviorType

{

get { return typeof(AddHttpHeaderBehavior); }

}

}

 

Als nächstes benötigen wir die PipelineKomponente. Diese könnte zum Beispiel so aussehen:

[ComponentCategory(CategoryTypes.CATID_PipelineComponent)]

[ComponentCategory(CategoryTypes.CATID_Encoder)]

[Guid("88CDCE17-D9B1-47BA-98C6-3BF7E9E2FE65")]

public class HttpHeaderComponent : IBaseComponentIComponentIComponentUI

{

public string Description => "HttpHeaderComponent";

public string Name => "HttpHeaderComponent";

public string Version => "1.0.0";

public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)

{

pInMsg.Context.Write(

"HttpHeaders",

"http://schemas.microsoft.com/BizTalk/2006/01/Adapters/WCF-properties",

"Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l\nAccept-Encoding: gzip, deflate");

return pInMsg;

}

public IntPtr Icon => IntPtr.Zero;

public System.Collections.IEnumerator Validate(object projectSystem) => new string[0].GetEnumerator();

}

Der Großteil der Klasse kann beliebig ausgestaltet werden. In Execute setzen wir das Authorisierungsschema auf Basic mit Benutzer „Aladdin“ und Password „OpenSesame“; außerdem akzeptieren wir gzip- und DEFLATE-komprimierte Daten.

Nachdem wir diese Projekte kompiliert haben, installieren wir die Pipeline ganz normal als BizTalk-Assembly. Das Behavior muss in den Global Assembly Cache installiert werden, z. B. mit gacutil oder BizTalk. Dann muss in der machine.config innerhalb des behaviorExtensions-Tags eine Zeile analog zu

<add name="biztalkAddHttpHeader" type="WCFBasicHttpAdditionalHeaders.AddHttpHeaderBehaviorExtensionElement, WCFBasicHttpAdditionalHeaders, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9350da1595971f93"/>

eingefügt werden. Die Datei machine.config findet sich jeweils in C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\ und C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\. Es empfiehlt sich, jetzt die entsprechenden Host-Instanzen neuzustarten.

Das Behavior ist nun einsatzbereit. Wir erstellen einen neuen Send Port vom Typ WCF-Custom und setzen dort unsere Pipeline ein.

Wir setzen die URL auf den gewünschten Endpunkt ein und tragen bei Action etwas Beliebiges ein; dieser Wert wird später vom Behavior wieder gelöscht, aber er sorgt dafür, dass der Port funktioniert. Unter Binding setzen wir den Binding Type auf „basicHttpBinding“ und unter Security den Mode auf „Transport“.


 

Zuletzt fügen wir unter Behavior noch unser Behavior hinzu.

Damit ist der Send Port fertig und meldet sich nun am Endpunkt mit dem Benutzer „Aladdin“ und dem Passwort „OpenSesame“ an.

Dieser Tech-Tipp kommt von QUIBIQ Berlin.

Ihre Kontaktmöglichkeiten

Sie haben eine konkrete Frage an uns


 

Bleiben Sie immer auf dem Laufenden


 

Mit meinem "Ja" erkläre ich mich mit der Verarbeitung meiner Daten zur Zusendung von Informationen einverstanden. Ich weiß, dass ich diese Erklärung jederzeit durch einfache Mitteilung widerrufen kann. Bei einem Nein an dieser Stelle erhalte ich zukünftig keine Informationen mehr.

© QUIBIQ GmbH · Impressum · Datenschutz