Modeling Client Context in WCF Web API with MEF - wcf-web-api

I need to extract several header values at the start of each request and place them into a ClientContext object that can be injected into my application code by MEF. I am using Preview 5 of the WCF Web API and don't see a way to do this.
In 'standard' WCF, I would create a class that implements IExtension<OperationContext> and have the following property to wire it all together:
[Export(typeof(IClientContext)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public static ClientContextExtension Current
{
get
{
var operationContext = OperationContext.Current;
if (operationContext == null)
return null;
var extension = operationContext.Extensions.Find<ClientContextExtension>();
if (extension == null)
{
extension = new ClientContextExtension();
operationContext.Extensions.Add(extension);
}
return extension;
}
}
A custom DelegatingHandler calls ClientContextExtension.Current and sets the properties from the header values. Unfortunately, with WCF Web API, OperationContext.Current is always null!
I cannot figure out a way to make this work with the Web API. Any help is appreciated!!!

I've come up with a working solution but remain open to other options. First, some rationale behind the original approach...
Because WCF uses thread pooling, anything based on a per-thread model may (and will) have a lifetime that extends beyond an individual request. I needed a way to store client context information pulled from the HTTP headers for each request as the information will be different each time. This means I can't persist the context information per-thread because the thread will be re-used.
Or can I?
The flaw in my logic was that thread re-use was the problem. In reality, each thread is only every servicing a single request at one time thereby making any information in that thread isolated to that request. Therefore, all I need to do is make sure that the information is relavent to that request and my problem is solved.
My solution was to refactor the Current property to reference a private static field marked with the [ThreadStatic()] attribute, ensuring that each instance was specific to the thread. Then, in my DelegatingHandler, which executes for each request, I reset the properties of the object for that request. Subsequent calls to Current during that request return the request-specific information and the next request handled by the thread gets updated in the DelegatingHandler so as far as my other code is concerned, the context is per-request.
Not perfect, but it at least gets me up and running for the moment. As I said, I am open to other solutions.
UPDATE
Upon closer inspection, this solution is not working as there is no thread affinity between the DelegatingHandler and the service code that is making use of the context object. As a result, sometimes my call to retrieve the ThreadStatic object works as expected but on other occasions I get a new instance because the code is operating on a different thread than the handler.
So, disregard this solution. Back to the drawing board.
UPDATE TO MY UPDATE
After discussing my problem with Glenn Block, it turns out that it is just a matter of making sure the context is set on the same thread the request handler (the service) is executing. The solution is to use an HttpOperationHandler instead of a MessageHandler.
According to Glenn, message handlers operate asynchronously which means they could execute on a different thread from the request handler (service) so we should never do anything in a message handler that requires thread affinity. On the other hand, operation handlers run synchronously on the same thread as the request handler, therefore we can rely on thread affinity.
So, I simply moved my code from a MessageHandler to an HttpOperationHandler and have the desired results.
You can read a full explanation here: http://sonofpirate.blogspot.com/2011/11/modeling-client-context-in-wcf-web-api.html

You can try to use a
HttpOperationHandler<HttpRequestMessage, HttpRequestMessage>
There you should be able to access the headers.

Related

ServiceStack: Reinstate pipeline when invoking a Service manually?

As a follow-up to this question, I wanted to understand how my invoking of a Service manually can be improved. This became longer than I wanted, but I feel the background info is needed.
When doing a pub/sub (broadcast), the normal sequence and flow in the Messaging API isn't used, and I instead get a callback when a pub/sub message is received, using IRedisClient, IRedisSubscription:
_subscription.OnMessage = (channel, msg) =>
{
onMessageReceived(ParseJsonMsgToPoco(msg));
};
The Action onMessageReceived will then, in turn, invoke a normal .NET/C# Event, like so:
protected override void OnMessageReceived(MyRequest request)
{
OnMyEvent?.Invoke(this, new RequestEventArgs(request));
}
This works, I get my request and all that, however, I would like it to be streamlined into the other flow, the flow in the Messaging API, meaning, the request finds its way into a Service class implementation, and that all normal boilerplate and dependency injection takes place as it would have using Messaging API.
So, in my Event handler, I manually invoke the Service:
private void Instance_OnMyEvent(object sender, RequestEventArgs e)
{
using (var myRequestService = HostContext.ResolveService<MyRequestService>(new BasicRequest()))
{
myRequestService.Any(e.Request);
}
}
and the MyRequestService is indeed found and Any called, and dependency injection works for the Service.
Question 1:
Methods such as OnBeforeExecute, OnAfterExecute etc, are not called, unless I manually call them, like: myRequestService.OnBeforeExecute(e) etc. What parts of the pipeline is lost? Can it be reinstated in some easy way, so I don't have to call each of them, in order, manually?
Question 2:
I think I am messing up the DI system when I do this:
using (var myRequestService = HostContext.ResolveService<MyRequestService>(new BasicRequest()))
{
myRequestService.OnBeforeExecute(e.Request);
myRequestService.Any(e.Request);
myRequestService.OnAfterExecute(e.Request);
}
The effect I see is that the injected dependencies that I have registered with container.AddScoped, isn't scoped, but seems static. I see this because I have a Guid inside the injected class, and that Guid is always the same in this case, when it should be different for each request.
container.AddScoped<IRedisCache, RedisCache>();
and the OnBeforeExecute (in a descendant to Service) is like:
public override void OnBeforeExecute(object requestDto)
{
base.OnBeforeExecute(requestDto);
IRedisCache cache = TryResolve<IRedisCache>();
cache?.SetGuid(Guid.NewGuid());
}
So, the IRedisCache Guid should be different each time, but it isn't. This however works fine when I use the Messaging API "from start to finish". It seems that if I call the TryResolve in the AppHostBase descendant, the AddScoped is ignored, and an instance is placed in the container, and then never removed.
What parts of the pipeline is lost?
None of the request pipeline is executed:
myRequestService.Any(e.Request);
Is physically only invoking the Any C# method of your MyRequestService class, it doesn't (nor cannot) do anything else.
The recommended way for invoking other Services during a Service Request is to use the Service Gateway.
But if you want to invoke a Service outside of a HTTP Request you can use the RPC Gateway for executing non-trusted services as it invokes the full Request Pipeline & converts HTTP Error responses into Typed Error Responses:
HostContext.AppHost.RpcGateway.ExecuteAsync()
For executing internal/trusted Services outside of a Service Request you can use HostContext.AppHost.ExecuteMessage as used by ServiceStack MQ which applies Message Request Request/Response Filters, Service Action Filters & Events.
I have registered with container.AddScoped
Do not use Request Scoped dependencies outside of a HTTP Request, use Singleton if the dependencies are ThreadSafe, otherwise register them as Transient. If you need to pass per-request storage pass them in IRequest.Items.

Ninject: What is MvcModule: GlobalKernelRegistrationModule<OnePerRequestHttpModule>?

I'm seeing Ninject source code, I cannot understand the MvcModule (source code in github).
Why the OnePerRequestHttpModule stand as a generic template type? What does it mean for?
As you undoubtedly know, Ninject.Web.Common defines InRequestScope. This scope is for the activations that should live for the lifetime of a single http request. When an http request is finished, you might want to clear your activation cache for this request, but how do you know that the request has ended?
Well, the usual way of finding out is creating an Http Module and subscribing for the EndRequest event.
Suppose you've done that. Now you need to implement the event handler. In the event handler you want to clear your activation cache for this request, but how does the handler know where this activation cache is located? Ultimately this cache is part of ninject kernel, so if only you could get access to that.
But that's no problem, right? You are the implementer, so why don't you wire up your HttpModule during your kernel set-up?
Unfortunately there are quite a few problems with this approach. First, HttpModules have to be registered during the pre application startup up phase and there is no guarantee that your kernel will be created at that time. More importantly, what if you have multiple kernels? Does each of these going to create a new instance of HTTP Module? Better to avoid that.
So this is what ninject does.
The GlobalKernelRegistration class is almost static class that keeps per domain collection of kernels. It has one instance method - protected void MapKernels(Action<IKernel> action). This method executes and action on every kernel in the list. The kernel lists are kept per registration type, such as OnePerRequestHttpModule.
So what you (as a ninject author) do is derive OnePerRequestHttpModule from GlobalKernelRegistration and then in your implementation of EndRequest event handler you use this.MapKernels to execute your code to clean up the activation cache for the request.
GlobalKernelRegistrationModule class is a simple class that registers your generic type parameter (in your case OnePerRequestHttpModule) and the current kernel in the registry (GlobalKernelRegistration).
When you derive your MvcModule from GlobalKernelRegistrationModule<OnePerRequestHttpModule> this registration happens automatically when your MvcModule is loaded into the kernel.
You also need to make sure that OnePerRequestHttpModule is registered as an Http Module which is usually done in the bootstrap code inside NinjectWebCommon.cs or in NinjectHttpApplication (if the project is not using webapi).
It deactivates objects InRequestScope after the request ended.

Calling ConfigureAwait from an ASP.NET MVC Action

I was working on a presentation and thought the following should fail since the ActionResult isn't being returned on the right context. I've load tested it with VS and got no errors. I've debugged it and know that it is switching threads. So it seems like it is legit code.
Does ASP.NET not care what context or thread it is on like a client app? If so, what purpose does the AspNetSynchronizationContext provide? I don't feel right putting a ConfigureAwait in the action itself. Something seems wrong about it. Can anyone explain?
public async Task<ActionResult> AsyncWithBackendTest()
{
var result = await BackendCall().ConfigureAwait(false);
var server = HttpContext.Server;
HttpContext.Cache["hello"] = "world";
return Content(result);
}
ASP.NET doesn't have the 'UI thread' need that many clients apps do (due to the UI framework below it). That context isn't about thread affinity, but for tracking the page progress (and other things, like carrying around the security context for the request)
Stephen Toub mentions this in an MSDN article:
Windows Forms isn't the only environment that provides a
SynchronizationContext-derived class. ASP.NET also provides one,
AspNetSynchronizationContext, though it's not public and is not meant
for external consumption. Rather, it is used under the covers by
ASP.NET to facilitate the asynchronous pages functionality in ASP.NET
2.0 (for more information, see msdn.microsoft.com/msdnmag/issues/05/10/WickedCode). This
implementation allows ASP.NET to prevent page processing completion
until all outstanding asynchronous invocations have been completed.
A little more detail about the synchronization context is given in Stephen Cleary's article from last year.
Figure 4 in particular shows that it doesn't have the 'specific thread' behavior of WinForms/WPF, but the whole thing is a great read.
If multiple operations complete at once for the same application,
AspNetSynchronizationContext will ensure that they execute one at a
time. They may execute on any thread, but that thread will have the
identity and culture of the original page.
In your code, HttpContext is a member of your AsyncController base class. It is not the current context for the executing thread.
Also, in your case, HttpContext is still valid, since the request has not yet completed.
I'm unable to test this at the moment, but I would expect it to fail if you used System.Web.HttpContext.Current instead of HttpContext.
P.S. Security is always propagated, regardless of ConfigureAwait - this makes sense if you think about it. I'm not sure about culture, but I wouldn't be surprised if it was always propagated too.
It appears because the Controller captures the Context whereas using System.Web.HttpContext is live access to what is part of the synchronization context.
If we look at the ASP.NET MVC5 sources we can see that the ControllerBase class that all controllers inherit from has its own ControllerContext which is built from the RequestContext.
I would assume this means that while the synchronization context is lost after a ConfigureAwait(false); the state of the Controller in which the continuation is happening still has access to the state of the control from before the continuation via the closure.
Outside of the Controller we don't have access to this ControllerContext so we have to use the live System.Web.HttpContext which has all the caveats with ConfigureAwait(false);.

Inject behavior into WCF After or During identification of WebGet Method to call

I am trying to solve a problem where i have a WCF system that i have built a custom Host, Factory host, instance providers and service behaviors to do authentication and dependency injection.
However I have come up with a problem at the authorisation level as I would like to do authorisation at the level of the method being called.
For example
[OperationContract]
[WebGet(UriTemplate = "/{ConstituentNumber}/")]
public Constituent GetConstituent(string ConstituentNumber)
{
Authorisation.Factory.Instance.IsAuthorised(MethodBase.GetCurrentMethod().Name, WebOperationContext.Current.IncomingRequest.Headers["Authorization"]);
return constituentSoapService.GetConstituentDetails(ConstituentNumber);
}
Basically I now have to copy the Call to IsAuthorised across every web method I have. This has two problems.
It is not very testable. I Have extracted the dependecies as best that I can. But this setup means that I have to mock out calls to the database and calls to the
WebOperationContext.
I Have to Copy that Method over and over again.
What I would like to know is, is there a spot in the WCF pipeline that enables me to know which method is about to be called. Execute the authorisation request. and then execute the method based on the true false value of the authorisation response.
Even better if i can build an attribute that will say how to evaluate the method.
One possible way to do what you want might be by intercepting requests with a custom IDispatchMessageInspector (or similar WCF extension point).
The trick there, however, is that all you get is the raw message, but not where it will be processed (i.e. the method name). With a bit of work, however, it should be possible to build a map of URIs/actions and the matching method names (this is how you'd do it for SOAP, though haven't tried it for WebGet/WebInvoke yet).

wcf - transfer context into the headers

I am using wcf 4 and trying to transparently transfer context information between client and server.
I was looking at behaviors and was able to pass things around. My problem is how to flow the context received in the incoming headers to the other services that might be called by a service.
In the service behavior I intercept the the message and read the headers but don't know where to put that data to be accessible to the next service call that the current service might make.
What I am looking for is something like:
public void DoWork()
{
var someId = MyContext.SomeId;
//do something with it here and call another service
using(var proxy = GetProxy<IAnotherService>())
proxy.CallSomeOtherMethodThatShouldGetAccessTo_ MyContextualObject();
}
If I store the headers in thread local storage I might have problems due to thread agility(not sure this happens outside ASP.NET, aka custom service hosts). How would you implement the MyContext in the code above.
I chose the MyContext instead of accessing the headers directly because the initiator of the service call might not be a service in which case the MyContext is backed by HttpContext for example for storage.
In the service behavior I intercept
the the message and read the headers
but don't know where to put that data
to be accessible to the next service
call.
Typically, you don't have any state between calls. Each call is totally autonomous, each call gets a brand new instance of your service class created from scratch. That's the recommended best practice.
If you need to pass that piece of information (language, settings, whatever) to a second, third, fourth call, do so by passing it in their headers, too. Do not start to put state into the WCF server side! WCF services should always be totally autonomous and not retain any state, if at ever possible.
UPDATE: ok, after your comments: what might be of interest to you is the new RoutingService base class that will be shipped with WCF 4. It allows scenarios like you describe - getting a message from the outside and forwarding it to another service somewhere in the background. Google for "WCF4 RoutingService" - you should find a number of articles. I couldn't find antyhing in specific about headers, but I guess those would be transparently transported along.
There's also a two-part article series Building a WCF Router Part 1 (and part 2 here) in MSDN Magazine that accomplishes more or less the same in WCF 3.5 - again, not sure about headers, but maybe that could give you an idea.