1

I have an ASP.NET WebForm application - a main page that hosts a bunch of IFRAME "widgets". When main page loads - the widgets' pages load as well and begin their own processing, which include connecting to SQL Server to run stored procedures.

What would be the best way to cancel those IFRAME processing should user need to do so? I could probably set their SRC to another/blank page from client-side thus canceling the request, but if the IFRAME pages already called SQL Server - how do I cancel the SQL processing as well?

EDIT: To clarify the slowest point in the IFRAMEd page is the SQL Server stored procedure call, so essentially this boils down to - can I initiate cancellation of the SQL command from client?

Yuriy Galanter
  • 38,833
  • 15
  • 69
  • 136
  • 1
    @Yurjy setting up the SRC may cancel the loading of Page in IFRAME, but it probably will NOT stop the thread currently running on Web Server. Which means query will run fully on server, then response will be discarded later. This is my assumption I am NOT very sure. I would suggest to look into asynchronous programming in ASP.net. as well. – sallushan Apr 07 '15 at 09:16
  • Weird thing - setting SRC does change the page, but only temporarily, when long-running one finishes processing - it appears in the iframe again.. – Yuriy Galanter Apr 07 '15 at 18:19
  • @sallushan - "probably"? definitely will not. – Igor Apr 08 '15 at 13:04
  • @YuriyGalanter - consider `SqlCommand.CommandTimeout` and `SqlCommand.Cancel`. To use the latter, you, of course, need to be able to get at the command instance from another thread which requires additional infrastructure to be designed/built. Plus, there is the problem of ASP.NET serializing same-session requests - if they are not marked session-readonly. – Igor Apr 08 '15 at 13:14
  • @Igor thanks for the suggestions. I cannot rely on `SqlCommand.CommandTimeout` because if user doesn't cancel the request and is willing to wait - the command must run thru. I was looking into `SqlCommand.Cancel` - but like you said, requests are serialized, but are you saying this can be bypassed marking session read-only? – Yuriy Galanter Apr 08 '15 at 13:21
  • 1
    @YuriyGalanter - yes, http://stackoverflow.com/questions/4506273/make-session-readonly-on-asp-net-programmatically-enablesessionstate-readonly - this should let same-session requests for such pages run in parallel – Igor Apr 08 '15 at 13:24
  • new tecnhiques without using iframes ? HTML5 supports iframe? – Kiquenet Dec 29 '18 at 21:48

1 Answers1

2

One solution that came up in my mind is to have a static List of currently Running SqlCommands, whenever user invokes cancel you can extract the Command from this static list, and then cancel it. The page that is executing the command will receive the command cancel exception, it then can handle it appropriately.

Here are the things that you need to handle:

  1. Somehow user interface should have some key, so that when you press the cancel button, user interface will then send that key to the cancel routine, and cancel routine will extract the SqlCommand using that key and call its Cancel method.
  2. Cancellation calls should be done through AJAX
  3. Proper locking should be done for thread-safety

Update:

I am adding some details here,

  1. Here is the link of Project http://goo.gl/noKUmj
  2. Above project is a Web Form Application
  3. You may add as many controllers as you want in this project, the routing code has already been added in Global.ascx, so new controllers should work
  4. But for new IFRAME cancellation you don't have to add another controller. You just need to pass the PageName (as key) to the Cancel Controller
  5. LIMITATION: This project has limitation that if you hit cancel button for an IFRAME, it is going to cancel all the current requests, which means in a multi-user environment, if one user cancels the IFRAME-1, all IFRAME-1 are going to be cancelled for every other user.
  6. You can cancel multiple IFRAMEs easily, as you can see the cancel button code it is executing a JavaScript code, you just need to call multiple Cancellation Codes in 1 click.

As you may have already seen the project, it is using PageName as Key to extract the SqlCommand from List. Due to this we have the limitation as I have mentioned above. Since PageName will be same for multiple SqlCommands.

To overcome this limitation, you can generate a GUID as Key and pass this GUID in QueryString to Form1.aspx and Form2.aspx pages, so that they add the command in List using these GUIDs. These keys should be generated at the time of host page rendering or in JavaScript.

If you don't want to do the RnD, here is the updated project which uses GUID as Key. :) http://goo.gl/I86S7Z

