ASP.NET Task Await Ajax - c#

So, I'm just catching up on the old MVC 5 stuff now that I'm out of university.
I just looked at this implementation, its point 3. about registering a user, i noticed it used async:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser() { UserName = model.UserName };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInAsync(user, isPersistent: false);
return RedirectToAction("Index", "Home");
}
else
{
AddErrors(result);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
I just want a bit of clarity, I am familiar with the async keyword and its association with Task and await, do you have to use this with Ajax operations?
Can it be used with Ajax operations?
If so, I guess Ajax would be the best way to achieve it.

Do you have to use this with Ajax operations?
No, absolutely not. You can use synchronous code with AJAX operations (and most of the time you probably will): the client (browser) request is still asynchronous even if a server thread is blocked in the background.
Can it be used with Ajax operations?
Yes, it can. When it's appropriate. Generally to allow long-running I/O operations to complete without blocking worker threads.
In your example, the Register method will be waiting for UserManager.CreateAsync to complete but - in the meantime - the thread executing this method is free to handle other requests.
Here's some good documentation.

Web code is almost always asyncronous out of the box. This is due to IIS hosting numerous threads in a pool, all listening for connections. As a result your code can run on multiple threads concurrently. async and await are a means of delegating work to a different thread pool and receiving the response when the work is done. It has nothing to do with the native-async ASP.NET pipeline, but can be used within the pipeline for additional performance gains. Reading this might help clear it up for you.

Related

Async Await control flow in Web API

webcontroller {
async Task<ActionResult<string>> doSomething() {
var stringResult = await doSomethingAsync();
return stringResult;
}
}
what will be control flow here? will the controller return dummy response (ActionResult) to client after reaching doSomething() method call or the control remain in the web controller and return the stringResult to client? consider doSomething() is doing some network intensive tasks which might take more time to complete. Can anyone please explain the same to me if possible? Thanks in Advance!
will the controller return dummy response (ActionResult) to client
after reaching doSomething() method call or the control remain in the web controller and return the stringResult to client
It will not return anything to the client until doSomething method finished.
consider doSomething() is doing some network intensive tasks which
might take more time to complete
In this case you will have timeout on the client.
You have to start background job. Return to the client that task has been started. Then tell somehow to the client that task is finished.
Another source of information: Long running task in WebAPI
I recommend reading an article I wrote about how async works on ASP.NET.
will the controller return dummy response (ActionResult) to client after reaching doSomething() method call or the control remain in the web controller and return the stringResult to client?
When doSomethingAsync returns an incomplete task, then the await in doSomething will also return an incomplete task. Then the ASP.NET runtime (asynchronously) waits for that task to complete before sending the response.
await in ASP.NET yields to the thread pool; it does not yield to the client.

await blocks the request

I have an action in my controller in which there is an async function call
public async Task<ActionResult> Subscribe(AspNetUser user, string newUploadPath)
{
//do some work
await DocServiceImpl.CopyUserAllModels(user, newUploadPath);
//do some work
return RedirectToAction("List", "ClientDashboard");
}
and this function uploads a lot of files to Azure CDN so it takes too long.
The problem is that the client who makes this request has to wait until the CopyUserAllModels function finishes, because all this waiting time the client sees his page is reloading in the browser.
I've tried not to wait at all and used without await
DocServiceImpl.CopyUserAllModels(user, newUploadPath);
but I've searched that this is a bad experience, and except it,
in this case I find that some part of the files haven't been uploaded at all, so
without await it does not work properly in my case(I couldn't understand why).
My problem is: How to finish the request earlier, and then after it do all the work in CopyUserAllModels function?

WebApi Controller - Send Mail Async

I have a WebApi Controller that one of the parts is sending emails to a set of users.
[HttpPost]
[Authorize]
[Route("{id}/Do")]
public async Task<HttpResponseMessage> Post(int id, Model model)
...
await _emailService.SendAsync(message);
...
Now the method that sends the emails (SendGrid)
public override async Task SendAsync(MailMessage message)
{
var client =
new SmtpClient(SendGridServerName, SendGridServerPort)
{
Port = SendGridServerPort,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false
};
var credentials = new NetworkCredential(SendGridUserName, SendGridPassword);
client.EnableSsl = true;
client.Credentials = credentials;
message.From = new MailAddress(FromAddress);
await client.SendMailAsync(message);
}
Everything works, but it's very slow. I was expecting it to be fast, but the await _emailService.SendAsync(message); does not appear to be async. It stops there for a while.
Any ideas?
Thanks
What async does is allowing your server to run other threads while your slow method is executed asynchronously. I.e., when you await for an async method, the server executes a different thread until the async method finishes execution, and then keep running the thread that called the async method. Async actions in a controller are treated exactly in the same way behind the scenes. So, the response from your async action to the browser will not happen until the async email sending has finished.
NOTE: for example, if there are connectivity problems to the email server, or the DNS resolution, you'll usually get a time out after 30 seconds, so your thread will be slept during 30 seconds, and only then will send the answer to the browser
If you want to return the response to your browser quickly, you need to implement a different idea, which is to start a new thread that sends the email, but don't wait for it to finish, so that your thread keeps running and inmediately returns the asnwer to the browser. That's known as fire and forget. To understand what I'm speaking about, please see this: Fire and forget approach. And then read this other carefully: Fire and Forget (Asynch) ASP.NET Method Call. Take into account that MVC itself is threaded and you need to have it into account when using the fire and forget approach.
Obvioulsy in fire and forget, the controller will not be able to detect errors during the email sending, beacause the new thread runs on its own while the main thread has already finished. So you have to implement something to at least log the possible error, and ideally let the user now what happened (for example which reports that he can see later on). Please, see this: ASP.NET Exception Handling in background threads

How to make an async call not prevent action from returning response to user

I have the following async code
public async static void SendAsync(string url)
{
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.KeepAlive = false;
request.Timeout = 5000;
var response = await request.GetResponseAsync().ConfigureAwait(false);
response.Close();
}
catch (Exception ex)
{
SendException(ex, url);
}
}
Which is called by the controller action.
public ActionResult Details(string id)
{
// DO something
SendAsync(some-valid-url);
// Do something
return View();
}
When i debug it - it runs async and hits
return View();
and exits before it is comes to
response.Close();
But in fiddler you can see that the http response is not sent by the browser and it waits for the SendAsync function to finish processing, which is not what i want. I want the http response to return back to the user right away.
What do I have to change here to achieve that?
i actually edited it and am now doing async static void since i do not
need to track the end of the task,
But you do need to keep track, as MVC will close the connection when Details returns, you need to tell MVC you are waiting for a background action.
public async Task<ActionResult> DetailsAsync(string id)
{
// DO something
var sendTask = SendAsync(some-valid-url);
// Do something else that does not depend on sendTask
await sendTask;
return View();
}
To answer your updated comment
doing an await will make it wait for the async http call to finish.
Which i do not want.
To get the behavior you are looking for you need to use AJAX, the async/await system will not give you what you want by itself. (I have never really done MVC with AJAX so I don't have a example for you how to do it)
doing an await will make it wait for the async http call to finish.
Which i do not want.
It sounds to me like you want fire and forget since you don't want to wait for the response.
There are a few negative points to bare in mind (such as no error handling, no guarantees, etc), so I would recommend reading into this a bit before dropping it into your project.
This is, in my opinion, is the easiest way to call a method with fire and forget.
ThreadPool.QueueUserWorkItem(o => SendAsync(some-valid-url));
This will request an available thread from the app pool. It will then use that thread to execute the method without blocking your current running one.
I hope this helps.

What is the benefit to using await with an async database call

I am just looking at the default MVC5 project and how it uses async in the controllers.
I would like to know what benefit async provides here over simply using synchronous calls:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Disassociate(string loginProvider, string providerKey)
{
ManageMessageId? message = null;
//why use an async database call here with await instead of just using a synchronous one?
IdentityResult result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey));
if (result.Succeeded)
{
message = ManageMessageId.RemoveLoginSuccess;
}
else
{
message = ManageMessageId.Error;
}
return RedirectToAction("Manage", new { Message = message });
}
What am I missing?
Does this provide some kind of performance benefit in the type of wait that will occur here?
On the server side (e.g., ASP.NET MVC), any I/O you do (e.g., databases) should be done asynchronously. This frees up the request thread for the time that the I/O is in flight.
So, when the RemoveLoginAsync sends its SQL to the database, it returns an incomplete task, and when the request hits the await, it returns the request thread to the thread pool. Later, when the DB operation completes, a request thread is taken from the thread pool and used to continue the request.
The end result is scalability, because (in the 99.9% case at least) tasks scale better than threads. However, there isn't a big advantage if your database is just a single server and all requests hit the db, because your scalability bottleneck in that scenario is the db server, not the web server.

Categories