ASP.NET Web API: any downsides to asynchronous operations? - c#

I'm setting up a Web API that will serve a client over our Intranet. For the sake of convenience for the developers working on the client, I am considering having the Web API adhere to an interface that will be shared with the client, something like what is shown below.
The purpose of using a shared interface mostly has to do with making changes to the Web API detectable by the client developers at compile time. Also, the client can leverage the interface to be used for wrappers around HttpClient instances that will be used to communicate with the Web API.
The client developers would like to use async and await throughout their implementation, and who am I to say "no"?
public interface IValueController
{
Task<string> ReadAsync();
string ReadSync();
}
[Route("api/v1/[controller]")]
public class ValueController : Controller, IValueController
{
[HttpGet("async")]
public Task<string> ReadAsync()
{
return Task.FromResult("async!");
}
[HttpGet("sync")]
public string ReadSync()
{
return "sync!";
}
}
I'm not all that interested in providing both synchronous and asynchronous methods - one of them will have to do. The question is: Is there any down-side to defining the Web API operations as asynchronous? If not, I'm going all-in!
-S

When to use Async:
Async API calls.
Long Running database queries.
Tasks that are CPU bound.
When you need to achieve parallelism.
When not to use: While writing any quick running tasks or methods.
NOTE: Beware of deadlocks as the compiler allows you to write and successfully compile async code even without understanding it's basic concept.

The purpose of using a shared interface mostly has to do with making changes to the Web API detectable by the client developers at compile time.
These days, it's more common to auto-generate an API description (e.g., Swagger), and then auto-generate clients from that (which can be .NET or other languages). Not only does this approach allow multiple clients (e.g., one Swagger client is HTML documentation for your APIs, complete with examples and the ability to invoke them right from the website), but it also handles the synchronous/asynchronous translation for you without requiring any kind of "async signature but really it's sync" code.
That said, if you wanted to implement asynchronous methods synchronously, there's nothing that would prevent it. The only gotcha I can think of is that if you're on full ASP.NET, then asynchronous actions cannot be child actions. This restriction no longer exists on ASP.NET Core.

Related

How to determine in which order IHostedServices are being called at shutdown?

I'm maintaining a integration package that allows my users to integrate my library with ASP.NET Core. This package must be compatible with all versions of ASP.NET Core starting at 2.1. At application shutdown my integration package must be able to execute asynchronous cleanup, and unfortunately can't take a dependency on IAsyncDisposable through Microsoft.Bcl.AsyncInterfaces (see below).
The only way this, therefore, seems feasible is by registering an IHostedService implementation. It's StopAsync method is called at shutdown:
public sealed class ShutdownHostedService : IHostedService
{
public MyLibaryCleanupObject Obj;
public Task StartAsync(CancellationToken token) => Task.CompletedTask;
public Task StopAsync(CancellationToken token) => this.Obj.CleanupAsync();
}
services.AddSingleton<IHostedService>(new ShutdownHostedService { Obj = ... });
Application developers, however, can of course add their own IHostedService implementations, which might interact with my library. This is why it is important for my own IHostedService implementation to be called last. But here lies the problem.
With the introduction of ASP.NET Core 2.1 application developers can choose between using the new Microsoft.Extensions.Hosting.Host and the (now deprecated) Microsoft.AspNetCore.WebHost. With WebHost, at shutdown, IHostedService implementations are called in order of registration, whereas with Host, IHostedService implementations are called in opposite order of registration.
This is problematic for me, because my hosted service should be called last. As application developers might use my integration package in their existing ASP.NET Core application, they might still use WebHost, which is why it is important to support that scenario.
Question: What would be a reliable way to determine in what 'mode' the ASP.NET Core application runs, so I can decide to add my hosted service first or last?
Alternatively, to prevent falling into the XY-problem trap, I'm open to completely different solutions that solve my problem of implementing "asynchronous shutdown".
Note on IAsyncDisposable:
One solution that would come to mind (as Ian rightfully notes in the comments) is to add an IAsyncDisposable Singleton registration to the ServiceCollection. This would allow asynchronous cleanup at shutdown. Unfortunately, due to constraints (explained here) it's impossible for my integration package to take a dependency on Microsoft.Bcl.AsyncInterfaces and, therefore, not on IAsyncDisposable. This is an unfortunate situation that certainly complicates the matter. As a matter of fact, the reason for not being able to take a dependency on IAsyncDisposable is the reason I'm looking for alternative ways of implementing asynchronous shutdown code.
The solution I end up using is identical to the solution chosen by Microsoft's Microsoft.Extensions.Hosting.Internal.Host class and doesn't involve using IHostedService instances. The Host class contains the following Dispose method:
public void Dispose()
{
this.DisposeAsync().GetAwaiter().GetResult();
}
This might raise some eyebrows and might be seen as a bad practice, but don't forget that:
This code is guaranteed to run in the context of ASP.NET Core, where this code can't cause a deadlock
This code runs just once at shutdown, so performance isn't an issue here.
This is why Microsoft's Host class can take this approach, and it means that it is a safe approach for my library to do as well.

When use async/await on .net core web-api with repository pattern?

