Testing async web api methods with custom authorization - asp.net-web-api

I have a WebApi method looking more or less like this:
public async Task<HttpResponseMessage> Get(Guid id)
{
var foo = await Store.GetFooAsync(id);
if (foo.BelongsTo != User.Identity.Name)
throw new HttpResponseException(HttpStatusCode.Forbidden);
//return foo here
}
This seems to work fine in the actual application, where a custom IHttpModule sets the principal in both HttpContext.User and Thread.CurrentPrincipal.
However, when calling from a unit test:
Thread.CurrentPrincipal = principal;
var response = controller.Get(id).Result;
User is reset after await (i.e. on the continuation), so the test fails. This happens when running under R#8, and it wasn't happening with R#7.
My workaround was to save the current principal before the first await, but it's just a hack to satisfy the test runner needs.
How can I call my controller method and make sure continuations have the same principal as the original call?

I fixed this by upgrading the MVC packages. The new version keeps the principal in ApiController.RequestContext.Principal, separate from Thread.CurrentPrincipal, avoiding the problem completely.
My new test code starts with:
controller.RequestContext.Principal = principal;

The short version is, use HttpContext.Current.Use instead of Thread.Principal.
The short version is, use Request.LogonUserIdentity or Request.RequestContext.HttpContext.User.
async/await preserves the original request context, not the thread that started the method. This makes senses, otherwise ASP.NET would have to freeze the thread and have it available for when await returns. The thread you run after await is a thread from the ThreadPool, so modifying its CurrentPrincipal is a very bad idea.
Check the transcript from Scott Hanselman's podcast "Everything .NET programmers know about Asynchronous Programming is wrong" for more.

Related

EchoBot: How does control flow from BotController to EchoBot

