Here’s the situation. I have a webservice (C# 2.0), which consists of (mainly) a class inheriting from System.Web.Services.WebService. It contains a few methods, which all need to call a method that checks if they’re authorized or not.
Basically something like this (pardon the architecture, this is purely as an example):
public class ProductService : WebService { public AuthHeader AuthenticationHeader; [WebMethod(Description='Returns true')] [SoapHeader('AuthenticationHeader')] public bool MethodWhichReturnsTrue() { if(Validate(AuthenticationHeader)) { throw new SecurityException('Access Denied'); } return true; } [WebMethod(Description='Returns false')] [SoapHeader('AuthenticationHeader')] public bool MethodWhichReturnsFalse() { if(Validate(AuthenticationHeader)) { throw new SecurityException('Access Denied'); } return false; } private bool Validate(AuthHeader authHeader) { return authHeader.Username == 'gooduser' && authHeader.Password == 'goodpassword'; } }
As you can see, the method Validate has to be called in each method. I’m looking for a way to be able to call that method, while still being able to access the soap headers in a sane way. I’ve looked at the events in the global.asax, but I don’t think I can access the headers in that class… Can I?
Here is what you need to do to get this to work correctly.
It is possible to create your own custom SoapHeader:
Then you need a SoapExtensionAttribute:
And a custom SoapExtension:
Then, in your web service add the following header to your method:
When you consume this service, you must instantiate the custom header with the correct values and attach it to the request: