How can an HTTP request continue after cancellation? - c#

I use .NET 6.0 for an API.
When the user goes to a different page on our (react) webapp it automatically cancels the ongoing HTTP requests. What I see on my end (.NET API) is a System.OperationCanceledException and then the processing completely stops.
This is annoying because if the user creates an item on the webapp but switches to another page before the API got time to save the data to our database we get problems.
I tried to reproduce this locally but after I cancel the request in postman I can see the exception in the console but the execution seems to continue. The debugger does hit breakpoints after the request was cancelled.
Why is the behavior different? And how can I change this into a "fire and forget" request?
I did some research online but I could only find people asking about cancelling things instead of NOT cancelling things.
I'm not even sure "fire and forget" is the right term, since we don need a response if the user stays on the same page.
And we looked into changing this on the frontend side, but this doesn't really matter since the user can simply close their browser.

You absolutely can create a fire-and-forget function (It already is) , however not waiting for the response comes with a few problems:
1: Any error that happens to that fire and forget call, is basically lost to you, if you for example attempt to log the error to a persistence layer, and said layer fails, you can't tell the user that the error happened.
2: If the user is able to lose a request by leaving the page, why not just warn the user that they are about to leave an active process that hasn't finished yet, and will cancel it, instead?
This at least imitates what is actually happening.
Implement a cancellation token for an async call.
3: If you ever wish to actually tell the user that the request is done, that won't really be an option, you would have to create a page, where the user can go back to.
Lets say you put the request into a queue (like rabbitmq or kafka) then the user would have to go to a page with a UI that can show processes being processed by this queue system, or whatever system you choose to use.
How do you make a user aware that this is even an option?
The fire and forget solution will be very user un-friendly.

Related

How to do a specific proccess per in month in asp.net mvc?

I am trying to write a website and now I need to do a specific method one per month(at the end of the every month).
Imagine that the method is Method A().
I want to run it at the end of the every month.
So now how to run it ?
UPDATE:
The mission of the website is something else.Just in a part of it I need to do this.
I dont know but I guess maybe running the method in application start at the end of the every month can solve it but I am not sure that its the way or not.
ASP.NET MVC is for writing web applications, not scheduled tasks.
Web applications are architected as request/response systems. They are not suited for background tasks which need to happen at regular intervals. They receive a request, respond to that request, and are done. While idle a web application is subject to the web server's resource management, which could include shutting it down entirely while waiting for the next request.
Instead, what you'll want to use is either a Windows Service or a Console Application (invoked by a task scheduler, such as the one that comes with Windows). This would run continuously in the background or at regular intervals, respectively. This application can be very small, just calling that one method and nothing else.
In short... If you want to run the code in response to a user request then a web application will do the job. If you want to run the code at regular intervals regardless of user requests then a scheduled task is what you want.
Well, that seems like something that doesn't belong on the web site. i.e. it shouldn't be run within ASP.NET anywhere. Maybe it should be run in a back office, or a service that's running on the back end or a database job or a scheduled task. But if all you have is the one job, it would probably be easier to have a button that when pushed calls the method A(), and have it in a logged in portion of the website with some sort rights check to ensure no one but the correct people press it. And you could also put checks, within the method to ensure it's only run once a month. If you can be sure that the rest of the website is being used, you could put in other methods a CheckToSeeIfIShouldCallMethodA method, but all of these seem like worse options than something that runs on the back end.

The connection was reset ASP.NET

