How do you decouple a web service that requires an authheader on every call?
I have a service reference to a .NET 2.0 web service. I have a reference to this service in my repository and I want to move to Ninject. I've been using DI for some time now, but haven't tried it with a web service like this.
So, in my code, the repository constructor creates two objects: the client proxy for the service, and an AuthHeader object that is the first parameter of every method in the proxy.
The AuthHeader is where I'm having friction. Because the concrete type is required as the first parameter on every call in the proxy, I believe I need to take a dependency on AuthHeader in my repository. Is this true?
I extracted an interface for AuthHeader 开发者_如何学Pythonfrom my reference.cs. I wanted to move to the following for my repository constructor:
[Inject]
public PackageRepository(IWebService service, IAuthHeader authHeader)
{
_service = service;
_authHeader = authHeader;
}
...but then I can't make calls to my service proxy like
_service.MakeSomeCall(_authheader, "some value").
...because because MakeSomeCall is expecting an AuthHeader, not an IAuthHeader.
Am I square-pegging a round hole here? Is this just an area where there isn't a natural fit (because of web service "awesomeness")? Am I missing an approach?
It's difficult to understand exactly what the question is here, but some general advice might be relevant to this situation:
Dependency injection does not mean that everything has to be an interface. I'm not sure why you would try to extract an interface from a web service proxy generated from WSDL; the types in the WSDL are contracts which you must follow. This is especially silly if the
IAuthHeader
doesn't have any behaviour (it doesn't seem to) and you'll never have alternate implementations.The reason why this looks all wrong is because it is wrong; this web service is poorly-designed. Information that's common to all messages (like an authentication token) should never go in the body where it translates to a method parameter; instead it should go in the message header, wherethe ironically-named
AuthHeader
clearly isn't. Headers can be intercepted by the proxy and inspected prior to executing any operation, either on the client or service side. In WCF that's part of the behavior (generallyClientCredentials
for authentication) and in legacy WSE it's done as an extension. Although it's theoretically possible to do this with information in the message body, it's far more difficult to pull off reliably.In any event, what's really important here isn't so much what your repository depends on but where that dependency comes from. If your
AuthHeader
is injected by the kernel as a dependency then you're still getting all the benefits of DI - in particular the ability to have this all registered in one place or substitute a different implementation (i.e. a derived class).
So design issues aside, I don't think you have a real problem in your DI implementation. If the class needs to take an AuthHeader
then inject an AuthHeader
. Don't worry about the exact syntax and type, as long as it takes that dependency as a constructor argument or property.
精彩评论