REST Batch\Bulk API implemetation in WCF similiar to Facebook API - c#

I'm implementing new REST API method which allows calling other REST API methods in batch\bulk manner. Similar to Facebook's https://developers.facebook.com/docs/graph-api/making-multiple-requests
Request example:
POST /batch
[
{"method":"GET", "relative_url":"/user/anton"},
{"method":"GET", "relative_url":"/user/vitaliy"}
{"method":"POST", "relative_url":"/user/dan", "body":{name:Dan}}
]
Response example:
status 200
[
{"status":"200", "body":{name:"Dan"}},
{"status":"404"},
{"status":"201"}
]
In short, batch method should on server-side call OTHER methods one-by-one and return result as array of results.
The most simple solution will be create .Net HttpClient on server side and call other WCF methods on-by-one.
The question is: How implement this using WCF infrastructure without calling WCF method externally via HttpClient?
The reason for that - I don't want to have network-round trips.
The most perfect solution will be to use .Net Reflection, but this not good solution in terms of REST abstraction
The most close solution is create WCF Message including HttpRequestMessageProperty (URL, Headers, Method, Content-Type) and send it to processing by WCF infrastructure (just it was sent via HTTP protocol) (not sure about this):
Message responseMessage = wcfInsfrastucture.Process(createWcfMessage(url, method,contentType,body));
Currently I'm lost in WCF Samples, and WCF server-side channel architecture.
Most similar question was asked in Sending custom WCF Message to a service but I can't making it work with existing configured server-side behaviors.
Similar questions:
Sending custom WCF Message to a service
https://stackoverflow.com/questions/26049136/generic-way-to-send-wcf-messages-to-different-channels

How implement this using WCF infrastructure without calling WCF method externally via HttpClient?
The only way I found is to implement request-response pattern over WCF.
Create a single entry point in WCF service, that receives an abstract request as an argument and returns an abstract response.
For example,
<OperationContract> function Execute(Request as IRequest) as IResponse
Create concrete request and response classes for service operations
Create CompositeRequest and CompositeResponse for Batch / Bulk operations
All service has to do is to apply business logic according to request type.
In case service receives CompositeRequest it just calls the same Execute method for all nested requests one-by-one and aggregates responses into CompositeResponse.

Related

Authentication via headers in WCF REST service

I am new to WCF services and currently testing out things.
I have got a little REST API, which has several methods. Some of them require a user context (session), some others don't. At login, each user gets a session token. The client should supply this token and his user ID on every request via HTTP headers.
At the moment, I wrote a method for getting those two headers and validate the session, calling it on every method which will need a user context. This seems kinda nasty if the API gets bigger.
Is there a better approach for doing this?
You can leverage of following solutions:
Custom class deriving IClientMessageInspector/IDispatchMessageInspector for client and service respectively. Then you add its instance to MessageInspectors. Advantage of having messageInspector is that it's applied to single endpoint so regardless of having many endpoints exposed (both SOAP and REST), messageInspector can be associated only with single one. Whenever message is either received or sent, AfterReceive or BeforeSent method is invoked respectively. There you retrieve headers and if token does not match any expected you can throw an exception. Such a way out provides separation between exposed contract and background checks such as token validation.
Custom class deriving IOperationInvoker. Within custom operation invoker you explicitly call method and thanks to it you can examine headers (OperationContext.Current.IncomingMessage) before any method gets invoced.
I brought up only concepts, extensive information and examples can be looked up on Internet.

Is RequestFilter Validation client dependent?

Should I expect Request Filter Validation (e.g. FluentValidation) to be triggered when instantiating a reference service via AppHostBase.ResolveService<>?
Thus far, I've only successfully received proper error responses to my C# application when using the typed clients (JsonServiceClient in this case specifically).
You are right. If you try use AppHostBase.ResolveService<T> it does not execute any of the registered request filters. Essentially it only resolves the Service from the AppHost dependancy container, you get back just the Service instance. Thus your validators aren't triggered.
ServiceStack v4:
As #mythz points out you can use the MQ entry point API of the HostContext to execute the call with the MQ request filters and thus have the validation run. To do this:
HostContext.ServiceController.ExecuteMessage(new Message<T>(requestDto), httpReq);
#mythz also notes you can execute a service using just a DTO, rather than having to determine the service and handling method to call, but in a similar fashion to AppHostBase.ResolveService<T> it doesn't trigger the request filters. Usage:
HostContext.ServiceController.Execute(requestDto, httpReq)
ServiceStack v3:
GetAppHost().Config.ServiceManager.ServiceController.ExecuteMessage(new Message<T>(requestDto), httpReq);