I have some code that pulls data from SQL DB, then loops through the records to generate a string, which will eventually be written to a text file.
The code runs fine on my local, from VS, but on the live server, after about a minute and half, I get "No Data Received" error (chrome). The code stops in middle of looping through the DataTable. Hosting support said "The connection was reset" error was thrown.
I"m not sure if this is a timeout issue or what. I've set the executionTimeout in my web.config (with debug = false) and it didn't seem to help. I also checked the Server.ScriptTimeout property, and it does match the executionTimeout value set in the web.config.
Additionally, a timeout would normally give "Page not available" message.
Any suggestions are appreciated.
after about a minute and half
There's your problem. This is a web application? A minute and a half is a very long time for a web application to respond to a request. Long enough that it's not really worth engaging in various trickery to make it kind of sort of work.
You'll want to offload this process to be more asynchronous with the web application itself. The nature of web applications is that they should receive a request and respond in a timely manner. What you have here is a long-running process which can't respond in a timely manner. The web application can facilitate interactions with the data, but shouldn't directly handle the processing thereof in the request/response directly.
How does the web application interact with the process? Does it just start it, or does it provide information for the process to begin? I would recommend that the process itself be handled by something like a Windows Service or perhaps a Console Application. The more de-coupled from the web application, the better. Now, since I don't know anything about the process itself, I'm making a few assumptions about its behavior...
The web application can receive a request to start the process, along with any information needed for the process. It can store this in a database with a status value (pending, queued, etc.) and then respond to the user (in a timely manner) that the request has been received and the process has been queued. The web application can have a page which checks the status so that the user can see how the process is doing (if it's started, how many records it's gone through, etc.).
The offline application (Windows Service, et al) would just monitor that database for newly-queued data to be processed. When it sees it, it updates the status (running, processing, etc.) and provides any relevant feedback during the process (number of records processed, etc.) by updating that data. So the offline application and the web application are both interacting with the same data, but not in a manner which blocks the thread of the web application and prevents a response to the user.
When the process is finished, the status is again updated. The web application can show that it's finished and provide a link to download the results. The offline process could even perhaps send an email to the user when it's done, or maybe the web application can have some kind of notification system (I'm picturing the little notification icons in Facebook) which would alert the user to new activity.
This way the thread isn't blocked, the user can continue to interact with the application (if there's even anything with which to interact), etc. And you get other added benefits, too. For example, results of the process are thus saved in the database and automatically historically tracked.
It sounds like it's the browser that's timing out waiting for a response, not on the server. You can't control what the browser has set for this. What you can do is send a response of some kind to the browser, so that it knows you're still around and haven't crashed in some way.
For this to work, you can't wait until you finish building the entire string. You need to re-think your code so that instead of appending to a string, you are writing each addition to an output stream. This has the added advantage of being a much more efficient way to create your text file. For purposes keeping the browser alive, you can write out anything, as long as some data is coming back for the browser to read. Html comments can work for this. You also need to periodically flush your response stream, so that your data isn't sitting buffered on your web server. Otherwise you might still timeout.
Of course, the real solution here is to re-think your design, such that your operation doesn't take 90 seconds plus in the first place. But until you can do that, hopefully this is helpful.
it does sound like a timeout, Could you try and return the information via a View, this would certainly speed things up.(if possible).
When i had this error, i was able to resolve it by adding in the Web.config file:
<system.web>
<httpRuntime executionTimeout="600" maxRequestLength="51200" />
</system.web>

ASP.NET: How to prevent opening same site a few times in parallel?