I am looking at the EchoBot sample and trying to understand it. I see that BotController is mapped to api/messages and HttpPost which in turn invokes Adapter.ProcessAsync. But how does this translate into EchoBot.OnMessageActivityAsync call? I tried to set up a breakpoint and see the call stack but that doesn't help ( see attached screenshot).
I understand BotFrameworkHttpAdapter is invoked via dependency injection. But I don't know how we end up in EchoBot eventually.
To find the answer to this you really have to dive into the source code, so I hope you've got your scuba diving gear because we're going deep.
Step 1
Inside the BotController.cs file the following piece of code is called:
await Adapter.ProcessAsync(Request, Response, Bot);
which calls the ProcessAsync method on the IBotFrameworkHttpAdapter interface.
Step 2
Inside the Startup.cs file we have the following line:
services.AddSingleton<IBotFrameworkHttpAdapter, BotFrameworkHttpAdapter>();
which says that every time we ask for an IBotFrameworkHttpAdapter, provide the same instance of BotFrameworkHttpAdapter - essentially a static variable, you can read more about dependency injection service lifetimes here.
Step 3
Inside the Microsoft.Bot.Builder package we have the implementation for the ProcessAsync method, that can for our purposes be reduced to the following line:
var invokeResponse = await ProcessActivityAsync(authHeader, activity, bot.OnTurnAsync, cancellationToken).ConfigureAwait(false);
which calls ProcessActivityAsync which is another function that lives in this library - the important part here is the bot.OnTurnAsync parameter being passed in.
Step 5
Also inside the Microsoft.Bot.Builder package is the implementation for ProcessActivityAsync:
return await ProcessActivityAsync(claimsIdentity, activity, callback, cancellationToken).ConfigureAwait(false);
which calls an overload of the same method, but before we move on from here, the callback parameter is the bot.OnTurnAsync parameter that was passed through before.
Step 6
The overload of ProcessActivityAsync is also implemented inside the Microsoft.Bot.Builder package, and can be simplified to this line:
await RunPipelineAsync(context, callback, cancellationToken).ConfigureAwait(false);
where callback is bot.OnTurnAsync.
Step 7
Digging deeper still we find the implementation of the RunPipelineAsync method inside of the Microsoft.Bot.Builder package which is were things start to get a bit fuzzy... Theoretically we want to fall through to the else block where the callback (i.e. bot.OnTurnAsync) is called:
// Call any registered Middleware Components looking for ReceiveActivityAsync()
if (turnContext.Activity != null)
{
// Other code
}
else
{
// call back to caller on proactive case
if (callback != null)
{
await callback(turnContext, cancellationToken).ConfigureAwait(false);
}
}
However, back in Step 6 we also had this line:
using (var context = new TurnContext(this, activity))
where the context is created, and the activity property is initialised. This same context is pass through to the RunPipelineAsync call, which means that we will not fall through to the else block...
But there are the following comment on the RunPipelineAsync method:
/// <param name="callback">A callback method to run at the end of the pipeline.</param>
and inside the remarks section:
...Once control reaches the end of the pipeline, the adapter calls
the <paramref name="callback"/> method...
So I believe is it safe to say that our callback method is being executed which means that we continue by bubbling back up the chain to resolve the function that callback maps to (bot.OnTurnAsync).
Step 8
In BotController we pass in an instance of IBot to the ProcessAsync method, and in Startup we wire up all requests for an IBot to return an instance of EchoBot like so:
// Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
services.AddTransient<IBot, EchoBot>();
The EchoBot implementation inherits from the ActivityHandler class:
public class EchoBot : ActivityHandler
Step 9
The ActivityHandler class provides a default implementation for the OnTurnAsync method which I will simplify to:
switch (turnContext.Activity.Type)
{
case ActivityTypes.Message:
return OnMessageActivityAsync(new DelegatingTurnContext<IMessageActivity>(turnContext), cancellationToken);
// Other cases
}
which the OnMessageActivityAsync method on the same class that has an implementation that returns a completed task, i.e. is a no-op, however it is a virtual method - classes which inherit ActivityHandler can provide their own implementation.
Step 10
A custom implementation for OnMessageActivityAsync is provided inside the EchoBot class:
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
await turnContext.SendActivityAsync(MessageFactory.Text($"Echo: {turnContext.Activity.Text}"), cancellationToken);
}
where the user's input is echoed back to them, and thus our journey ends.
Regarding Step 7, the Microsoft team are pretty active on SO for things tagged with botframework so it might be best to get #mdrichardson or #tdurnford to clarify what happens here.
As an aside in Visual Studio you can debug some library code by enabling the following option:
Tools --> Options --> Debugger
Uncheck "Enable Just my Code"
Also if you enable navigation to decompiled sources (you will have to accept a legal notification popup) by doing this:
Tools --> Options --> Text Editor --> C# --> Advanced
Check "Enable navigation to decompiled sources"
You will be able to inspect the source code of external packages within Visual Studio itself.

Async/Await - not awaiting the async method [duplicate]

