Contents tagged with SoapExtension
-
WCF Client Calling ASMX Service with Soap Headers
Need to send soap headers from WCF (Service Reference) clients to older ASMX services? The ASMX service not handling the header properly? It may have to do with namespaces being set in the soap header XML in a way differently from what the ASMX service is expecting.
So, how do you create and add the same type of headers, with the correct namespace, in a WCF client? For every outgoing call?
First, a simple ASMX service for your pleasure to play with:
[WebService(Namespace = "http://tempuri.org/")]
public class Service1 : WebService
{
public MyHeader myHeader;
[WebMethod]
[SoapHeader("myHeader")]
public string HelloWorld()
{
if (myHeader != null)
return "Got header: " + myHeader.MyFirstValue + " " + myHeader.MyOtherValue;
return "Got no header!!";
}
}
That's it on the server side. Over to the client side... Well, the header itself can be either a class which implements the MessageHeader class, but I prefer to use a normal class decorated with DataContract attribute. Notice the namespace property which matches the one on the service above:
[DataContract(Namespace = "http://tempuri.org/")]
public class MyHeader
{
[DataMember]
public string MyFirstValue { get; set; }
[DataMember]
public string MyOtherValue { get; set; }
}
In ASMX clients you normally create a soap extension to add the header to every outgoing call, but here the ASMX soap extension is replaced by a (Client)MessageInspector in WCF, which is added to a client endpoint via a behavior. I'm cramming the whole sample implementation into one class:
public class AddSoapHeaderBehavior : BehaviorExtensionElement, IClientMessageInspector, IEndpointBehavior
{
#region IClientMessageInspector Members
public void AfterReceiveReply(ref Message reply, object correlationState) { }
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var myHeader = new MyHeader { MyFirstValue = "Yeeehaaaw!!", MyOtherValue = "Gaaah!" };
var messageHeader = new MessageHeader<MyHeader>() { Actor = "Anyone", Content = myHeader };
request.Headers.Add(messageHeader.GetUntypedHeader("MyHeader", "http://tempuri.org/"));
return null;
}
#endregion
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior) { behavior.MessageInspectors.Add(this); }
public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher) { }
public void Validate(ServiceEndpoint serviceEndpoint) { }
#endregion
#region BehaviorExtensionElement Members
protected override object CreateBehavior() { return new AddSoapHeaderBehavior(); }
public override Type BehaviorType { get { return GetType(); } }
#endregion
}
The endpointbehavior and behaviorextensionelement member implementations are just boilerplate stuff that should be hidden as default behavior by WCF if you ask me, but you need to type this out.
Finally, the behavior must be loaded in the config (or via code):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="MyEndpointBehaviors">
<ClientSoapHeaderAdderBehavior />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="ClientSoapHeaderAdderBehavior"
type="MyBehavior.AddSoapHeaderBehavior, MyBehavior, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<client>
<endpoint name="Service1Soap"
address="http://localhost:4221/Service1.asmx"
binding="basicHttpBinding"
behaviorConfiguration="MyEndpointBehaviors"
contract="ClientProxy.Service1Soap" />
</client>
</system.serviceModel>
</configuration>
Hope it helps someone.
-
WS-Security webcasts
Architect Webcast: Securing Web Services (interwise recording)
Support WebCast: Introduction to Microsoft Web Services Enhancements (Windows streaming media)
This one is good if you've been into soap headers and such before:
Support WebCast: Microsoft ASP.NET: Advanced XML Web Services Using ASP.NET (Windows streaming media)
And this is an older, but very good article that describes the different proposed security specs around web services.
If you know of good webcasts about WS-Security, please comment.
-
WS-Security receives official blessing from OASIS
If someone out there missed it :)
"Web Services Security 1.0, the foundation specification for creating a security infrastructure around Web services, officially became a standard Monday, paving the way for corporate adoption."
InfoWorld April 20, 2004
One of many articles is available here.
-
Anyone tried encrypting soap messages with WS-Security yet?
The security guys here also banned access to the soap chat server I set up on the Internet to be able to chat with my old pals... correct, they don't allow Messenger or any other chat-programs. I know I'm not allowed to do chat-stuff over the Internet according to the IT-rules here, but gaaaaahhh!!! I must be able to chat a little with my friends, my mailbox is flooding as it is already!
I'm thinking of moving my chat Web Service (which is already protected by userid and password in a SOAP header) to another location and encrypting the messages. How hard can it be in .NET?
-
[SoapExtension] I did it again :(
This is the second time I try to test a SoapExtension class by calling a web service method from a browser! *hit self*
I've written the tiniest SoapExtension that captures web service exceptions, then publish it through my modified variant of Microsoft's Exception Management Application Block. Without comments and stuff it looks like this:
public class SoapExceptionHandler : SoapExtension
{
public override object GetInitializer( LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
//not used
}
public override object GetInitializer(Type WebServiceType)
{
//not used
}
public override void Initialize(object initializer)
{
//not used
}
public override void ProcessMessage(SoapMessage message)
{
switch(message.Stage)
{
case SoapMessageStage.AfterSerialize:
if(message.Exception != null)
ExceptionManager.Publish(message.Exception.InnerException);
break;
}
}
That's all you need. Register the SoapExtension to "listen" to the entire virtual root like this:
...
<system.web><webServices>
<soapExtensionTypes>
<add type="ExceptionManagement.SoapExceptionHandler,ExceptionManagement" priority="1" group="0" />
< SPAN>soapExtensionTypes>
< SPAN>webServices>
...UPDATE: Got rid of some source, just to shorten the post somewhat.