sallushan
  • 1,134
  • 8
  • 16
  • The problem with this approach is I won't be able to make AJAX call if current HTTP request is being processed - AJAX call will have to wait till it completes – Yuriy Galanter Apr 09 '15 at 15:23
  • @YuriyGalanter, are you putting the Cancel button on the same page which is shown in IFRAME? I guess no, probably your cancel button is on the host page, then you should create a separate Handler / Controller which will be called by the Cancel button using AJAX, in this way a separate HTTP request will be generated. I have test project, do you want me to upload on Google Drive and share link? – sallushan Apr 09 '15 at 18:23
  • Sorry for delayed response only now got to look into the demo, looks very cool. If I understood it correctly - every time a command is created - it is added to static list of commands (and removed from it upon successfull execution). If user hits Cancel button - an AJAX call to API controller is made which cancels the command. Does it mean I can easily just add a controller code to an existing WebForm app without advanced config (routes etc.) and it will work? Also how would this work in multiuser environment? And will it be possible to cancel multiple iframes at once? Thanks! – Yuriy Galanter Apr 13 '15 at 14:01
  • Thanks for the updated info, I also figured that GUID was the way to go and am trying it now :) I will play around with the solution in my own project and most likely will accept the answer later today. My only concern remaining is - if there're more than 2 iframes are opening and all HTTP requests are serialized - "later" iframes may still be waiting to be processed (i.e. they didn't even begin to execute SQL command and just waiting their turn) - what do do in this case. But I will think of somehting. Your project has been a great help and boost to my own efforts – Yuriy Galanter Apr 13 '15 at 16:25
  • I don't think HTTP requests are serialized, they are processed simultaneously, which means if you have 2 IFRAMEs on 1 page and you open that page in your PC, both IFRAMEs will load simultaneously. If 2 users open this page together, then you'll have 4 HTTP requests running simultaneously on the server. – sallushan Apr 13 '15 at 16:41
  • When I tried the same in my Webform project I am getting *Could not load file or assembly 'AttributeRouting.Web' or one of its dependencies. The system cannot find the file specified.* when making that AJAX POST call. I have added the controller class and initialized routing as your sample and the project compiles and runs sucessfully and only during AJAX call I am getting this error. I think I added all needed references, what am I missing? – Yuriy Galanter Apr 13 '15 at 17:31
  • Actually never mind that (sorry) the previous error happen because I actually had folder called "api" in my IIS root. Now it's removed but I am getting *"Error 404.0 - Not Found. Requested URL http://server/api/CancelLoading. Physical Path C:\\inetpub\\ServerPath\\api\\CancelLoading"*. I've added route initialization to `global.asa` - why is it looking for physical path? – Yuriy Galanter Apr 13 '15 at 17:56
  • Ok never mind that too, figured it out :) Sorry for being such a noob, but Web API is really new to me. Now it is working exactly as you've described so I am accepting the answer. But the iframes do load sequentially - *after a certain threshold* so perhaps 2 can load at the same time, but 3rd or 4th will have to wait. So when "Cancel" button for that form is clicked - at that time SQL command isn't even begin to execute. But I will figure something out, thanks for your help! – Yuriy Galanter Apr 13 '15 at 18:07
  • After looking into your multiple IFRAME loading issue, it seems browser is following RFC2616 standards, which states that a browser should only do 2 simultaneous connection per domain. http://blogs.msdn.com/b/ie/archive/2005/04/11/407189.aspx – sallushan Apr 13 '15 at 19:26
  • Yup. That's what it is. But there should be a workaround, e.g. have a function that does that in sequence: as soon as one IFRAME is canceled, issue command for the next. Your solution still applies here – Yuriy Galanter Apr 13 '15 at 19:30
  • 1
    Made a blog post out of your solution. For myself to remember and perhaps others find it useful. For posterity :) http://codecorner.galanter.net/2015/04/14/cancel-long-running-sql-command-in-asp-net-webform-application/ – Yuriy Galanter Apr 14 '15 at 20:04
  • The only change I did in my project is `RemoveCommand(String pageName)` i.e. passing string key here as well. Any particular reason you passed `sqlCommand` as a parameter here? – Yuriy Galanter Apr 15 '15 at 17:07
  • In ver 1, I didn't use the `GUID` as Key, therefore on successful command execution, if I remove by `pageName`, it would remove all other the commands as well, which would not be acceptable. That is why page always removes the `SqlCommand` object through instance, so that other instances should remain as is. – sallushan Apr 16 '15 at 07:55
  • Ah yes makes sense. But turned out in my case command could change during lifetime of the page (different queries can be assigned to it, so essentially it was becoming a different command) but using GUID for the key worked nicely – Yuriy Galanter Apr 16 '15 at 13:30
  • ***only do 2 simultaneous connection per domain*** for IE,Chrome,Firexof ? only 2 Ajax simultaneous request ? – Kiquenet Dec 30 '18 at 08:34