This question already has answers here:
Am I right to ignore the compiler warning for lacking await for this async call?
(3 answers)
Closed 7 years ago.
Below is my code. Compiler gives warning because AddLog is not awaited. I do not want to await this call and want to continue executing next lines. I dont have any concern if the exception is consumed also. Is it fine to ignore the warning?
public async Task Add()
{
this.AddLog( "Add executing" );
// Logic to Add Customer
}
public async Task AddLog( string message )
{
// Write to DB
}
Assuming you truly want to call the AddLog method in a fire-and-forget way, then you have a few options.
If, by design, you want AddLog to always be invoked as a fire-and-forget method, then you could change the signature to not return a Task.
public async void AddLog( string message ) // change Task to void
{
// Write to DB
// WARNING: Make sure that exceptions are handled in here.
}
However, if you do this, you better make sure that exceptions are properly handled from within the AddLog method. If any exception goes unhandled, it will crash your process.
Another option is to change the way you invoke AddLog to clearly state your intent that you don't care about when the Task completes, or about any exceptions that may be raised. You can do this by defining an empty continuation (Well, almost empty. See my edit at the bottom of the post for why it's a good idea to read the Task.Exception property at the very least).
// see EDIT for why the Task.Exception property is read here.
this.AddLog("Add executing").ContinueWith(t => { var observed = t.Exception; });
With either option, unless you are awaiting on other code inside your Add method that you are not showing us, then there is no longer any point in defining your Add method as async. You can simply turn it into a regular synchronous method. Otherwise, you'll then get another warning telling you that This async method lacks 'await' operators and will run synchronously....
public void Add() // no need for "async Task"
{
// see EDIT for why the Task.Exception property is read here.
this.AddLog("Add executing").ContinueWith(t => { var observed = t.Exception; });
// Logic to Add Customer
}
In any case, I wouldn't simply ignore the warning. Much like sometimes we get the warning Use of unassigned local variable 'x' in cases where we know that our code is fine, we typically don't ignore the warning. Instead, we may explicitly initialize the variable to null just to make our intent clear, and make the warning go away. Similarly, you can make the warning go away by making your intentions more explicit to the compiler using one of the above options.
EDIT: Word of caution about unobserved exceptions
I should also mention that even with the ContinueWith option, you may have to be careful about unhandled exceptions that come from your AddLog method.
According to this article, the way unobserved exceptions from tasks are handled has changed between .NET 4.0 and .NET 4.5. So, if you are still running .NET 4.0, or if you forcing .NET 4.0 exception behavior via configuration, you run the risk that unhandled exceptions will crash your process whenever the task gets GC-collected and finalized.
To make sure that this is not a problem, you can adjust the continuation to explicitly observe the exception, if any is present. You don't actually need to do anything with it, you just need to read it. This is one way to do it safely:
this.AddLog("Add executing").ContinueWith(t => { var observed = t.Exception; });
I've updated my earlier examples above to use the safer version of the continuation.
I would make add() non async since it isn't...and then task.run on add log

Claims not persisting in Session Token

