asp.net 3 core api - use of async in console hosted - api

I've been going through the aspnet core 3 Rest API tutorial here (Code below)...
https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-3.1&tabs=visual-studio
I want to host this in a console app. My understanding is that this uses "Kestrel" as a web server.
Lets assume a request takes 10 seconds.
If two requests came in at the same time, what exactly would be different between two scenarios where one used Async Await Task , and one did not ( returned normal ActionResult) in my Console App?
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return todoItem;
}

If two requests came in at the same time, what exactly would be different between two scenarios where one used Async Await Task , and one did not ( returned normal ActionResult) in my Console App?
In my opinion,what you mean is the differences between async and sync method in asp.net core web api.
Synchronous means two or more operations are running in a same context (thread) so that one may block another.
If an API call is synchronous, it means that code execution will block (or wait) for the API call to return before continuing. This means that until a response is returned by the API, your application will not execute any further, which happens sequentially.
Making an API call synchronously can be beneficial, however, if there if code in your app that will only execute properly once the API response is received.
Asynchronous means two or more operations are running in different contexts (thread) so that they can run concurrently and do not block each other.
For more details,refer to
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/
Not much difference between ASP.NET Core sync and async controller actions
WebApi async vs sync
What's a sync and async method?

Related

Should async controlles always used in MVC for data access