I'm trying to write a simple web api service with Users CRUD, i'm a bit confused about using async/await methods in repository pattern...
pattern flow is: CONTROLLER > BLOGIC > REPOSITORY
where i must use async/await methods ?
in all layers or only at the top (controller layer)?
async is "bubbling" up in your code structure, so obviously main source of asynchronous code should be your repository layer, but to leverage it being asynchronous you will need to make all calling code to be asynchronous too (or just return Task<T> if caller just passes results without doing anything with them) otherwise you will need to block on asynchronous call which basically not only removes all possible gains from it but also in some cases can introduce issues.
Also please read this answer.

How would I pass a Web API Request through Dependency Injection?

I am having a Web API application in which the controller has Services/Repositories etc. injected into it through Dependency Injection (Unity). Let's assume that I have an IStuffService that needs the IPrincipal of the current request (or a wrapper around it).
The problem with Web API seems to be that the only reliable source of the current Request/User is the Request property on the instance of the ApiController. Anything static (be it HttpContext.Current, CallContext.Get/SetData or Thread.Get/SetData) is not guaranteed to be on the same thread due to the sync nature of Web API.
How do I reliably ensure that Request-specific context is passed through dependencies, and more importantly, that the operation retains the correct IPrincipal all the way through the operation?
Two options:
Every method that needs an IPrincipal has it as an argument to the method - that is the most reliable way, but it also requires me to have that thing in every method signature
Inject the IPrincipal into the ctor of the Service, spinning up a new insance of the object graph on every request, using a DependencyOverride in Unity: container.Resolve(opType, new DependencyOverride(typeof(IPrincipal), principal))
Option 2 means that my method signatures are clean, but it also means I need to make sure all dependencies are using the TransientLifetimeManager, not a Singleton or even Per-Thread one.
Is there a better solution than I'm not seeing?
From the comments:
#MichaelStum, I believe HttpContext.User should be flowed correctly
across async/await (within the same HTTP request). Is it not for you?
– Noseratio 17 hours ago
#Noseratio See the other answers - in .net 4.0, it's bound to the
current thread and was not properly maintained. It seems that in 4.5,
this might be fixed. That said, HttpContext.Current is still not that
appropriate in Web API because on self-hosted ones there is no
HttpContext.Current.
AFAIK, there's no proper support for async/await in ASP.NET 4.0 anyway (you probably can use Microsoft.Bcl.Async for the language support, but there is no ASP.NET runtime support, so you'd have to resort to AsyncManager to implement the TAP pattern).
That said, I'm 99% sure Thread.CurrentPrincipal would still be correctly flowed across await continuations in ASP.NET 4.0. That's because it gets flowed as a part of ExecutionContext flow, rather than by synchronization context. As to HtttContext.Current.User, I'm not sure if it would flow correctly in ASP.NET 4.0 (although it certainly does in ASP.NET 4.5).
I've re-read your question, but could find an explicit complaint about Thread.CurrentPrincipal not being correctly flowed. Are you experiencing this issue in existing code (if so, it probably would be a bug in ASP.NET)?
Here's a list of related questions, answered with some great insights by Stephen Cleary:
Understanding context in C# 5 async/await
Why is an "await Task.Yield()" required for Thread.CurrentPrincipal to flow correctly?
Using ASP.NET Web API, my ExecutionContext isn't flowing in async actions
This blog post by Scott Hanselman is also related, although he speaks about WebForms:
System.Threading.Thread.CurrentPrincipal vs. System.Web.HttpContext.Current.User or why FormsAuthentication can be subtle
If you're concerned about self-hosting scenarios, I believe Thread.CurrentPrincipal will still be flowed correctly there (once having been set to a correct identity). If you want to flow any other properties (besides those which get automatically flowed with ExecutionContext), you can roll out your own synchronization context. Another option (not so nice, IMO) is to use custom awaiters.
Finally, if you face a situation where you actually require thread affinity across await continuation (much like in a client side UI app), you have such option, too (again, using a custom synchronization context):
How to use non-thread-safe async/await APIs and patterns with ASP.NET Web API?
The ultimate answer is that our IoC containers need to be changed to support async/await better.
Background:
The behavior of async/await around this changed between .NET 4 and .NET 4.5. In .NET 4.5 the SynchronizationContext was introduced and it will correctly restore HttpContext.Current (see http://msdn.microsoft.com/en-us/magazine/gg598924.aspx). However, it is often a best practice to use .ConfigureAwait(false) (see "Configure Context" in http://msdn.microsoft.com/en-us/magazine/jj991977.aspx) and that specifically requests that the context not be preserved. In that case you would still have the issue you describe.
Answer:
The best answer I have been able to come up with in my own code is to be sure to request the dependency that comes from HttpContext.Current (in your case IPrincipal) early in the web request so that is is loaded into the container.
I don't have any experience with Unity, but in Ninject this would look something like:
kernal.Bind<IPrincipal>().ToMethod(c => HttpContext.Current.User).InRequestScope();
Then I would be sure to load the IPrincipal early in the web request before you have lost the context. Either in BeginRequest or as a dependency of the controller. That will cause the IPrincipal to be loaded into the container for this request.
Note: There are still situations where this may not work. I don't know if Unity has this issue, but I know Ninject does. It actually uses the HttpContext.Current, to determine what request is active. So if you try to resolve something from the container later, like a service locator or factory then it may not be able to resolve.
I know this is an old question I have worked with option one (in the question) and, it works.
UPDATE: I deleted my answer as I realized I've posted something that doesn't work.
Sorry for any inconvenience.
How do I reliably ensure that Request-specific context is passed
through dependencies, and more importantly, that the operation retains
the correct IPrincipal all the way through the operation?
I don't think you should do this. Your service is a lower layer than your Api controller. Your service should not depend on any classes related to the higher layer, otherwise your service could not be reused, for example: when you need to build a win forms application on top of the existing services.
IPrincipal is not appropriate to be injected into our services as it's web application related . When we pass this information down to lower layers (service), we should pass our neutral-classes or just a userId to decouple our services from the application using it.
You should define your own classes for Users and anything request-related to be used in our services layer as it's more domain-related. With this, your service-layer is application-layer (web, win forms, console,..) agnostic:
public class AppPrincipal : IAppPrincipal
{
public int UserId { get; set; }
public string Role { get; set; }
//other properties
public AppPrincipal() {
}
public AppPrincipal(int userId, string role):this() {
UserId = userId;
Role = role;
}
}
Then you can register IAppPrincipal as per-request scope in your web application and populate all the properties using your IPrincipal. The will initialize your IAppPrincipal for your entire object graph before any await/async calls. Example code with Unity:
public void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IAppPrincipal>(
new PerRequestLifetimeManager(),
new InjectionFactory(c => CreateAppPrincipal()));
}
public IAppPrincipal CreateAppPrincipal()
{
var principal = new AppPrincipal();
principal.UserId = //Retrieve userId from your IPrincipal (HttpContext.Current.User)
principal.Role = //Retrieve role from your IPrincipal (HttpContext.Current.User)
return principal;
}
The key here is that we already decouple our service layer from the web. If you need to reuse your service layer to build a windows form or console application, you could register IAppPrincipal as singleton and populate it differently.
We don't need to deal with platform-related problems like async/await

