Execute Javascript after postback with cleared response in C# - javascript

When a user clicks a button on my website I make an excel file on server-side and write it in the response.
HttpResponse httpResponse = Page.Response;
httpResponse.ClearHeaders();
httpResponse.ClearContent();
httpResponse.Clear();
httpResponse.Buffer = true;
httpResponse.AppendHeader("Content-Disposition",
"attachment; " +
"filename=\"" + fileName + "\";");
httpResponse.ContentType = "application/vnd.xlsx";
httpResponse.Charset = "";
using (MemoryStream memoryStream = new MemoryStream())
{
workbook.SaveAs(memoryStream);
memoryStream.WriteTo(httpResponse.OutputStream);
memoryStream.Close();
}
httpResponse.Flush();
httpResponse.End();
When I'm done writing this file, I would like a JavaScript script block to run, but I can't seem to make this work. I have heard that when I clear the response, I can't write a script block with the Page.ClientScript.RegisterStartupScript (deprecated?), since the user doesn't get the same page as the response, but I am hoping there's a workaround.
The button that makes the postback and fetches the file is not in an UpdatePanel, so I am unable to use the PageRequestManager.add_endRequest function that is implemented there. And I can't put the control into an UpdatePanel, since it won't allow me to write a file in an async postback.
Is there any other way to trigger a javascript function at the end of a postback? A JavaScript interval function that checks if a postback is in progress (or finished) is also an acceptable solution as well (but as far as I know, there is no way for JavaScript to "check" if a synchronous postback is in progress).

The Response.End() aborts the thread and sends the execution to Application_EndRequest.
Nothing can be done after that. You can either download the file or execute the javascript. But there is this solution using iframes.

Related

How to properly use ExecuteASyncScript in VBA Selenium?

I have the below piece of JavaScript script. I'm using VBA for Excel (with Selenium) and what I want is to wait for the server response in the website before the macro in VBA goes to the next line. For that, I'm using MyVbaVar = ChromeDriver.ExecuteAsyncScript(script), where "script" is the code below.
From what I've read, I must indicate a callback somewhere in the script so that Selenium knows when to stop executing the script. However, I have no idea how to do that. I tried many ways, without success, and searched everywhere, but all solutions for this type of problem are in posts about Selenium for Python or JavaScript.
Any help here (even just pointing out how to correctly use the ExecuteAsyncScript with a simple example) would be much appreciated!
PS: I have tried this code with just ExecuteScript, but the macro goes to the next line without waiting for the website response, as expected.
* some variable declarations here
functionThatAwaitsResponseFromServer(){
if(response){
response_var = response;
}else{
setTimeOut(functionThatAwaitsResponseFromServer, 1000); //run function again if no response
};
return response;
};
functionThatRequestsSomethingToTheServer(){
requestFromServer();
myFinalResult = functionThatAwaitsResponseFromServer();
return myFinalResult
};
return functionThatRequestsSomethingToTheServer();

call JavaScript function from a php script

I'm wondering if this is something I can do. I have a PHP script that needs to call a function that I define in my main index.php.
Inside my other PHP file I have:
echo "<script>ShowModal('PopUpNameItem','closeNameItem');</script>";
and inside my main index.php I have that function. how do I actually call this from a seperate script? Normally you would use something like this but since my files are .php can I do this?
<script type="text/javascript" src="ajax.js"></script>
and this is the function I'm trying to call
function ShowModal(popup, closeBtn) {
var modal = document.getElementById(popup);
var span = document.getElementsByClassName(closeBtn)[0];
modal.style.display = "block";
span.onclick = function() {
modal.style.display = "none";
}
if (modal != "PopUpNameItem") {
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
}
}
Ok. I think can see the clear picture now.
No. it is not possible. You can not can not call client-side javascript method from server-side PHP script.
In web application there are to sides:
client (in your case its web browser, that works with html/css and javascript + data received from the server)
server side that works with whatever (in your case its PHP) and generates the html/css, javascript and data.
Now, your index.php on the server side is processed by the web server and produces index.html that is being sent by the server to the client. Client opens this file and loads/executes all the scripts,styles that are defined in it. And it creates document structure. All of it is now existing on the client side.
However, server side does not have a direct link to your client context. So the are two ways to run this method as a result of the server processing.
1) to send a ajax request to the server, and, based on the result, execute the method.
2) If you don't want to deal with ajax cal logic, you may do a script insertion approach. How it works, is that when the button is pressed you do something like this:
var scriptRef = document.createElement('script');
scriptRef.setAttribute('src','url_to_script.php');
document.head.appendChild(scriptRef);
What it will do, it will dynamically append a script tag to your document and load script content as a result of your php script output. There you can decide to launch the method or do something else.
However, script insertion is a bit of a headache and should not be used on a long-running pages (in my opinion), as it actually adds a new script every time you press a button. And its your responsibility to keep track of it and remove it.
As long as you display your functions correctly in JavaScript format
You can just call:
<script type="text/javascript" src="ajax.php"></script>

