AsyncFileUplaod losing target frame - asp.net

My page has an IFRAME tag with a src pointing to another page which has 4 ImageButtons and a ModalPopupExtender that opens up a DIV that contains an AsyncFileUpload (AFU) for loading pictures.
Whenever the user click an ImageButton the ModalPopupExtender opens up the DIV with the AFU control, the user select the picture and then the Imagebutton get the ImageURL of the selected image.
The first time I select an image to upload evrything works fine, the image is saved and the ImageButton gets the correct ImageURL and control goes back to the calling page (the one with the IFRAME tag). The second time the user click an ImageButton to open the ModalPopupExtender for selcting and uploading a picture the page open a new browser window with the iframed document as the main document...
I searched the web for a solution and found out that the AFU changes the document.forms[0].target so in my uploadComplete event I try to restore the document.forms[0].target to the correct target (the IFRAME id) but it still opens up in a new browser window with the iframed document as the main document.
Anyone can help with this ?

There is a known issue with the design of the ASP.NET AJAX AsyncFileUpload control: AsyncFileUpload changes browser location when used in IFRAME page. However, I am unable to reproduce this issue with v3.5.50731.0 of the toolkit and the sample code below.
Since your problem is occurring when the ImageButton is clicked, you should add an OnClientClick handler that resets the form target there - and it should probably be reset to '' (empty string), since the ImageButton is already inside the IFRAME.
Here is the minimum sample, which I can't break with AjaxControlToolkit v3.5.50731.0:
<%# Page Language="C#" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolKit" %>
<html><body>
<script runat="server">
int Id = Convert.ToInt32(HttpContext.Current.Request["Id"]);
</script>
<form runat="server">
<ajaxToolKit:ToolkitScriptManager runat="server" />
<h1>IFRAME <%= Id %></h1>
<asp:UpdatePanel runat="server">
<ContentTemplate>
<ol><li><ajaxToolKit:AsyncFileUpload runat="server" /></li>
<li><asp:Button runat="server" Text="After the file is uploaded, click this button" /></li></ol>
</ContentTemplate>
</asp:UpdatePanel>
</form>
<% if (++Id % 3 != 0)
{ %><iframe src="?id=<%= Id %>" width="90%" name="iframe<%= Id %>" height="400px"
style="float: right" />
<% } %>
</body></html>

Related

Problem with losing upload path on refresh in ASP.NET Web Forms

I have a problem with losing my files on FileUpload in ASP.NET Web Forms. I am making a website which contains a form where a pdf page and an image should be uploaded by user, and previewed, but when they choose a headline text, font name and font size below uploads, those controls refresh my page and all of the uploaded files are lost. I have tried to add enctype="multipledata" in the form, but it did not work. Does anyone have a clue? Thanks in advance.
<script type="text/javascript">
function ShowImageBackPreview(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#<%=imagePreview.ClientID%>').prop('src', e.target.result)
.width(240)
.height(150);
};
reader.readAsDataURL(input.files[0]);
}
}
</script>
<asp:FileUpload ID="uploadImage" runat="server" CssClass="uploads" onchange="ShowImageBackPreview(this)" />
<asp:Image ID="imagePreview" Height="150px" Width="250px" runat="server" />
<asp:TextBox ID="txtName" runat="server" AutoPostBack="true" placeholder="Name"></asp:TextBox>
<asp:TextBox ID="txtSurname" runat="server" AutoPostBack="true" placeholder="Surname"></asp:TextBox>
When I start to enter the name and the surname, the uploaded shown image is disappeared and also the file path, on each entered text it refreshes the page.
Remove the autopostback for the controls txtName and txtSurName.
A auto post back means the page will post back when you change the values in those controls, and when you post-back, then the file is up-loaded, and your image preview will be lost.
You need a final up-load button on your page that when clicked on will run your code. That upload button can then grab the file up-loaded. You can't have autopostbacks for the text box controls as you show, but then again, there should NOT be ANY requirement for those text box controls to have autopostback=true.
So, remove your autopostback for the controls, and you should be fine.