Have seen Dominick Baier's videos on Pluralsight and most of this I got from there. I'm trying to do a claims transformation in .net 4.5, MVC. After a lot of messing around I can get the claims transformed, but can't get them to persist. If I just have it run my ClaimsTransformer every time no problem, but this is hitting a database so I want to cache these.
So here's what I did
class ClaimsTransformer : ClaimsAuthenticationManager
{
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (!incomingPrincipal.Identity.IsAuthenticated)
{
return base.Authenticate(resourceName, incomingPrincipal);
}
ClaimsPrincipal transformedPrincipal = incomingPrincipal;
I then perform some database access add new claims to transformedPrincipal. Then create a new principal (probably don't need this additional instantiation but others seemed to do it), write this out:
ClaimsPrincipal newClaimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(transformedPrincipal.Claims, "ApplicationCookie"));
if (HttpContext.Current != null)
{
// this caches the transformed claims
var sessionToken = new SessionSecurityToken(newClaimsPrincipal, TimeSpan.FromHours(8));
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
}
return newClaimsPrincipal;
I can see the new claims here in newClaimsPrincipal. To force the transformation to get called I am using ClaimsTransformationHttpModule from the ThinkTecture guys and can verify that this code gets run:
context.User = transformedPrincipal;
HttpContext.Current.User = transformedPrincipal;
Thread.CurrentPrincipal = transformedPrincipal;
And my additional claims are part of the transformedPrincipal.
So looks fine - but when subsequent requests come in I don't have the additional claims. ClaimsTransformer is not called, as expected, but I only have the initial set of claims - not those added by my transformation.
After logging out, my additional claims are persisted. This is using the new Visual Studio 2013 basic MVC template with Identity 2.0etc.
What I think is happening is the login runs first:
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
and this writes the authentication cookie, before my claims are transformed. Following this my claimstransformer runs and writes its own authorization cookie so now I have two. When I logout the first one's claims are lost and not the second one's claims become active.
Am confused.com.
Thanks
Ray
Looks like you are mixing the two architectures.
ClaimsAuthenticationManager and FederatedAuthentication.SessionAuthenticationModule are the .NET 4.5 way of doing things. Also called the WIF method.
SignInManager is OWIN.
Indeed don't use the WIF things in this way when you are using OWIN.
This should clarify/solve half your problem. Now you still need a ClaimsTransform in OWIN. Some filter should do it and then persist it in the OWIN identity Cookie (haven't yet done it myself).

Is JavaSamplerClient the right way to test this setup?

I have a java server that communicates with java clients over the network. What I want to do is to verify that they are maintaining state and gather performance statistics for the server. I've used JMeter to test web services in the past and thought to use it to test this server.
The clients are pretty simple and only send and receive a few message types. They login to the server and create a session id. Then they can do a number of transactions using that id, get text data, send text data, ping to verify the connection is alive and finally logout.
Initially I thought I'd wrap the client code in a JavaSamplerClient, but having read the javadocs again I'm not sure that is a good idea. JavaSamplerClient looks like it expects to do one thing and return the same kind of data. But I want to not only return the performance numbers, but I want to verify that the state of the client and check that the data is not being corrupted.
Is using JavaSamplerClient in JMeter the right thing to use here or is there a better solution?
JavaSamplerClient can do everything you'll implement.
For instance, if you create your class as follows:
public class MySampler extends AbstractJavaSamplerClient {
#Override
public void setupTest(JavaSamplerContext context) {
return;
}
#Override
public SampleResult runTest(JavaSamplerContext context) {
return null;
}
#Override
public Arguments getDefaultParameters() {
return null;
}
If you don't intent to use GUI for sampler you can omit setupTest and getDefaultParameters methods and leave only runTest one.
Your test code should be placed inside runTest method. It returns an instance of SampleResult which is fully controllable.
for instance:
result.setResponseCode() - set response code based on any condition
result.setResponseMessage() - the same for response message
The bit you're looking for is probably
result.setResponseData() - here you can make your sampler to return anything you want.
Reference material: Beanshell vs JSR223 vs Java JMeter Scripting

Meteor 0.5.9: replacement for using Session in a server method?

So, I was attempting to do something like the following:
if(Meteor.isServer){
Meteor.methods({connect_to_api: function(vars){
// get data from remote API
return data;
}});
}
if(Meteor.isClient){
Template.myTpl.content = function(){
Meteor.call('connect_to_api', vars, function(err,data){
Session.set('placeholder', data);
});
return Session.get('placeholder');
};
}
This seemed to be working fine, but, of course, now breaks in 0.5.9 as the Session object has been removed from the server. How in the world do you now create a reactive Template that uses a server-only (stuff we don't want loading on the client) method call and get data back from that Method call. You can't put any Session references in the callback function because it doesn't exist on the server, and I don't know of any other reactive data sources available for this scenario.
I'm pretty new to Meteor, so I'm really trying to pin down best-practices stuff that has the best chance of being future-proof. Apparently the above implementation was not it.
EDIT: To clarify, this is not a problem of when I'm returning from the Template function. This is a problem of Session existing on the server. The above code will generate the following error message on the server:
Exception while invoking method 'connect_to_api' ReferenceError: Session is not defined
at Meteor.methods.connect_to_api (path/to/file.js:#:#)
at _.extend.protocol_handlers.method.exception ... etc etc
Setting the session in the callback seems to work fine, see this project I created on github: https://github.com/jtblin/meteor_session_test. In this example, I return data in a server method, and set it in the session in the callback.
There are 2 issues with your code:
1) Missing closing brace placement in Meteor.methods. The code should be:
Meteor.methods({
connect_to_api: function(vars) {
// get data from remote API
return data;
}
});
2) As explained above, you return the value in the session, before the callback is completed, i.e. before the callback method had the time to set the session variable. I guess this is why you don't see any data in the session variable yet.
I feel like an idiot (not the first time, not the last). Thanks to jtblin for showing me that Session.set does indeed work in the callback, I went back and scoured my Meteor.method function. Turns out there was one spot buried in the code where I was using Session.get which was what was throwing the error. Once I passed that value in from the client rather than trying to get it in the method itself, all was right with the world.
Oh, and you can indeed order things as above without issue.

Resources