How to make JS wait until protocol execution finished

I have a custom URL protocol handler cgit:[...]
It launches up a background process which configures some stuff on the local machine. The protocol works fine, i'm launching it from JavaScript (currently using document.location = 'cgit:[...]'), but i actually want JavaScript to wait until the associated program exits.
So basically the steps i want JavaScript to do:
JavaScript does something
JavaScript launches cgit:[...]
Javascript waits until cgit:[...] exits
JavaScript does something else
Code:
function launchCgit(params)
{
showProgressBar();
document.location="cgit:"+params;
document.addEventListener( /* CGit-Program exited event */, hideProgressBar );
}
or:
function launchCgit(params)
{
showProgressBar();
// setLocationAndWait("cgit:"+params);
hideProgressBar();
}
Any ideas if this is possible?
Since this isn't really an expected use of window.location I would doubt that there's an easy way. My recommendation would be to use an AJAX request and have the c++ program send a response when it's done. That way, whatever code needs to run after the c++ program can be run when the request completes.
As i didn't find a suitable way to solve my problem using ajax requests or anything similar, i finally solved my problem using a kind-of-ugly workarround including XmlHttpRequest
For launching the protocol i'm still using document.location=cgit:[...]
I'm using a server side system including "lock-files" - that's like generic dummy files, with generated names for each request.
Once the user requests to open the custom protocol, such a file is being generated on the server specifically for that one protocol-opening-request.
I created a folder called "$locks" on the server where these files are being placed in. Once the protocol-associated program exits, the appropriate file is being deleted.
The website continuously checks if the file for a request still exists using XmlHttpRequest and fires a callback if it doesn't (example timout between tests: 1 sec).
The structure of the new files is the following:
lockThisRequest.php: It creates a file in the $locks directory based on the req url-parameter.
unlockThisRequest.php: It deletes a file in the $locks directory; again based on the req url-parameter.
The JavaScript part of it goes:
function launchCgit(params,callback)
{
var lock = /* Generate valid filename from params variable */;
// "Lock" that Request (means: telling the server that a request with this ID is now in use)
var locker = new XmlHttpRequest();
locker.open('GET', 'lockThisRequest.php?req='+lock, true)
locker.send(null);
function retry()
{
// Test if the lock-file still exists on the server
var req = new XmlHttpRequest();
req.open('GET', '$locks/'+lock, true);
req.onReadyStateChanged=function()
{
if (req.readyState == 4)
{
if (req.status == 200)
{
// lock-file exists -> cgit has not exited yet
window.setTimeout(retry,1000);
}
else if (req.status == 404)
{
// lock-file not found -> request has been proceeded
callback();
}
}
}
req.send(null);
}
document.location = 'cgit:'+params; // execute custom protocol
retry(); // initialize lockfileCheck-loop
}
Ussage is:
launchCgit("doThisAndThat",function()
{
alert("ThisAndThat finished.");
});
the lockThisRequest.php-file:
<?php
file_put_contents("$locks/".$_GET["req"],""); // Create lock file
?>
and unlockThisRequest.php:
<?php
unlink("../\$locks/".$_GET["req"]); // Delete lock file
?>
The local program / script executed by the protocol can simply call something like:
#!/bin/bash
curl "http://servername/unlockThisRequest.php?req=$1"
after it finished.
As i just said this works, but it's anything else than nice (congratulations if you kept track of those instructions)
I'd rather prefered a more simple way and (important) this also may cause security issues with the lockThisRequest.php and unlockThisRequest.php files!
I'm fine with this solution, because i'm only using it on a password protected private page. But if you plan to use it on a public or non protected page, you may want to add some security to the php files.
Anyways, the solution works for me now, but if anyone finds a better way to do it - for example by using ajax requests - he/she would be very welcome to add that way to the respective stackoverflow-documentation or the like and post a link to it on this thread. I'd still be interested in alternative solutions :)

