Execute javascript after loading generic handler asp.net - javascript

I have a gridview with a list of pdf files. When the user clicks a pdf, it displays the file inline on the page. I want to execute some javascript after the pdf has been loaded but I cannot get this to work. The issue is that the pdf loads after everything else, so the load event fires before the pdf begins to load.
My first approach was to use an iframe. The inner page would retrieve the file and write the data to the response. As mentioned previously, the load event occurred before loading the pdf and I need it to trigger after. The current code uses a generic handler ashx to load the pdf inline. How do I trigger an event to execute javascript, after the pdf data is loaded server side from the ashx generic handler?
Aspx page:
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "View")
{
int index = Convert.ToInt32(e.CommandArgument.ToString());
string Id = GridView1.DataKeys[index].Value.ToString();
HtmlGenericControl myObject = new HtmlGenericControl();
myObject.TagName = "object";
Panel1.Controls.Add(myObject);
myObject.Attributes.Add("data", "GetPdf.ashx?Id=" + Id);
}
}
Generic handler ashx:
public void ProcessRequest(HttpContext context)
{
System.Diagnostics.Debug.WriteLine("GetPdf.ashx started");
string Id = context.Request.QueryString["Id"];
byte[] data = GetPdf(Id);
context.Response.ClearContent();
context.Response.ContentType = "application/pdf";
context.Response.AppendHeader("Content-disposition", "inline");
context.Response.AddHeader("Content-Length", data.Length.ToString());
context.Response.BinaryWrite(data);
System.Diagnostics.Debug.WriteLine("GetPdf.ashx is done");
context.Response.End();
}

Have you tried setting an event handler for the object tag's onload event? I'm not sure if that will work across all browsers, but I also don't know which browsers you require it to work on.
Worst-case scenario you could use setTimeout to rapidly poll for the PDF's existence.
Here's a previous answer that may help you with both aspects.

Related

function to get image from database is not working

I'm new to Javascript. I want to add an icon to all my project's web pages. This icon changes accordingly to whoever logs in in my page. What i'm trying now is, in master page load (when i have all of its data in codebehind, including his chosen icon), i introduced a js function to change icon:
(function icon(image) {
var link = document.querySelector("link[rel*='icon']") || document.createElement('link');
link.type = 'image/x-icon';
link.rel = 'shortcut icon';
link.hre = image;
document.getElementsByTagName('head')[0].appendChild(link);
})();
(adapted from here: Changing website favicon dynamically)
im trying to call this function with Page.ClientScript.RegisterStartupScript() method:
(protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//...
UserModel usuario = (UserModel)Session["usuario"];
//...
Page.ClientScript.RegisterStartupScript(this.GetType(), "icone", $"icone({(Bitmap)new ImageConverter().ConvertFrom(usuario.imagem)});", true);
}
}
The method is simply not executing(its not returning error either, it just "jump it"), and i sincerely have no idea why.
OOOOR, there may be a better way to do it, but i just cant figure it.
For the record, i DONT have the icons/images on a folder. I MUST get them form the database.
(I will later add validation for when user has no image in database. Assume for now it will never be null).
A few things need to be edited:
First, think you got the parameters for RegisterStartupScript not set as required. The 3rd value should be the javascript code to run. You can add the entire script as a variable (as indicated here: https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.clientscriptmanager.registerstartupscript?view=netframework-4.7.2), or you can add your function in <script>...</script> tags to the HTML page, and then just call the function from within RegisterStartupScript (as the 3rd parameter value)
Secondly, there's a typo in your JavaScript function:
link.hre = image; should be link.href = image;
Thirdly, (this part might require some work) the image has to be a URL (string) to the actual image (Not the binary Bitmap)... you might first have to save the image to the web server as a .jpg or .png and use its URL to there, or you have to convert the image to Base64 and add the image via Data URLs https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
Finally, you modified the JavaScript from the original example (you mentioned) In this case, you want to send the image URL as a parameter to the function icon However, the icon function is encapsulated. So the function is basically in a Private scope. Remove the encapsulation around the function if needed to be called from another function on the page... hope this make sense.
Instead of using Javascript, you could simply link your shortcut-icon to a handler, that immediately returns the image. (The following code is not tested, it's there to describe the basic process!)
In your page:
<link rel="shortcut icon" type="image/x-icon" href="/userimage.ashx">
userimage.ashx:
<%# WebHandler Language="C#" Class="UserImageHandler" %>
userimage.ashx.cs:
using System;
using System.Web;
public class UserImageHandler : IHttpHandler {
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "image/png"; // or image/jpg, image/bmp, ...
var image = FetchImageFromDatabase(context.User.Identity.Name); // your logic for fetching the image from the database
// You could also return a default image here, if the user has not selected one.
context.Response.Write(image); // Write the binary data to the response stream.
}
public bool IsReusable {
get {
return false;
}
}
}

