Generic/Intermediate WCF Service

11 Iul

Abstract

Sometimes you have a dependency on a web service but unfortunately you can’t really access it or by any reason it is outside of your management; one example would be that you need to consume some 3rd party service but the PO wasn’t able to provide you, the developer, a set of credentials.

Other case of a generic WCF service use is when you want to mock different behaviors depending on the input data: for example you have a set of end2end tests which verify cases of different error code provided by the external service. Again, unfortunately, no 3rd party provides test data for all the error codes.

Of course, at one point you might need a service which acts as a router/load balancer thus not having a Contract, Action defined.

Scope of the project

I decided to implement a generic WCF service that would accept any data (SOAP for starters), hash the incoming string, find the file with the name as the generated hash and return whatever content it finds there. One limitation I imposed on myself was that the implementation should take less than 50 lines of code.

Implementation

I will skip the boring part where you create a new VS solution for the WCF project. If you don’t know how, maybe this article is not for you. After the project is created delete all the boilerplate code that it generated.

I created a new WCF service and named it CatchAllService with the underlying interface called ICatchAll.

ICatchAll should look like this:

[ServiceContract]
public interface ICatchAll
{
    [OperationContract(IsOneWay = false, Action = "*", ReplyAction = "*")]
    Message ProcessMessage(Message message);
}

Note that ProcessMessage has Action set to * which means that regardless of the action set in the Soap message we will process it here.

Now, for the actual implementation we just need to write some code in the ProcessMessage method for the CatchAllService class.

[ServiceBehavior(ValidateMustUnderstand = false)]
public class CatchAllService : ICatchAll
{
    public Message ProcessMessage(Message message)
    {
        var xrdr = message.GetReaderAtBodyContents();
        var bodyData = xrdr.ReadOuterXml();

        var hash = Hashing.GetHashString(bodyData);

        var bytes = Encoding.UTF8.GetBytes(File.ReadAllText($"{HostingEnvironment.ApplicationPhysicalPath}/Responses/{hash}.txt"));
        var reader = XmlDictionaryReader.CreateTextReader(bytes, XmlDictionaryReaderQuotas.Max);

        return Message.CreateMessage(reader, int.MaxValue, message.Version);
    }
}

As stated in the scope paragraph the program reads the message body, hashes it, find the file under Responses folder and returns a new message with file content.

And that’s it!

How to test it

Fire SoapUI -> Create new Empty Project -> Right click on the project -> Add new REST Service from URI -> write http://localhost/CatchAll/CatchAllService.svc. Under Media Type select text/xml write any Soap message there. Attach the debugger to w3wp (or start it by F5) and set a breakpoint in ProcessMessage method.

Improvements

Accept any type of request by exposing several endpoints.

Nu fi egoist, dă mai departe să ajungă la tot poporul

Lasă un răspuns