Service HTTP response code not returned correctly

Dec 12, 2012 at 12:29 PM

Hi,

I'm using RO within an ASP.NET MVC 4 project, as follows:

  1. The RestfulObjectsController calls GetInvokeOnService, which corresponds with a service I've written.  
  2. At the end of the  service action code, I return a new HttpResponseMessage instance with the appropriate return code.
  3. The value is then returned to the GetInvokeOnService in the RestfulObjectsController, in which the response's status code differs from the one returned from the service.

Some code:

The action handler in RestfulObjectsController:

 

[HttpGet]
[ActionName("authorize")]
public HttpResponseMessage Authorize(...)
{
   ...

   var argumentMap = ModelBinderUtils.CreateArgumentMap(JObject.Parse(jsonMap));
   var response    = GetInvokeOnService(ServiceName, "Authorize", argumentMap);
   ...
   return response;  // response.StatusCode = OK instead of BadRequest

The auto-generated controller code:

 

[HttpGet]
public override HttpResponseMessage GetInvokeOnService(string serviceName, string actionName, [ModelBinder(typeof(ArgumentMapUrlBinder))] ArgumentMap arguments)
{
    var response = base.GetInvokeOnService(serviceName, actionName, arguments);

    return response;  // response.StatusCode = OK instead of BadRequest

/}

 

My service action code:

[QueryOnly]
public HttpResponseMessage Authorize(...)
{
    ...

    if (contentBitrate == null)  // This condition evaluates to true
    {
        ...
        return new HttpResponseMessage(HttpStatusCode.BadRequest);
    }
    ...

Any ideas?

 

 

Coordinator
Dec 12, 2012 at 12:47 PM

I'm a bit dubious about returning a HttpResponseMessage from the service action - it's a coupling I would try to avoid if possible.

For a bad request try throwing a 'BadRequestNOSException'  

Dec 12, 2012 at 1:34 PM
Edited Dec 12, 2012 at 2:25 PM

As returning a status other than "OK" is expected to happen a lot, I would like to avoid exceptions as much as I can, and the fact that the code is "invoked" the way it is doesn't help either.

I used HttpResponseMessage because I need to return values (I use the HttpResponseMessage.Content property) and since GetInvokeOnService already returns a HttpResponseMessage, I thought I'm expected to return the same type.

If there's a way to return a string to the controller, it's excellent for me.

BTW, I'm following your lead on the NO disucssion: "Within that function call up to 'GetInvokeOnService' - service name is probably hard coded, the actionName matches your passed in action in the url and you should be able to create an ArgumentMap with your passed in parameters. Based on the response from the action you can return "OK" or nothing".  Did I get it right?

Coordinator
Dec 12, 2012 at 2:56 PM

OK there's all sorts of alarm bells going off here. If performance is so critical that you are concerned about throwing exceptions then I have to wonder if Restful Objects is right for this part of your application.  We make a lot of use of reflection  and Naked Objects is not optimised for high throughput. Perhaps for those parts of the app you might want to write something in node ?

Otherwise I would suggest your service action returns a string indicating the result

[QueryOnly]
public string Authorize(...)
{
    ...

    if (contentBitrate == null)  
    {
       return "BadRequest"; 
    }
   
    if (otherThing) 
   {
       return "NotOK";
    }

   return "OK"; 

}

That will get wrapped in an HttpResponse message for you so when you get the response back from GetInvokeOnService you'll have to unpack it and the message body should contain a result with the value (see p143 of the RO spec - or just debug the code).

Then you'll need to just map to a new httpresponse message based on the RC. Something like ?

 [HttpGet]
        [ActionName("authorize")]
        public HttpResponseMessage Authorize(...)
        {
      

           var argumentMap = ModelBinderUtils.CreateArgumentMap(JObject.Parse(jsonMap));
           var response    = GetInvokeOnService(ServiceName, "Authorize", argumentMap);

var body = response.Content.ReadAsStringAsync().Result;
var rc = ExtractRC(body); //
if (rc == "BadRequest") { return new HttpResponseMessage(HttpStatusCode.BadRequest); } else if (rc == "NotOK"... etc }

 

 

 

Dec 12, 2012 at 3:31 PM

Ok, just to recap the NO discussion:

The project is a subscriber and content management system, which interfaces with 3rd party services.  The content management is implemented using NO and involves a user (and later APIs) creating the content tree, which changes ever so slowly.  Subscriber management is actually responding to remote server requests, which may can be by the hundreds per second (in extreme cases - I wish this would be the case).  This is implemented as follows:

  1. Request handling logic involves querying the content tree.  It does not change the content tree.  RO is used for that end.
  2. There are a few very specific, isolated exceptions to the above.  I handle them in-memory and without the NO/EF frameworks (i.e. interlocked-protected counters).  I persist these data items to the database periodically (say, every minute), which is good enough for my use cases, via dedicated repositories in the RO framework.
  3. Every request is written directy to the database, not using domain objects but rather by using Context.ExecuteStoreCommand, which I assume "performs optimally".
  4. All the above is perfomed from within the service action.

I hope this makes more sense now.

With that said, should I try what you suggest above or do I need to try another approach in responding to requests?

Coordinator
Dec 12, 2012 at 4:18 PM

I would try getting it to work with the above suggestions. Once the service logic is running there's a lot of things you could do to optimise performance if necessary. My concern was that you were wanting very high (1000+/sec) numbers of requests.

Dec 12, 2012 at 7:08 PM

Got it, thanks.