AsyncTimeoutAttribute is not working with Controller Actions - asp.net

We tried to use the following code to increase request timeout for our backup process which runs on IIS and ASP.NET MVC:
[AsyncTimeout(79200000)]
public async Task<ActionResult> DailyBackup(Guid secret)
{
HttpContext.Server.ScriptTimeout = 22*3600;
await Backups.Create();
return null;
}
However, this didn't change the timeout and after a short period of time, ASP.NET MVC returns us an empty page and await Backups.Create() is continue to run separately in background.
What should we do in order to increase timeout for certain actions without changing our Web.Config file?

Related

ASP.NET Core Session loading per request, Authentication or seperate Middleware?

Our application has a extra piece of a Middleware which is called after UseAuthentication and UseAuthorization. It's reponsible to load user data from cache or database. The data is then stored in HttpContext.Items.
We however recently felt that this is a little out of place. We currently believe, it makes more sense to handle this in a custom authorization handler. Since the authorization handler is responsible for setting the HttpContext.User. Setting the session, is extremely close in functionality to setting the User. Our application actually doesn't use HttpContext.User, but our custom Session object to keep track of certain data.
Overall the documentation doesn't clearly specific when to use custom Middleware or custom Authentication handlers.
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/?view=aspnetcore-6.0
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-6.0
Nothing relevant is mentioned in the performance considerations either.(https://learn.microsoft.com/en-us/aspnet/core/performance/performance-best-practices?view=aspnetcore-6.0).
Are there limitations or considerations that should be considered when deciding to implement custom Middleware or Authentication handles in .net-core?
public async Task Invoke(HttpContext context, ISessionManager sessionManager, ILogger<VarioClientSessionMiddleware> logger)
{
var token = ParseToken(context.Request.Headers.Authorization);
try
{
var session = sessionManager.GetSession(token);
if (session != null)
{
context.SetSessionState(session);
}
}
catch (InvalidSessionIdException ex)
{
logger.LogDebug("...");
}
await _next.Invoke(context);
}

Why all my requests are blocked until async/await method executed

I have an asp.net mvc async method waiting for 10 second.
The problem is IIS Express (production IIS also) stops processing incoming requests until that async method finishes.
I thought await keyword frees current thread for new incoming request. But it seems that I missed something.
public async Task<ActionResult> AsyncMethod()
{
using (DeliveryPortalEntities context = new DeliveryPortalEntities())
{
await context.Database.ExecuteSqlCommandAsync("WAITFOR DELAY '00:00:10'");
}
return Json(new { status = "ok" });
}
Update! Can anyone explain why during this code execution IIS stops answer requests immediately.
public async Task<ActionResult> AsyncMethod()
{
await Task.Delay(10000).ConfigureAwait(false);
return new EmptyResult();
}
I thought await keyword frees current thread for new incoming request.
It does; the thread is free. However, the request is not complete. And if that request has a read/write lock on the session, then no other requests for that session can be processed until that lock is free.
To resolve this, you'll need to change your session usage. If you can go sessionless, that's best - it allows really good horizontal scalability. If not, try to go read-only. Long requests with a read-only session lock can run concurrently with other requests in that same session if they also only need a read-only session lock.

How to response percentage of file upload process in asp.net core 2.0

I want to response percentage of my total file upload process.
I use XmlHttpRequest to post upload file to server by async. But I have a problem getting the progress percentage from .net core controller.
This is my API method.
[HttpPost]
[DisableRequestSizeLimit]
public async Task<IActionResult> RegisterBlockedFile(IFormFile file, string text)
{
long size = file.Length;
string filePath = Path.GetTempFileName();
//Connect and Upload to DB Logic
//~~~~
//I always want to return real percentage of all processes.
return Ok(new { count = 1, size, filePath });
}
In my plan, client will upload the file and above server controller's method will connect and upload to db server. And if this all progresses are finish, then it can call 100% finished.
But this API method is always called after the file was already received. The client side's xml-http request always can know about just amount of its sent bytes. But it is not a real percentage.
All references and examples are just for client side's send bytes progress.
It there have any easy solution to solve this?

Get URL information in Startup

In an asp.net MVC 5 project I'm using a katana owin based middlewere to handle the authentication. Inside the Start.cs file I have the Startup class with the Configuration method.
Is there a way to get the full URL of the request inside the Configuration method? I need to get the last part of it to be stored in a cookie
public void Configuration(IAppBuilder app) {
app.UseCookieAuthentication(new CookieAuthenticationOptions { ... }
// something here to get the full URL
// other authentication code here
}
Startup runs outside of the request-cycle. In fact, it only runs once, and then multiple successive URLs can be serviced before it ever runs again (when AppPool recycles, server restarts, etc.)
Long and short, even if you could access the URL, it wouldn't do you any good because it would simply be the first random URL that was accessed, which may or may not be applicable to whatever you're trying to do here.

Asp.net MVC Is it safe to keep sensitive info in Session?

I have a basic Authentication system on my Asp.net MVC Website
[HttpPost]
public ActionResult Login(LoginViewModel model, string returnUrl)
{
WebSecurity.Login(model.UserName, model.Password, persistCookie: false)
return RedirectToAction("Index", "Home");
}
I also have a UserInfoViewModel class where i keep some user specific information, and i use it on different pages.
To avoid creating the UserInfoViewModel every time i need it, i want to save it in Session on Login method.
public ActionResult Login(LoginViewModel model, string returnUrl)
{
WebSecurity.Login(model.UserName, model.Password, persistCookie: false)
var userInfoViewModel = new UserInfoViewModel();
Session["userInfo"] = userInfoViewModel;
return RedirectToLocal(returnUrl);
}
Considering that i have sensitive information that i rely on inside UserInfoViewModel, like IsSuperuser, is it safe to keep that object in Session? Will it expire when the user login session expires as well?
SOLUTION
System.Security.Principal.IIdentity is exacly made for that. It saves inside AUTH cookie custom user information you need, so you don't recalculate it every time.
Use Custom Principal Objects video turorial
Thank you for answers!
Yes, it is safe because the Session is stored on the server. But you have another problem you should be thinking about if you decide to use ASP.NET Sessions. If this session is stored in the memory of the web server (default), IIS could recycle your application at any time and you will loose this session data. On the other hand the user will still be authenticated because he is tracked by a forms authentication cookie which will still be sent. So if you want to use Sessions I would recommend you switching to an out-of-proc session provider (such as StateServer or SQLServer).
Also as #Mikeb is pointing out in the comments section there's another very serious issue with the Session. If you enabled it for read and write mode for a given controller you will not be able to process multiple requests from the same session in parallel. The server will block and process them sequentially. Think for example multiple AJAX requests from the same session. They will all block and process sequentially.

Resources