开发者

WCF service calls includes same information in every call

I have a web service that will be consumed by some application (web site currently).

The calls are almost all specific to a certain client but still the same. So one call might be getAllFoo() but I would need some parameter to say from which client the Foo is.

It would become bothersome quickly if I just add a standard parameter to all calls so I was hoping to do it a little bit DRY and automatic. Something that would be included in all service calls.

Is IDispatchMessageInspector the right thing for me here? What kind 开发者_开发知识库of info could that include and can I access that info inside the methods?

Should I create some sort of attribute perhaps for the calls?

If anyone could point me towards a solution for this it would be great.

Edit

Another solution I'm thinking off.

Where the service call to a specific client happens on the consumer side, it will be known at instanceCreation so I could instance the ServiceClient with a known client.

Could I use this solution for the ClientBase<> extender somehow.

Let's say I'm serving Domain1 (let's call the client Domain to not confuse it with a serviceclient/consumer) I create a InformationProvider consumer side that has a ClientBase<IInformationService> field. I ensure that the DomainName (domain1) is set at construction so I could parhaps do the same thing when instancing the ClientBase<IInformationService> so It somehow let's the service know what domain I'm calling for.

I'm just still learning about WCF so I'm not sure how one would do this.


I can understand that you want to keep you solution simple and tidy, but ultimately - as you say yourself -

... I would need some parameter to say from which client...

The obvious and simplest solution is to include a client parameter on all your service calls where it is required. Surely there'll be service calls that don't require the client parameter, and in those cases you don't need to include the parameter.

You may be able to do something clever where a client identifier is passed discreetly under the covers, but beware of doing unnecessarily clever things. I would pass the client as a simple parameter because it is being used as a parameter. Two reasons come to mind:

  1. if someone maintains your code they quickly understand what's going on.
  2. if someone needs to use the service it is obvious how to use it.


A possible pattern:

  • Make sure you service instantiates per session. This means you'll have to use wsHttpBinding, netTcpBinding, or a custom binding as http does not support sessions.
  • Always call an initialization operation when each session is instantiated that sets the client id for that service.
  • Put this initialization operation inside a constructor for a proxy.

The steps involved would be something like this:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class MyService : IMyService
{
    private int clientId;

    public void StartUp(int clientId)
    {
        this.clientId = clientId;

and then client side, assuming you use the generated proxy, wrap the client inside another proxy.

public class ExtendedClient : MyServiceClient
{
    public ExtendedClient(int clientid) : base()
    {
        this.StartUp(clientid);
    }

Now you should instantiate the ExtendedClient, it will create the channel and prime the service by delivering the client id.

I would personally prefer to simply send the client id for each service call, but if you are able to use a session-able binding then this should work.


Just some information on WCF for you. If you have a stateless service, then you'll need to include the client as a parameter in every service call. This does not mean you need to include the client everywhere throughout your code - you could, for example, retrieve it inside the ClientBase constructor. But you will need to add it to every OperationContract and all the service implementations.

The alternative is to have a stateful service - the instance that you first use will remain for you to reuse (except for timeouts / exceptions). In this case you can potentially send the client just once, and then the service will know about the client for subsequent calls. This is the pattern described above. It means that you cannot use http binding. I believe that by doing this you're only increasing the potential for problems in your application (stateful services, having to ensure the initialization operation completes, more service calls being made).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