Asp.Net Web Api Versioning with Load Balancer (Layer 4)

I'm currently in charge of developing a rather complex REST api with .Net and Web Api.
The interface should later be consumed by various public and private (in house) Clients.
I read a lot about how you should version your api, but opinions seem to be very different.
The application runs behind a load balancer in a multi server environment.
Now my problem is, the load balancer is hard restricted and only supports layer 4 load balancing, so I'm not able to inspect the URL / headers etc. of the incoming requests to route them to the correct version of the application.
We don't want to have versioned api controllers in our code base since we have a lot external dependecies which should be updated frequently, so we could break some functionality.
Currently it seems to be the only solution to use subdomains for versioning, e.g.
ver1.api.domain.com
Is there anything against this approach, do you have other solutions?
The issue with that versioning approach is that there will be duplicate entries for all resources including un-modified ones.
In my opinion, a better approach is to include the version of a resource in the Uri.
Let's have a look at a concrete example. Supposing there is a CarsController like the one below:
public class CarsController : ApiController
{
[Route("cars/{id}")]
public async Task<IHttpActionResult> Get(int id)
{
DoSomething();
return Ok(result);
}
}
After the first release, we introduce the second version of the Get method, we can do something like
[Route("cars/{id}/v2")]
public async Task<IHttpActionResult> GetCarsVersion2(int id)
{
DoSomethingElse();
return Ok(result);
}
So the existing clients still refer to the old Uri /Cars/{id}, whereas new clients can use the new Uri /Cars/{id}/v2.
In addition, if there aren't many differences between the two versions, the original implementation can be refactored to satisfy new requirements. Which, in turns, reduces code duplication.

Creating asynchronous WCF clients without using Service References

Currently I do not use Service References as I feel the code it autogenerates is more weight than I need. Instead I generate a proxy class by doing:
public class MyClient : ClientBase<IMyService>, IMyService
This has worked great for me, no proxy classes are generated so I reuse the same datatypes. But this only lets me create synchronous client methods.
What would it take to generate async versions? I have taken a look at the autogenerated code that adding a Service Reference would do and it seems like soo much boilerplate. A ton of begin/end/onbegin/oncomplete associated event arg datatypes etc etc.
Is there a simpler way with less scaffolding needed to create async client methods?
My ultimate end goal is to be able to use the new c# 5 async/await keywords on webservice clients
You can always author a contract IMyAsyncService that is exactly like IMyService but uses the Begin/End async pattern (and has [ServiceContract(Name="IMyService")] to keep the same name). It will be the same wire contract, and work with ClientBase, but now you have async methods you can use with await.
I think adding this
[OperationContract(IsOneWay = true)]
to your method declaration in the Interface on your services will determine its async.
The CTP for async/await is just a preview of the support for these features. They plan to fully integrate them into WCF.
http://blogs.msdn.com/b/endpoint/archive/2010/11/13/simplified-asynchronous-programming-model-in-wcf-with-async-await.aspx

Categories

Resources