AjaxFileUpload does not work in ASP.NET VB.Net

AjaxFileUpload works on visible TabContainer control TabPanels yet not on ones that are initially invisible and then set to visible.
I believe the issue would be resolved if the visibility property of the TabPanels is set by JavaScript rather than from the server but doesn't know how to do it.
Please help me to fix this issue. Thanks.
ASPX Code:
<%# Page Language="VB" AutoEventWireup="false" CodeFile="AjaxFileUpload.aspx.vb" Inherits="_Default" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server" EnablePageMethods="true"></asp:ToolkitScriptManager>
<p>AjaxFileUpload works on visible TabContainer control TabPanels yet not on ones that are initially invisible and then set to visible.</p>
<p>I believe the issue would be resolved if the visibility property of the TabPanels is set by JavaScript rather than from the server.</p>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:TabContainer ID="TabContainer1" runat="server" ActiveTabIndex="0">
<asp:TabPanel ID="TabPanel1" runat="server" HeaderText="TabPanel 1">
<ContentTemplate>
<asp:Button ID="btnShow" runat="server" Text="Show"></asp:Button>
</ContentTemplate>
</asp:TabPanel>
<asp:TabPanel ID="TabPanel2" runat="server" HeaderText="TabPanel 2" Visible="false">
<ContentTemplate>
<asp:Button ID="btnHide" runat="server" Text="Hide"></asp:Button>
<asp:AjaxFileUpload ID="AjaxFileUpload1" runat="server" AllowedFileTypes="txt,xls,xlsx,doc,docx,msg,pdf,bmp,gif,jpg,jpeg,png" MaximumNumberOfFiles="5" Width="500px" OnUploadComplete="AjaxFileUpload1_OnUploadComplete"></asp:AjaxFileUpload>
</ContentTemplate>
</asp:TabPanel>
</asp:TabContainer>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
Backend VB.Net Code:
Imports System.IO
Imports AjaxControlToolkit
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub btnShow_Click(sender As Object, e As System.EventArgs) Handles btnShow.Click
If TabPanel2.Visible = False Then TabPanel2.Visible = True
TabContainer1.ActiveTabIndex = 1
AjaxFileUpload1.Visible = True
End Sub
Protected Sub btnHide_Click(sender As Object, e As System.EventArgs) Handles btnHide.Click
If TabPanel2.Visible = True Then TabPanel2.Visible = False
End Sub
Protected Sub AjaxFileUpload1_OnUploadComplete(ByVal sender As Object, ByVal e As AjaxFileUploadEventArgs)
Dim strPath As String = Server.MapPath("~/Uploads")
If Not Directory.Exists(strPath) Then Directory.CreateDirectory(strPath)
Dim sFilename As String = System.IO.Path.GetFileName(e.FileName)
Dim sUploadPath As String = "~/Uploads/"
AjaxFileUpload1.SaveAs(Server.MapPath(sUploadPath) + sFilename)
Dim filePath As String = Server.MapPath("~/Uploads/" & e.FileName)
Dim filename As String = Path.GetFileName(filePath)
End Sub
End Class
Actually, even if you set a textbox with visible=false, then the control is NOT sent down to the web page. So, you can't client side even turn that simple text box to become visible.
Use style, and display none.
The page first time is initialized, and that includes js wriing up the ajax up-loader.
So, put the mess in a div (with the control, and anything else you need to hide/show)
, say like this:
<div id="uploader" runat="server" style="display:none;width:50%">
<ajaxToolkit:AjaxFileUpload ID="AjaxFileUpload1" runat="server"
ChunkSize="8192"
ClientIDMode="Static"
ViewStateMode="Enabled" />
</div>
So, if you are in SERVER side code (some button postback), then you can show the "div" like this:
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.uploader.Style("display") = "inline"
End Sub
and to hide:
Me.uploader.Style("display") = "none"
Remember, while we are in a post back, all that "jazz" JavaScript STILL needed to do it dance on the FIRST page load. (so, we can't use visible = false) on first page load (and against the control or div). You need the full page to load - including the truckload of code that ONLY runs the FIRST time the ajaxupload control loads. If it not a first page load - the control will not setup and initialize correctly.
So, by using style, then the control is rendered when the page is first loaded. And this concept not only applies to the ajax, but say for a hidden text box or what not? Again, using style with display none.
In fact, DURING the process of a user selecting files, and up-loading with that control? Well, you don't want a post back. But when the whole up-load is done? And the server side events (such as saving the files), then I often DO WANT some final code, or even the web page to move on. I do want a final post-back to move on. But, I need a post-back client side!
In place of using a JaveScript _dopostback? (which forces you to write parameter code in the server side page load event? I just drop a asp button on the form some place, and HIDE it (of course with style="display:none").
Now I can use client side js to to "click" of that hidden button. The beauty is then the server side event code stub for the single button code runs, and I don't have write up event code with _doPostBack + code in load event for a code stub server side to run!
Now, in the above, I displayed the up-loader using a server side code-behind.
But, you can ALSO rather easy have client side code to hide or show that div.
If you using jQuery()?
Well, jQuery has .hide(), and .show() (and guess what!!! - .hide()/.show() actually sets the style for you!!! - so even jQuery assumes that you hide or show controls with style, since using the "SomeControl.visible" is near use-less (since anything set visible = false is NOT rendered client side - so then you can't hide/show anyway!!!).
So, to hide/show that with jQuery, you could use this client side:
function show() {
$('#uploader').show();
}
function hide() {
$('#uploader').hide();
}
And, if you not using jQuery, and want to hide/show the div? (javascript).
This will work:
function showl2() {
var mydiv2 = document.getElementById('<%=uploader.ClientID%>');
mydiv2.style.display = "inline";
}
function hidel2() {
var mydiv = document.getElementById('<%=uploader.ClientID%>');
mydiv.style.display = "none";
}
So, the simple concept here is that the control has to render on the page load and must do the first time. So, it has to come down to the browser side. Any control not visible will not be sent down to the client side. However, using css means the control is sent down client side - in all cases.
Now, after a upload, and I want a full post back of the page? Well, as note, this can be difficult, since after the ajax server side events run (such as saving the file), you do NOT get a final post back when all is said and done.
So, I set a client side event for the ajax up-loader like this:
<ajaxToolkit:AjaxFileUpload ID="AjaxFileUpload1" runat="server"
AllowedFileTypes="pdf,zip"
ChunkSize="8192"
OnClientUploadCompleteAll="UpLoadDone"
/>
So, note the above client side event - all code (both server and client is done). But we now want a postback from the client side.
So, in the UpLoadDone routine?
I have this:
function uploaddone() {
document.getElementById('<%= btnProof.ClientID %>').click();
}
So, I get a post back and ALSO the code in the button stub server side also runs. And that btProof is hidden with style. But, it is a regular asp.net button. I just wanted it to be clicked after the ajax file up-load is done. But, there not really a way to get the ajax up-load to fire a postback when all is said and one. But, once again:
The concept of a hidden control with style is used - since if I hide that button with .visible = false, then in fact the button would not exist client side, and never be rendered or placed into the browser client side.

Server Control Auto Postback with form has _blank attribute

My case is I have an asp.net page has a form
<form id="form1" runat="server" target="_blank">
and a button redirect to another page and this page will open in a new window because of the target attribute of the form .
<asp:Button ID="button1" runat="server" PostBackUrl="~/kindofpage.aspx" Text="Generate" />
and I have a dropdownlist has auto postback = true to post the past to fill another dropdownlist by selected data .
<asp:dropdownliast id="Make" name="Make" runat="server" autopostback="true"></asp:dropdownlist>
the question is : why when I select item from the auto postbacked dropdown an blank page opened ?
I need a way to post the page by the dropdownlist without openning a blank page ..
Thank you,
For lack of a better idea, you could just remove the target="_blank" attribute from your markup, and when your button is clicked, modify the form tag with JavaScript and set the attribute.
You can set the OnClientClick property and run JavaScript when it's clicked. For example:
<asp:Button ID="button1" OnClientClick="document.getElementById('form1').setAttribute('target', '_blank')" runat="server" PostBackUrl="~/kindofpage.aspx" Text="Generate" />
You could always just adjust your buttonpress code to open a new window such as this:
<asp:Button ID="myBtn" runat="server" Text="Click me"
onclick="myBtn_Click" OnClientClick="window.open('kindofpage.aspx', 'kindofpage');" />
then remove the:
target="_blank"
From the form tag.
I struggled with a similar situation but solved it in the following way.
As mentioned in this answer, you can use the OnClientClick property to set the target to "_blank". E.g.
<asp:Button ID="button1" OnClick="codebehind_method" OnClientClick="document.forms[0].target = '_blank';" runat="server" Text="targets new window" />
Then, in the aspx page that my "codebehind_method" function redirects to, I reset the target of the opener form like so:
<script type="text/javascript">
function resetTarget() {
opener.document.forms[0].target = '';
}
</script>
<body onload="resetTarget()">
Now, if you go back to your opener form and use a control that does not have the "OnClientClick" property set, the AutoPostBack should occur in the same tab.
If you want to find your form by ID, replace "document.forms[0]" with:
document.getElementByID('yourFormName')
<form id="form1" runat="server">

Page OnLoad not fireing changing query string

I have a problem that the OnLoad event is not fireing when I navigate to a page and just change the query string. If I do a postback it is called, then changing the query string ones more OnLoad gets called.
Here is how i try. I navigate to the page OnLoad fires -> then change the query string page updates (all bound elements get updated) OnLoad does not fire -> I do a postback using a button OnLoad fires -> then change the query string OnLoad fires.
I will try to explain in more detail.
The system has log in window when I log in I navigate to an other aspx page sending two query string messages the last query string is a number (page.aspx?key=text82&key2=2010). When I get to the page the first time PageLoad event gets called and all is fine, if I in the browser change the key2 to 2011 and press enter the PageLoad does not get called but all my bound elements get updated (GrivView etc..). If I then do a postback using a button the PageLoad gets called. If I now change the 2011 back to 2010 and press Enter PageLoad is called.
I try this is firefox the PageLoad get called every time.
I tired to write a test website but I do not get the same problem, but what i found out is that in IE 8 changing the query string to the same number and pressing enter the PageLoad is not called. But doing so in firefox makes the postback fire. Here is the test code
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<h2>
Welcome to ASP.NET!
</h2>
<p>
<asp:Button ID="Button1" runat="server" Text="Button" />
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Default2.aspx?t=tt& tttttt=2010">HyperLink</asp:HyperLink>
</p>
<p>
You can also find <a href="http://go.microsoft.com/fwlink/?LinkID=152368&clcid=0x409"
title="MSDN ASP.NET Docs">documentation on ASP.NET at MSDN</a>.
</p>
</asp:Content>
Navigates to
<%# Page Language="C#" AutoEventWireup="true" MasterPageFile="~/Site.master" CodeFile="Default2.aspx.cs"
Inherits="Default2" %>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label><asp:Button ID="Button1"
runat="server" Text="Button" />
</asp:Content>
OnLoad event Default2.aspx
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text += "Called " + DateTime.Now.ToString();
}
I found out the problem. Looks like the browser cache was giving me the problem. Press F12 and cleared the cache, it works.

ASP.NET, JQUERY: How do I pick up values populated on the client AFTER the last postback?

I have a legacy system where I want to improve the user experience.
On one of the forms there are 2 drop down listboxes; the change of one ddl cascades to the next.
On the current form, this is acheived by selectedindexchanged event from which the other ddl can be repopulated.
Although this works, in order for the event to be fired, the control has to have the autopostback=true property set.
This postback creates a bad user experience.
So the simple solution is to put the ddls into an update panel control. However doing this has the odd knock on effect of disabling my JQuery Cluetip controls. I do not know why this is.
In which case it is time I finally got round to populating my controls using JQuery and/or AJAX.
So I have tried the following solution below in a test application.
However when I click on the submit button, the changes I make to the Sub Categories ddl are not being picked up in the code behind event for my button (a server side control).
The reason appears to be that the client side updates happened after the last postback, and so on the server the control still has the previous values.
How do I pick up the new values on server side, or should I try something else?
I am using a server control button because that is what the orginal legacy code does, and changing everything to client side would be a big job.
The web page;
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link href="CSS/RM.css" rel="stylesheet" type="text/css" />
<script type='text/javascript' src='http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js'></script>
<script type='text/javascript' src='Default.js'></script>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>Test Categories</h1>
<table>
<tr>
<th class="wid3">Category:</th>
<td class="wid4"><asp:DropDownList
ID="Categories_ddl" runat="server" DataSourceID="odsCategories"
DataTextField="Category1" DataValueField="Category_ID"
>
</asp:DropDownList>
</td>
<th class="wid3">Sub Category:</th>
<td class="wid4"><select
ID="Sub_Categories_ddl" runat="server" DataSourceID="odsSub_Categories_4_Category"
DataTextField="Sub_Category1" DataValueField="Sub_Category_Id">
</select></td>
</tr>
</table>
<asp:ObjectDataSource runat="server" ID="odsCategories"
TypeName="ClassLibraryRiskManCategories.DAL" SelectMethod="GetCategories" />
<asp:ObjectDataSource runat="server" ID="odsSub_Categories_4_Category"
TypeName="ClassLibraryRiskManCategories.DAL" SelectMethod="GetSubCategories">
<SelectParameters>
<asp:ControlParameter ControlID="Categories_ddl" Name="categoryId"
PropertyName="SelectedValue" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
<div style="padding:100px"><asp:Button runat="server" ID="btnTest" Text="Submit"
onclick="btnTest_Click" /></div>
</div>
</form>
</body>
</html>
The JScript
$(document).ready(function() {
$("#Categories_ddl").change(function() {
$("#Sub_Categories_ddl").html("");
var CategoryId = $("#Categories_ddl > option:selected").attr("value");
if (CategoryId != 0) {
$.getJSON('LoadSubCategories.ashx?CategoryId=' + CategoryId, function(Sub_Category1) {
$.each(Sub_Category1, function() {
$("#Sub_Categories_ddl").append($("<option></option>").val(this['Sub_Category_Id'].toString()).html(this['Sub_Category1']));
});
});
}
});
});
ASP.NET cannot really be told to commit any changes to a control between postbacks unless they are performed in a fashion that it expects (such as editing a textbox). Arbitrarily changing a DropDownList's options outside of a server event is one case of a non-trackable change (at least in any reasonable sense). Fortunately, using an UpdatePanel as you were before is a viable approach and correcting the issue you described with your tooltips is actually quite straightforward.
To address the issue of your jQuery Cluetips not appearing after an UpdatePanel postback, you will need to reinitialize the plugin just after the partial refresh as it is no longer registered to elements existing in the DOM (since your the partial refresh replaced those elements). You can achieve this by wrapping the plugin initializer in a javascript method called pageLoad():
function pageLoad() {
// do some javascript here
}
Any javascript method called pageLoad() will automatically be called by ASP.NET after every full and partial page load. With this technique you will be able to restore your jQuery Cluetips after you repopulate the DropDownLists from the UpdatePanel's postback. Take a look at this excellent article on the ASP.NET AJAX Client Life-Cycle Events for more information.

Resources