I'm a newbie in ASP and I've encountered worst developer nightmare: I've received fired worker huge ASP.NET project and I must make some changes on it. One of the changes is to prevent opening same site few times on one Active Directory login (different tabs, browsers, etc...)
As I've noticed that app is using session. Any ideas to use session to prevent multiple instances of the same site?
Here is an idea. Use a hidden field with GUID which would be randomly generated by server for each page load. When a request comes to the server it checks if GUID coming is what was generated last time. If it is different or empty (while session is alive) - redirect to some page saying access denied (no new GUID here). If it is correct, serve requested page. Small problem with this would be that if someone closes browser and reopens it he/she would get access denied when trying to use your app again. To minimize that you need to lower session timeout to 1 minute and use AJAX asp:Timer to keep session alive. Remember to exclude keep alive calls (and any other AJAX calls) out of GUID generation/verification pipeline. Of course end of session resets the process. Also it would be good to encourage users to properly log out.
This is relatively simple solution to implement although it is weaker in level of protection than permanent connection. Should be enough for non-technical end users though - depends on your "audience". But even for someone who knows about the mechanism, it would make using two "instances" of application quite difficult.
Do it if you really need to. Generally I agree with Marc that web apps should not be restricted this way. Maybe it is a requirement from someone who can be educated?
You just need to create a persistent connection from each page. If browser navigates from one page to another on a single tab then you'll have a single persistent connection at all times. If you get two parallel persistent connections from same user then the user opened a new tab.
In the master page footer add a script that does an ajax call to the server on a page that doesn't end its response (Like long polling). If another ajax call comes from same user while the last one is connected then this is a second tab.
You might want to checkout SignalR for persistent connection thing. It should be able to switch between web sockets or long polling based on browser capabilities.
You cannot prevent the url from being loaded in multiple browsers or tabs at one time, since this is a client-initiated process.
You could implement a persistent connnection (as suggested by Hasan Khan) to ensure that only one browser window can be active at a time. I would add on to that that when a new window is opened up, you could warn the user that they already have an open connection. If they choose to use the new connection, then you send a message down to the old connection (different browser, tab, etc) that will cause it to clear the browser window for that user.

Creating separate process from web application request

A client came to me with a request to have a web app that does a lot of processing in the backend (reads from a file, writes to a web service). My question is that since this "process" (when the user clicks 'Go') may take hours, how do I make it so the processing continues after the user closes the web page? Please let me know if this does not make any sense and I can give more information. Any help would be greatly appreciated, thanks!
You have to create MS Windows Service for it.
You have provide for that Service some database table which client is going to use by your Website functionality.
This is, basically, a "batch job" requirement, and that's how I suggest that you approach it.
The client would use the web-page, not to perform the work, but rather to manage the list of batch jobs that are performing the work .. scheduling them, starting or stopping them, viewing their status and current output, and so on. (Yup, just like they did it in the 1970's, but without "//FOOBAR JOB (123,456)" ... thank god.
The user goes to the web-page and enters a request. A back-end service process on the host (the batch job manager...) now starts the job, perhaps on one computer; perhaps on several at a time. The user can, meanwhile, log off the web-site and do whatever he pleases. Then, he can come back at any time, go back to whatever the job-monitoring web page may be, and see how things are going. Stop the job, suspend/resume, what have you.
There are lots of batch-job monitoring tools out there already, for all sorts of environments, both free and commercial. So, it's not like you have to build all this stuff; you merely have to identify what off-the-shelf package works best for you and for your client.
The best possible solution will be to do the work in a windows service, and use your web app just to trigger the processing.

Long running operation on website

What if I have website with a button. User clicks on the button and starts a long running process. After a few hours (or minutes) user update webpage and see results. What is the best (and any other) way to implement long running operation on website?
From the user experience point of view I suggest you implement the job like you would implement order handling in an online shop.
When the user starts the job he should be able to track the state of the job. Is the job complete? Did the job fail? What is the progress of the job? He should probably also be able to cancel the job and perhaps modify properties of the job. You could implement an notification mechanism using e-mail or an SMS and the user should be able to control that.
By using JavaScript/AJAX you can provide a more interactive user experience where the job status web page is automatically refreshed at regular intervals in the background without forcing the user to refresh his browser.
The user should be able to leave his computer and later connect to the website from another computer and still be able to get information about pending and completed jobs. This requires some form of user login.
I suggest that you separate the job handling code from the website code. You could expose the job handling user a web service or another similar technology. The website should query the service and display the results providing a user interface on top of the job service.
How long? If it's really going to take hours, you don't want that code running in the web server. Have the server spawn an external process or start a service or something along that line, and put the long running code in there.
You could have that code put status updates somewhere (like in the database) as it runs, and the website can check that when the user comes back to see how it's doing.
I suggest you read up on Threading in asp.Net. For website performance, time consuming processes can be put on a different thread.
A different approach is executing the task with AJAX. This way, you can present the user interface to the user, and start an asynchronous process which handles the request.

Categories

Resources