Thursday, September 27, 2007

A simple GreatestCommonDivisor service in C# - Part2

What if we wanted to consume our previously built GCD Service by a web browser, such as Internet Explorer? ... Nothing easier than that. In fact, with minimal effort we can implement this functionality.
Firstly, we have to (1) declare that our service supports the HTTPQuery operation, secondly we have to (2) implement a handler for this HTTPQuery request, and thirdly we may (3) test the service with a browser.

1.
Just add the HTTPQuery port to the GCD service's port set, which is defined in GCDTypes.cs (assuming that your service is named GCD).

[ServicePort()]
public class GCDOperations : PortSet<..., HttpQuery, ...>
{}

So now that we have declared that our service is capable of understanding a HttpQuery action, we need to implement a routine, which handles such HttpQuery requests - a HTTPQueryGCDHandler.

2. Add the following lines to the GCD.cs

[ServiceHandler(ServiceHandlerBehavior.Concurrent)]
public virtual IEnumerator HTTPQueryGCDHandler(HttpQuery httpQuery) {
if (!string.IsNullOrEmpty(httpQuery.Body.Query["Action"]) &&
httpQuery.Body.Query["Action"] == "GCD")
{
string _M = httpQuery.Body.Query["M"];
string _N = httpQuery.Body.Query["N"];

int _intM = 1;
int _intN = 1;

if (!Int32.TryParse(_M, out _intM))
{
this.LogError("Failed to parse M");
httpQuery.ResponsePort.Post(

new HttpResponseType(new GcdtestState(-1)));
yield break;
}

if (!Int32.TryParse(_N, out _intN))
{
this.LogError("Failed to parse N");
httpQuery.ResponsePort.Post(

new HttpResponseType(new GcdtestState(-1)));
yield break;
}

int _GDC = this.ComputeGCD(_intM, _intN);
this.LogError("GDC = " + _GDC);

httpQuery.ResponsePort.Post(

new HttpResponseType(new GcdtestState(_GCD)));
}
else
{
this.LogError("Action is not GDC");
httpQuery.ResponsePort.Post(

new HttpResponseType(new GcdtestState(-1)));
}

yield break;
}

Besides computing the greatest common divisor and returning it as a http response, this handler does not do too much. It analyses whether the passed Action equals GCD and if so it tries to take the (hopefully) supplied parameters M and N. The service uses M and N to compute their GCD and if successful, passes the result back. If an error occurs, this service returns -1. The handler does not update the service's internal GCD state because of the following recommendation from the MRS help :

"As both GET and QUERY requests are defined by DSSP as not having any
side-effects, GET and QUERY handlers should be marked as
ServiceHandlerBehavior.Concurrent using the ServiceHandler attribute so that the
infrastructure knows that these handlers can run concurrently. "


3.With the handler in place, we may test our service. So we execute it by opening a browser and typing in the following URL

http://localhost:50000/GCD?Action=GCD&M=15&N=3

and this will return the correct result of 3. Note, that depending on you configuration the port and service name might be different. In fact, in the previous tutorial the service's name was GCDService, so you might want to take this into consideratio.

Although this was only a minor sample, I am trying to do something more meaningful with DSS and I hope to provide another small tutorial soon. So read you soon.

Christian

No comments: