Suche

über alle News und Events

 

Alle News

 

Mit einer cleveren Idee und einem engagierten Team...

Weiterlesen

Im Szenario einer Ablösung vom BizTalk Server 2016...

Weiterlesen

Neben der herkömmlichen, vierjährigen Ausbildung...

Weiterlesen

Bei Datenübertragungen stossen wir teilweise an...

Weiterlesen

Durable Function ist eine Erweiterung der...

Weiterlesen

Wir haben eine gute, vor allem spannende und hoch...

Weiterlesen

Am 09.05.2022 wurde ein Artikel von Microsoft...

Weiterlesen

Neben den altbekannten Logic Apps (Consumption),...

Weiterlesen

Im Jahr 2022 fallen eine Reihe von .Net Versionen...

Weiterlesen

SAP in die Power Platform integrieren – In einem...

Weiterlesen

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