execution order when running a javascript inside ASP.Net

I am noob to ASP.net.
I was trying to add a confirmation popup to webpage.
I used the following code :
(which is a variant from this one: http://www.codeproject.com/Articles/8173/A-Simple-ASP-NET-Server-Control-Message-Box-Confir )
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Text;
namespace BunnyBear
{
[DefaultProperty("Text"),
ToolboxData("<{0}:msgBox runat=server></{0}:msgBox>")]
public class msgBox : System.Web.UI.WebControls.WebControl
{
//private string msg;
private string content;
[Bindable(true),
Category("Appearance"),
DefaultValue("")]
public void confirm2(string msg)
{
string sMsg = msg.Replace("\n", "\\n");
sMsg = msg.Replace("\"", "'");
StringBuilder sb = new StringBuilder();
sb.Append(#"<script language='javascript'>");
sb.Append(#" if(confirm( """ + sMsg + #""" ))");
sb.Append(#" { }");
sb.Append(#" else { ");
sb.Append( "document.forms[0].submit(); }");
sb.Append(#"</script>");
content = sb.ToString();
}
protected override void Render(HtmlTextWriter output)
{
output.Write(this.content);
}
}
}
I try it from a test class as follows :
//event triggered when clicking a button
protected void Button2_Click(object sender, EventArgs e)
{
msgBox1.confirm2("are you sure?");
MoreCode();
}
I was expecting that when I click on the button, the confirmation popup pops and asks if I want to confirm:
if I click "no" : postback occurs so MoreCode() is not executed
If I click "yes" : no javascript code is executed, so the execution goes on and MoreCode() is executed.
This is not what happens.
When I click the button with the step by step debugger, I can see that :
it executes msgBox1.confirm2("are you sure?");
it then executes MoreCode()
and afterwards the popup pops
Could you pls explain me why this is executed in this order?
Thanks in advance.
MoreCode() is running on the server side, whereas the popup is on the client side. They are independent operations. If MoreCode must run after the button click, then you need to have a callback in your JavaScript, appending it after
sb.Append(#" if(confirm( """ + sMsg + #""" ))");
The callback would bind to a server call, and that server call would execute MoreCode.
Since you are not using any AJAX, the order of operations is clear: all server-side code is run, then HTML is returned to the browser where the browser executes any necessary client-side code. Here is what happens, in order, starting from when your Button2 is clicked:
Button2_Click server event is called. This event does everything it is asked to do: create a string that will be injected to the resulting HTML page, and then run MoreCode(). Control has not yet been returned to the browser--all this processing is handled on the server-side.
HTML for the resulting page is rendered, along with the string you injected, which includes the JavaScript you have written.
HTML is transferred to the browser and the HTML is executed. Your script triggers a JavaScript prompt, which is then displayed to the user using the text that was specified server-side.

How to make a popup display a message and then present a download after 5 seconds and then close the popup

In my project, I have a file that I want the user to download. When they click on the link, I want a popup window to display "Your download will shortly, if it doesn't start click here". After a few seconds, it will then close and the actual file download will then display.
I know to achieve the window closing you'll use:
window.setTimeout(function(){window.close()}, 5000);
But I'm not sure how you would call the download once the window has closed?
Cheers for any help!
In simple way, use window.open() to start download file.
Direct link
<script type="text/javascript">
setTimeout(function() {
window.open("myfile.doc");
},3000);
</script>
Okay so I don't know your platform so will give an ASP.NET version. If you are using something else then I have commented so you should be able to adapt to your platform.
EDIT: Now know user is using PHP so added code snippet for PHP (not robust but I'm no PHP dev)...
1) SAME FOR PHP/ASP Are you getting a file that will not be displayed by the browser automatically? i.e. .js will be shown as is but an exe will probably trigger a file download dialog (someone correct me if wrong please and I'll update)
If your files are always going to be i.e. .exe then you could probably just get away with:
$("body").append("<iframe src='http://www.targetsite.com/files/thefilename.exe'></iframe>");
but more likely you will be using a parameter to find the right file (and hide direct download
$("body").append("<iframe src='http://www.targetsite.com/downloader/?file=1234-1234-1234'></iframe>");
in some setTimeout function.
If the filetypes are unknown then I suggest pointing the above code at a script file (.ashx, php, etc) that writes the file byte stream to the http response.
FOR PHP:
<?php // Demo - send a (binary) file
$file = "ireland.jpg";//here you would use the query string parameter of the above
//ajax/iframe request eg file=1234-1234-1234 to find image in db
$fp = fopen($file,"r") ;
header("Content-Type: image/jpeg");//this would need to be modified to either show right content type or you could
//set it to Application/force-download
while (! feof($fp)) {
$buff = fread($fp,4096);
print $buff;
}
?>
WARNING Be careful with the above code. It occurred to me you might pass in filename directly which I'm pretty sure someone could use to get files in other places in your app without careful attention
FOR ASP:
I have included an example ashx (generic handler) solution:
aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Wardle.PdfGenerator;
using System.IO;
public partial class user_account_iframedownloader : System.Web.UI.Page
{
private IInformixRepository _rep;
//this page gets loaded into an iframe so we can do downloads while using ajax
protected void Page_Load(object sender, EventArgs e)
{
//write bytes out here i.e. see after for methods
}
}
Example byte output methods (you just need to do File.getBytes or something - my code is quite complicated so 'excercise for reader'
public static void PdfOutput(byte[] pdfData, string filename)
{
HttpContext.Current.Response.ContentType = "Application/pdf";
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename);
HttpContext.Current.Response.BinaryWrite(pdfData);
}
public static void PdfZipOutput(byte[] zipData, string filename)
{
HttpContext.Current.Response.ContentType = "Application/zip";
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename);
HttpContext.Current.Response.BinaryWrite(zipData);
}

Window background turns gray when showing javascript alert message

I m using some serverside validation and if any problem comes I m showing a pop up message using javascript using
page.ClientScript.RegisterClientScriptBlock
but when my message is displayed the background of the window turns gray.
can any one help me to get rid of this gray window
public static class Alert
{
/// <summary>
/// Shows a client-side JavaScript alert in the browser.
/// </summary>
/// <param name="message">The message to appear in the alert.</param>
public static void Show(string message)
{
// Cleans the message to allow single quotation marks
string cleanMessage = message.Replace("'", "\\'");
string script = "<script type=\"text/javascript\">alert('" + cleanMessage + "');</script>";
// Gets the executing web page
Page page = HttpContext.Current.CurrentHandler as Page;
// Checks if the handler is a Page and that the script isn't allready on the Page
if (page != null && !page.ClientScript.IsClientScriptBlockRegistered("alert"))
{
page.ClientScript.RegisterClientScriptBlock(typeof(Alert), "alert", script);
}
}
}
I am using this Function
Since you are using the Javascript alert() function, you have absolutely no control over how the browser handles it. Each browser looks slightly different. However, you can expect that it will be a modal popup with your content, and a single "Ok" button. Beyond that, you have no control.
If you want something different, you'll have to use more complex javascript; perhaps using a jQuery plugin to display your message exactly how you want, or overriding the alert() function.

Hiding loading image on asp.net postback for file download

I have a button on my asp.net page that does a postback, creates an Excel file, clears the response stream and writes the file. The user can then open or save the file user the brower's standard dialog.
This works great, I based the code on this:
http://www.adventuresindevelopment.com/2009/05/27/how-to-export-data-to-excel-in-aspnet/
As the file to be created takes quite a long time I have created a loading panel, just a hidden DIV, and set this to visible when the button is clicked.
But my problem is how to hide this DIV when the export has finished? I just cannot find a way of doing it. I need something like an event that fires when the file has been completely transfered to the browser.
Is this possible? Any help most appreciated.
Thanks,
AJ
What I'd do, long story short :
When the user clicks the "Download" button, use AJAX to call a
processing page asynchronously. This page will generate your Excel
document and store it in a temporary location
When the AJAX request is done, hide the "Loading" panel, and
redirect the user to a download page. Ideally, you should redirect
to a generic (.ashx) handler that opens the file, sets some headers,
streams the temporary file to the user, and deletes the file
afterwards.
Now in more details :
For step one, you should have some temporary folder where you have read and write access. Using the system temp folder is fine, so you could use Path.GetTempFileName. Here is an example of what you could write in an ashx handler :
public class Handler1 : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
string fName = Path.GetTempFileName();
context.Response.ContentType = "text/plain";
try
{
// Generate the Excel document
GenerateExcelInFile(fName);
// Store the file name in session for later use
context.Session["ExcelGeneratorFileName"] = fName;
// Send confirmation to the client
context.Response.Write("ok");
}
catch (Exception e)
{
context.Response.Write("error");
// TODO : Do some logging
}
}
// SNIP : IsReusable
}
After that, use your favorite JS framework to request that handler, and test the returned string. If it is "ok", you call the part two handler :
public class Handler2 : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/excel";
// Make sure the browser will show a "save as" dialog to the user
context.Response.AddHeader("content-disposition", "attachment; filename=Export.pdf");
string fName = context.Session["ExcelGeneratorFileName"] as String;
if (fName != null && File.Exists(fName))
{
// Stream the excel file to the response
context.Response.WriteFile(fName);
// Remove the file
File.Delete(fName);
}
}
// SNIP : IsReusable
}
You can call this page in javascript simply using a window.location = url. The content-disposition header will tell the browser that this URL should not be displayed, only downloaded, so your user should stay on the download page.

Categories