Asynchronous callback from web api controller

I'm very new to Web API and I have an unusual pattern that I need to implement. In the Post method of my controller, it is to take an object which includes a CallbackURL. It will then immediately return an HTTP response to the caller. Afterwards, it will use a 3rd party, off-site API to perform some work with the object. Once that work is done, the controller is to post the results of that work to the CallbackURL.
However, I do not know how to implement this in Web API. Once I return the HTTP response, the controller's lifecycle is over, correct? If so, how do I perform the work I need to do after I return the response?
If you only need to post results to a url and not to the client that initiated the call, you could possibly do something as easy as this:
public string MyAPIMethod(object input)
{
Task.Factory.StartNew(() =>
{
//call third-party service and post result to callback url here.
});
return "Success!";
}
The api call will return right away, and the Task you created will continue the processing in a different thread.
Creating a task to finish up the request (as suggested by Jason P above) will most likely solve the problem, thread-safety provided. However that approach might hurt the performance of your Web service if calls to the 3rd party API take a significant amount of time to complete and/or you are expecting many concurrent clients. If that was the case, your problem seems to be the perfect candidate for a service pattern called "Request/Acknowledge/Callback" (also "Request/Acknowledge/Relay"). Using that pattern, your Web API method will just store each request (including the callback URL) into a queue/database and return quickly. A separate module (possibly running on more than one machine, depending on the number and complexity of the tasks) will take care of completing the tasks, and subsequently notifying completion through the callback URL (please see http://servicedesignpatterns.com/ClientServiceInteractions/RequestAcknowledge).
This is presuming you want to return the results of your 3rd-party query to the caller.
You're correct, this is outside of what's possible with WebAPI. Once you return the HTTP Response, the client also has no connection to your server.
You should look into Asp.Net SignalR, which allows a persistent connection between the client and server, working in modern browsers, and even back to IE7 (though officially unsupported), as well as supporting non-browser clients.
You can then do a couple of things, all of which require the client to connect to SignalR first.
Option 1: You can call your WebApi controller, which can return, but not before launching a task. This task can query the 3rd party api, then invoke a function on the caller via SignalR with the results that you want to provide.
Option 2: You can call a SignalR Hub action, which can talk back to your client. You can tell your client the immediate response, query the 3rd-party api, then return the results you want to provide.

WCF when to use MessageHeader rather than passing variable in function argument

I am reading about MessageContract & MessageHeader and trying to understand the use case of sending some info in MessageHeader and not use it just as a function parameters?
Message contracts and message headers are somewhat advanced concepts which most people will never need to use. They're mostly used in interoperability scenarios where you need to communicate with a 3rd party service which expects the data in a certain format (i.e., some parameters in the headers).
Other possible scenarios for passing some parameters in message headers:
Headers can be easily accessed in message inspectors and other extensibility points in WCF (since headers are always buffered), so if you want to use some of those to do some validation (for example, some authentication decision), you may want to have the parameter in the header
As #Vasile mentioned, if you want to have a streamed transfer, since the headers are always buffered they can be used to convey some additional information to the operation prior to the (streamed) body being read / consumed
The MessageContract & MessageHeader provides lower-level control of your messages than DataContract & DataMember. Also it provides a way to create SOAP Headers if you're using webHttpBinding or basicHttpBinding.
If you're using streaming capabilities in your WCF service, than using MessageHeader is the only way to pass data besides the stream itself.
You can read more about message contracts in this MSDN article

WCF accessible via HTTP request with querystrings as parameters

I would like to create a WCF that can be invoked via a HTTP request and takes parameters in the URL.
Like:
http://someservice.svc/FetchEverything?User=xxx&category=clothes
The service should then return json in the response.
Would be thankful for advice.
Take a look at WCF Data Services. This allows you to easily expose an Entity Framework model (or part thereof) using a REST interface, or more precisely, an OData interface (= REST + AtomPub + query support).
Have a look at http://msdn.microsoft.com/en-us/library/cc668794.aspx.

Categories