Monday, 19 October 2015

Web API, Rest or RPC

Issue

I have a service method -

public String GetDeleteErrorLog()
{‏

...‏

I'm using the url http://lpsservices/api/ScheduledTask/DeleteErrorLog/

‎web api works fine‏

but when I add another method

method‏

public ScheduledTask GetTask(String id)‏

‎it always calls the 2'nd method‏ (and fails because the ID not present).

(BTW its not an object delete - its just the name of the process I return an id and then want to get the stauts of the task)

 

Cause

I contacted our REST Guru and here’s what he said:

Web Api pattern matches against controller methods to identify the correct method‏

‎Anything prefixed with a Get is obviously a Http Get by convention‏

‎so you have a ScheduleTaskController that resolves to ScheduleTask and...‏

‎it is verb based

so you call /lppservices/api/ScheduledTask‏

‎that is all‏

you are in RPC world with DeleteErrorLog‏ it thinks DeleteErrorLog is a parameter‏ because your route definition most likely has /api/{controller}/{id} where id is optional‏ therefore DeleteErrorLog resolves as the id parameter to your method‏.

WebApi does not like nouns‏ parameters are either behind the "?" e.g. ?id=DeleteErrorLog‏, /api/{controller}/{id}”

After he explained it again I understood the implication.  This essentially means that all the get methods must have different number of paramaters.  The “paradigm” seems to be that you are carrying out REST requests on an object.

But why – I went back to the GURU:

the issue with {action} is that it makes it very difficult to leverage http caching‏

‎15‎:‎29

as it managing expiration of urls after inserts, updates and deletes gets tricky‏

me
‎15‎:‎30

I'm starting an async process and returning the id (guid) so I can retrieve the status of that process - not really going to want http cacheing!‏

shay doherty
‎15‎:‎32

thats only if you use http level caching!, like you say you don't need it currently, but for some stuff in LPS HTTP Client Cache may become very useful if the client app does alot of repititive GET requests for lists of data‏

‎15‎:‎33

HttpClient supports http caching with the "Cache Cow" add on!‏

then managing expiration of those datasets maybe important‏

‎15‎:‎34

so it might come in handy‏”

 

Solution

It seems I may have drifted from the paradigm – perhaps my parameter should be the name of the service – but the ID is a string too.  Perhaps I am “PUT” ing as I;m creating the task – but just GETing the (task) token.

However, to solve the problem I have added a new route (in WebApiConfig).

config.Routes.MapHttpRoute(
               name: "ActionApi",
               routeTemplate: "actionapi/{controller}/{action}/{id}",
               defaults: new { id = RouteParameter.Optional }
           );

So now any url begining with /actionapi/ rather than /api/ will match the controller (class) and the action (method).

You can mark the actions too e.g. [ActionName("DeleteErrorLog")] or just let them be the same as the method name.

Conclusion

If you want to use explicit actions just change your url.

No comments:

Post a Comment