Sunday, March 6, 2011

How to design and implement a simple WCF service relay?

We are in the process of designing a simple service-oriented architecture using WCF as the implementation framework. There are a handful of services that a few applications use. These services are mostly used internally, so a basic authentication and authorization scheme (such as Windows-based) is enough.

We want, however, expose some of the services to some business partners. The set of services they have access to depend on the contract. Kind of a standard architecture.

I think we can implement a service gateway which authenticates the requests and relays them to the correct internal service endpoint (this resembles simple ESB), so we can centralize the authentication/authorization code and expose one single endpoint to the world. I looked at some available ESB toolkits, but they seem way too complex for this purpose. We do not need to integrate a lot of different services, but just to expose some of them to the Internet.

How can I design and implement such a relay/router in WCF, keeping it very simple? I have read Inside Windows Communication Foundation, which is a good book, but I'm still not confident enough on how to begin.

From stackoverflow
  • I have done something very similar to this. What you can do is expose an endpoint with a single operation.

    That operation would look something like

    [OperationContract(Namespace="www.fu.com", Action="*")]
    void CallThis(Message msg);
    

    Have your clients use a proxy that is intended for the service they intended to calling the operation they want. Then have them change the configuration to point to your endpoint/service. The "CallThis" method will accept any operation, regardless of its signature. The Message parameter is the WCF Message.

    Do what you need to do to determine where things are supposed to go, but you will need to change the "To" to go to your internal endpoint.

    I actually have a full implementation of this, so if you have questions, let me know.

    Joe.

    Dario Solera : Thank you, I'm exploring this option. The problem is that I'm not sure how to return the response generated by the internal service to the external requester.
    Joseph DeCarlo : Good point. My implmentation uses one way messages, so I don't have to deal with that. Using the Action="*" attribute forces this call to be higher in the WCF stack. So no serialization of types happens during your call.You should be able putting a return type of Message and it should work.
    tomasr : Dario: You should still be able to use a catch all handler like the above and return a Message instance; it doesn't need to be a one way operation.
  • It seems it is sufficient to build an interface as follows:

    [OperationContract(Action="*", ReplyAction="*")]
    Message CallThis(Message msg);
    

    I also found this post useful for implementing the CallThis method by "fiddling" with Message objects. A basic implementation of the CallThis method follows:

    public Message CallThis(Message message) {
        MessageBuffer buffer = message.CreateBufferedCopy(524288);
        Message output = buffer.CreateMessage();
        output.Headers.To = <INTERNAL_SERVICE_URI>;
    
        BasicHttpBinding binding = new BasicHttpBinding();
        IChannelFactory<IRequestChannel> factory = binding.BuildChannelFactory<IRequestChannel>(<INTERNAL_SERVICE_URI>);
        factory.Open();
    
        IRequestChannel channel = factory.CreateChannel(new EndpointAddress(<INTERNAL_SERVICE_URI>));
        channel.Open();
    
        Message result = channel.Request(output);
    
        message.Close();
        output.Close();
        factory.Close();
        channel.Close();
    
        return result;
    }
    

    Adding authentication and authorization should be quite straightforward.

  • Check out this SO question where one of the responses suggests .NET 4's RoutingService. Very nice addition to WCF.

0 comments:

Post a Comment