ERP+Shopping cart ASP.NET MVC 4.8 application is planned to migrate to .NET 5 MVC Core application.
Entity Framework Core with NpgSql data provider is planned to use.
MVC 4.8 application does no use any async method.
There are async methods in .NET 5 for Data Accesss like ToListAsync(), ExecuteSqlInterpolatedAsync().
Samples of Core MVC Controllers return async tasks like
[HttpPost]
public async Task<IActionResult> LogOn(LogOnModel model, string returnUrl,
[FromServices] ShoppingCart shoppingcart
)
There will be 100 human users.
Application has also Web API providing json data over http. Shopping cart part allows anonynous access an is scanned by search engines.
Ngpsql has connation pooling support so multiple connections are added automatically.
Application is hosted in Debian Linux VPS server with 4 Cores using Apache.
VSP has 20 GB of RAM so lot of data is cached by Linux. However probably most of time is still consumed by reading data from Postgres database.
Most controllers read and write data to/from database.
Answer in
https://forums.asp.net/t/2136711.aspx?Should+I+always+prefer+async+actions+over+sync+actions+
recommends to use async methods for data access always.
Answer in
Always using Async in an ASP.NET MVC Controller
recommends not to use async always.
Conclusion from https://gokhansengun.com/asp-net-mvc-and-web-api-comparison-of-async-or-sync-actions/ states
However async actions do not come with zero cost, writing async code
requires more care, proficiency and it has its own challenges.
Application and Database in in same VPS server
Answer in
mvc should everything be async
states that async should not used if application and database are in same server.
Answer in
When should I use Async Controllers in ASP.NET MVC?
states
I'd say it's good to use it everywhere you're doing I/O.
but afterwards:
If you're talking about ASP.NET MVC with a single database backend,
then you're (almost certainly) not going to get any scalability
benefit from async. This is because IIS can handle far more concurrent
requests than a single instance of SQL server (or other classic RDBMS)
There two upgrade paths in my case:
Continue to use only sync methods. Don't waste resources on async. Existing tested MVC controllers code can used. Number of threads in kestrel is not limited. Assume in future .NET compiler creates async code by analyzing application and manual async will become obsolete.
Change MVC controllers signatures to
public async Task
Replace all EF data access calls with async calls. Assume this is solid .NET feature which remains. Re-factor code so that Visual Studio 2019 warnings will not appear after change. After my application is released this allows to optimize existing code without major re-write.
Which upgrade path should used in this case ?
Will changing everything to async introduce new bugs in code ?
Async is not mandatory for web applications. It is mostly mandatory for GUIs only.
Your application will continue to work. Async programming is great at handling scale of requests. But you said you have at most 100 users. If they were 100.000, your application would have suffered a lot.
And I can tell for sure that async programming does come with challenges, because for example there are issues with transactions if you don't handle it properly.
Of course threads come with a cost too. Async exists to avoid the 500KB of overhead that is required for every thread. This means that the machine(s) running the application might need to be scaled vertically. In this sense, async saves RAM.
The choice is yours. Since you are refactoring your app anyways, you could work on improving it to the next step and get it ready for bigger scale.
Otherwise your application will still work fine for 100 users.
[Edit] a pull request is worth 1000 words. In async context, the transaction should be initialized with TransactionScopeAsyncFlowOption.Enabled to avoid the exception descripted and in order to tell the transaction engine that the thread is participating an async flow. To keep it simply simple, async flows share the same thread, so application code (and transaction management is C# code) must not rely on thread-local information and has to clean up context every time the context is switched to another async flow asking for attention.
Conclusion: your first comment is correct. Async flows dramatically reduce RAM utilizations on concurrent requests.

How to make ASP.NET MVC Controller Methods Async

I'm launching multiple ajax calls to various MVC controllers to load different parts of my page. However it seems that when this gets to the controller only one runs at a time. I'm guessing this is because by default ASP.Net MVC controllers are synchronous? I've also tested loading a page on 2 browser tabs and the second tab always waits for the first.
To get round this I've attempted to make the controller methods in question asynchronous. I've done this by doing the following
Append Async to controller method name
Make the controller methods return async Task
Used the Task.Factory.StartNew method to do the body of work in the method in a separate thread.
For example the controller methods in question now look like this...
public async Task<JsonResult> GetUser(int userId)
{
var result = await Task.Factory.StartNew(() => Task.Run(() =>
{
return userService.GetUser(userId);
})).Result;
return new JsonResult()
{
Data = result,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
However it still seems to be synchronous. Am I missing something or going about this completely the wrong way? I've not really used the Task Library much so may be missing something big?
No, your assumptions are most likely wrong. Your problem is likely one (or both) of two problems.
First, most web browsers have request limits that only allow a certain number of request to the same server at a time.
Second, you are probably running into a limitation of the Session object that causes multiple requests that use session to be serialized, because Session is not, itself, multi-threaded.
See http://tech-journals.com/jonow/2011/10/22/the-downsides-of-asp-net-session-state
The short answer is that if you don't use session in your action method, simply add this to the method...
[SessionState(SessionStateBehavior.Disabled)]
public class AjaxTestController : Controller
{
//...As above
}
If you only need to read the session, then do this:
[SessionState(SessionStateBehavior.ReadOnly)]
public class AjaxTestController : Controller
{
//...As above
}
There's not much you can do about the browser limitations though, since different browsers have specific request limits. These can be changed with registry (or browser config) entries (usually), but you can't force your users to do that in most cases.
One of the important feature introduced in MVC 4.0 was of Asynchronous controllers which enables to write the asynchronous action methods. Asynchronous controller allows an operation to get performed without making the working thread idle.
When an asynchronous action is invoked, the following steps occur:
The Web server gets a thread from the thread pool (the worker thread) and schedules it to handle an incoming request. This worker thread initiates an asynchronous operation. The worker thread is returned to the thread pool to service another Web request. When the asynchronous operation is complete, it notifies ASP.NET. The Web server gets a worker thread from the thread pool (which might be a different thread from the thread that started the asynchronous operation) to process the remainder of the request, including rendering the response.
Converting Synchronous Action Methods to Asynchronous Action Methods
Following is the example of synchronous action method and the its asynchronous equivalent version.
Synchronous Controller:
public class TestController : Controller
{
public ActionResult Index()
{
return View();
}
}
Asynchronous variant of above operation:
public class TestController : AsyncController
{
public void IndexAsync()
{
return View();
}
public ActionResult IndexCompleted()
{
return View();
}
}
Steps:
Synchronous Controllers are the classes derived from the Controller
class to implement an AsyncController instead of deriving the
controller from Controller, derive it from AsyncController class.
Controllers that derive from AsyncController enable ASP.NET to
process asynchronous requests, and they can still service synchronous
action methods.
Corresponding to the synchronous action method in Synchronous
controller you need to create two methods for the action in
asynchronous controller.First method that initiates the asynchronous
process must have a name that consists of the action and the suffix
"Async". The other method that is invoked when the asynchronous
process finishes (the callback method) must have a name that consists
of the action and the suffix "Completed".
In the above sample example, the Index action has been turned into two methods in asynchronous controller: IndexAsync and IndexCompleted.
The IndexAsync method returns void while the IndexCompleted method returns an ActionResult instance. Although the action consists of two methods, it is accessed using the same URL as for a synchronous action method (for example, Controller/Index).
Note the following about asynchronous action methods:
If the action name is Sample, the framework will look for
SampleAsync and SampleCompleted methods.
View pages should be named Sample.aspx rather than SampleAsync.aspx
or SampleCompleted.aspx. (The action name is Sample, not
SampleAsync)
A controller cannot contain an asynchronous method named SampleAsync
and a synchronous method named Sample. If it does, an
AmbiguousMatchException exception is thrown because the SampleAsync
action method and the Sample action method have the same request
signature.
For more details click here : http://www.counsellingbyabhi.com/2014/05/asynchronous-controllers-in-aspnet-mvc.html
mvc controllers are async in nature, how did you determine it's synchronous? The only reason could only be some lock implemented within your userService.
You can try by making a couple of hundreds of ajax calls to your web services using jquery

WCF Asynch pattern - Really required?

I have created one WCF service which performs a lengthy operation asynchronously using Asynch pattern. I have referred to below link to implement BeginAddNumbers and EndAddNumbers methods in the ServiceContract.
http://aspalliance.com/1335_Asynchronous_Pattern_in_Windows_Communication_Foundation.5
Everything is working fine. But I dont understand why we require this approach?
Even though its asynchronous operation on server, client will still blocked and we
have to invoke this operation asynchornously on client as well.
So instead of implementing operation asynchronously on server it's always
better to invoke operation asynchronously on client side to have responsive UI.
Can anyone help me to understand concept of implementing asynchronous operation on server side? Any practical example where I need to play around AsyncPattern=true in conjunction with OperationContract ?
Adding client code. Client is implemented using WPF application
private void button1_Click(object sender, RoutedEventArgs e)
{
MathOperationClient c = new MathOperationClient();
Task t = new Task(new Action(() =>
{
///Even if AddNumbers is is implemented as asynchronous operation
///second call to AddNumbers get chance only after completing below
///call.
///Note: AddNumbers method takes 10 sec to execute
int nResult = c.AddNumbers(2, 3);
this.Dispatcher.BeginInvoke(new Action(()=>{
label1.Content = nResult.ToString();
})
, null);
}));
t.Start();
Task t1 = new Task(new Action(() =>
{
///Below method is invoked only after executing first call ( above call with parameters 2 and 3 )
///in other words below call is blocked for 10 seconds.
///So what is advantage of implementing asynchronous AddNumbers method on server side?
int result = c.AddNumbers(5,5);
this.Dispatcher.BeginInvoke(new Action(() =>
{
label2.Content = result.ToString();
})
, null);
}));
t1.Start();
}
Thanks, Hemant
this post has some information.
in general:
In case of WCF, the realproxy is of type System.ServiceModel.Channels.ServiceChannelProxy. This proxy implementation calls service method synchronously even if we call it using BeginInvoke.
WCF only issues asynchronous calls if the method that is called on a proxy begins with BeginXXX() and is decorated with [OperationContract(AsyncPattern=true)] attribute.
I like the idea to implement this server side; and clearly indicate this by naming the operation accordingly. After all, if a call is asynchronous in nature, why give the client the choice?
Another reason is scalability: doing it server-side decouples the request from the WCF dispatcher thread. This means that WCF threads will not be blocked.
See here for an example.
You could even decide to make it a one way call; and have the client poll at regular intervals; which is, in fact, my favorite approach.

Calling WCF in async manner from client makes the WCF service also act in async manner?

When a WCF service is called in an async manner from a client, then we know that the client app is NOT blocked.
But is the thread on the WCF side blocked while executing the async method call OR the WCF releases the thread it uses to initiate the method call ?
For example, if I call the 'Add' method in an async manner from an ASP.Net app, as in code below, will the service instance in back-end wait till method completes? The WCF uses an InstanceContext of PerCall.
CalculatorClient client = new CalculatorClient();
// AddAsync
double value1 = 100.00D;
double value2 = 15.99D;
client.AddCompleted += new EventHandler<AddCompletedEventArgs>(AddCallback);
client.AddAsync(value1, value2);
WCF support for asynchronous calls are strictly a client-side feature only.
In-fact the service has no way (and should not have) of telling the difference between two clients, one making a synchronous call and the other making an asynchronous call.
This is true regardless of whether the client is making a call via an async proxy, or directly via async invocation.
It is easy to show this is true with a thought experiment; ANY wcf service can be called asynchronously, and additionally this is REGARDLESS of the binding selected - therefore this must be solely a client-side facility.

How to Consume MVC 4 WebApi Service

I am new to Web Api world and I see a lot of potential for in the new MVC 4 Web Api. I have generated a WCF Web Service but was planning to get to know Web-APIs and their web service capabilities. Now, is MVC 4 Web-Api Service more as front end? I wrote a sample Service by following some examples online in MVC 4 Web Api but how do I consume the Service in just a basic console app? I have figured out the only way to consume it is by using HttpClient are there other ways? I am used to ASP.NET Web Service and WCF Web Service as where you reference it as a service in your references and then you are able to see all of its objects, properties to make appropriate calls.
What happens if web-api is requesting a object "Task" for post method as an example how am I able to fill an object "Task" and post it back to the web-api? As in WCF I am able to see that "Task" object and its properties because of WSDL so I am able to fill them and send it back to the service how is that done in web-api service?
The webservice would be used internally is it worth it to have an web-api service?
Thank you so much for helping clearing some question of what I have about web-api services.
---Edit as per Comment---
This screenshot shows a possible structure which you can approach. Of course, you can take a design that best suit your application.
So ControllerLib is a separate Class Library project which is brought into the main project as a Service Reference (which is not shown in the screenshot but should be inside the References folder of the SecondMVCApplication project). The two controller file (HomeController.cs and LocationController.cs is a controller file that implemented the Controller class, which is the same thing as a Controller file when you create a new MVC4 application using the template)
So for your question regarding if there is a SVC file. NO. In MVC 4, there is no such thing as a SVC file whether the application is one project or a combination of multiple project (unless I am mistaken). Inside the SecondMVCApplication, there is a file called RouteConfig.cs which holds the routing URL and as long as you add the Service Reference and there controller function exists. The code will run. Also the sample screenshot I showed also includes a WebApiConfig.cs file. You can use that file to do API stuff for mobile if you need. So, the regular RouteConfig.cs handles website request and the WebApiConfig.cs handles API request.
Good to Note: If you are using a Model project as a separate project (which I know you will as it is a M-V-C project...DUH!!). Make sure you put your connection string inside the web.config main project (in this case, the SecondMVCApplication). I remember I was stuck in this problem for 3 days (8 hours each) trying to fix this problem. Hope you don't run into it.
---End Edit---
The following answer to your question is mostly based on my knowledge and may or may not be true to all users.
Is MVC 4 Web-Api Service more as front end?
This depends on how you look at it. Typically, a Web-API service is more suited for creating back-end service to provide a data payload to different platforms, like mobile, desktop apps and so on. However, a MVC4 Internet Application will have front-end aspects in them, namely the Views, which end-users sees.
How do I consume the Service in just a basic console app?
AFAIK, there is two way to do this. One if to consume the APIs as a Service Reference. Another is to use HTTP operation (which I will mention in your question regarding the HTTP client and reserve this answer using the Service Reference method).
This depends on how your application is done. Like I said, if it is a website, your MVC pattern will not need to do anything, but the Models, Views and Controllers all are designed to work together without using any service.
Although, as I mentioned in the comments to the questions, if it is a big application then you will need to break them into different projects that will make the app modular and nimble. So you will end up creating different Service Library. If you go down the Service Library road, then you just make use of the Add Reference option to bring in your API/Projects/Whatever-you-call-it into the project. (For this, I normally put all project inside a single solution and let Visual Studio manage the build order as I am lazy to write up a build script).
Similarly, the same logic could be applied when consuming your web service in a console app.
I have figured out the only way to consume it is by using HttpClient are there other ways?
One way to consume web APIs is using HTTP. Are you aware of how to write http request headers and handle http response. If so, this is the second way I mentioned. You call the web service through it's URL and then get the data and do whatever work. If your answer to use http in console app is NO, then look at this post: Create HTTP post request and receive response using C# console application
What happens if web-api is requesting a object "Task" for post method as an example how am I able to fill an object "Task" and post it back to the web-api?
I think I indirectly answered this in your previous answer (assuming you are going to take the HTTP road). If not, then comment and I'll see if I can find some resource for you.
The webservice would be used internally is it worth it to have an web-api service?
I sort of answered this in the comment to the question. Ask if you need clarification.
Hope all this helps.
you can create your own Client Service class that will serve for every request.
public class ClientService
{
#region async helper methods
private static string m_mediaTypeHeaderValue= "application/json";
static HttpClient client = new HttpClient();
static HttpClient createHttpClientInstance()
{
return client ?? new HttpClient();
}
// SELECT
internal static async Task<T> Get<T>(string endpoint)
{
client= createHttpClientInstance();
var response = await client.GetAsync(endpoint);
string content = await response.Content.ReadAsStringAsync();
return await Task.Run(() => JsonConvert.DeserializeObject<T>(content));
}
// INSERT
static async Task<T> Post<T>(string endpoint, object data)
{
client = createHttpClientInstance();
var httpContent = new StringContent(JsonConvert.SerializeObject(data));
httpContent.Headers.ContentType = new MediaTypeHeaderValue(m_mediaTypeHeaderValue);
var response = await client.PostAsync(endpoint, httpContent);
string content = await response.Content.ReadAsStringAsync();
return await Task.Run(() => JsonConvert.DeserializeObject<T>(content));
}
// UPDATE
static async Task<T> Put<T>(string endpoint, object data)
{
client = createHttpClientInstance();
var httpContent = new StringContent(JsonConvert.SerializeObject(data));
httpContent.Headers.ContentType = new MediaTypeHeaderValue(m_mediaTypeHeaderValue);
var response = await client.PutAsync(endpoint, httpContent);
string content = await response.Content.ReadAsStringAsync();
return await Task.Run(() => JsonConvert.DeserializeObject<T>(content));
}
// DELETE
static async Task<T> Delete<T>(string endpoint)
{
client = createHttpClientInstance();
var response = await client.DeleteAsync(endpoint);
string content = await response.Content.ReadAsStringAsync();
return await Task.Run(() => JsonConvert.DeserializeObject<T>(content));
}
#endregion
}