MVC call Javascript from razor #Helper at unpredictable times

In my MVC view I need to get razor c# code to execute a javascript function at unpredictable times, way after the page has loaded.
I have used a thread to simulate unpredictableness but ultimately instead of the thread it will be a WCF callback method that raises an event which runs the helper, but to eliminate session issues I have used the thread.
Javascript to execute:
<script type="text/javascript">
function DisplayNews(news) {
alert(news);
}
</script>
Helper that runs the javascript (because sticking this directly in the below thread didn't work)
#helper UpdateNews(string news)
{
<script>
DisplayNews(news);
</script>
}
Thread that simulates unpredictableness/post page loading or non user invoked events
#{
System.Threading.Thread T = new System.Threading.Thread(new System.Threading.ThreadStart(delegate
{
while (true)
{
System.Threading.Thread.Sleep(5000);
UpdateNews("Some cool news");
}
}));
T.Start();
}
If I stick a break point at UpdateNews("Some cool news"); I can see that it gets hit every 5 seconds as it should, but thats as far as it gets, nothing else happens. I can't stick a break point in the helper or the Javascript so I can't see where it stops working after that.
Is this going to work at all or is there another way I should be approaching this?
Any help would be greatly appreciated.
In server side code you can call an client function...
Razor executed in server side and javascript is in client side.that mean when you get server response it's created by razor code in server side and now you can just use javascript in client side
I may be misunderstanding what you are trying to do but you can have javascript that will run on page load that will be wrapped in a set timeout with a random millisecond period.
Something like this:
<script>
window.onload = function() {
setTimeout(function() {}, 1000); // this will run 1 second after page load
}
</script>
simply randomize the number being passed as the second parameter to setTimeout and your javascript will run at a random time after the page loads.

Any way to gracefully enforce a timeout limit when loading a slow external file via javascript?

I'm using javascript to include some content served up from a php file on another server. However, this other service can sometimes get flaky and either take a long time to load or will not load at all.
Is there a way in JS to try to get the external data for x number of seconds before failing and displaying a "please try again" message?
<script type="text/javascript" src="htp://otherserver.com/myscript.php"></script>
Couple issues: you can use timeout thresholds with XMLHttpRequest (aka ajax), but then since it's on an otherserver.com you cannot use XMLHttpRequest (and support all A-grade browsers) due to the Same Origin Policy restriction.
If the script introduces any kind of global name (eg any variable name, function name, etc) You can try setTimeout to keep checking for it:
var TIMELIMIT = 5; // seconds until timeout
var start = new Date;
setTimeout(function() {
// check for something introduced by your external script.
// A variable, namespace or function name here is adequate:
var scriptIncluded = 'otherServerVariable' in window;
if(!scriptIncluded) {
if ((new Date - start) / 1000 >= TIMELIMIT) {
// timed out
alert("Please try again")
}
else {
// keep waiting...
setTimeout(arguments.callee, 100)
}
}
}, 100)
The problem as I see it is you cannot cancel the request for the script. Please someone correct me if I'm wrong but removing the <script> from the DOM will still leave the browser's request for the resource active. So although you can detect that the script is taking longer than x seconds to load, you can't cancel the request.
I think you may be out of luck.
The only way I can think of doing this is to create a proxy on another (PHP-enabled) server which will fetch the data for you, but will stop when a certain timeout limit has been reached (and it can just return an empty result).
This is purely, purely theoretical:
<script> tags can be dynamically inserted into the DOM, at which point the script will be fetched and processed. This dynamic script tag injection is how some achieve cross-domain "AJAX."
I would imagine you could declare a global variable var hasLoaded = false;. At the end of the script you are attempting to load you could set that variable to true hadLoaded=true;. After injecting the script tag into the DOM you could then kickoff a setTimeout() whose callback function checks to see if "hasLoaded" is set to true. If it isn't, you can assume the script has not yet loaded fully into the browser. If it has, you can assume it has loaded completely.
Again, this is theoretical, but if you test it be sure to report back, I'm very curious.
I think that the only way to do this is take the content of the file via ajax and then set a timer. If the request finishes before the timer you can evaluate the respons with eval(that's not the better solution anyway), otherwise you can stop the ajax request and write the error message.

Categories

Resources