asp:FileUpload losing selected file on PostBack [duplicate] - c#

I have asp.net FileUpload control inside an update panel. When I click upload button, I am reading the file for some code, if code not found then I am showing ModalPopup for selecting a user from dropdown, otherwise uploading and emailing the file to user of that Code(this code is saved in Database).
If code not found,its displaying ModalPopup and removing the selected file, I want to persist the selected file after post back.
This is my code
<asp:UpdatePanel ID="UpdatePanel3" runat="server" >
<ContentTemplate>
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:RequiredFieldValidator ID="rfvFileupload" ValidationGroup="validate" runat="server" ErrorMessage="* required" ControlToValidate="FileUpload1"></asp:RequiredFieldValidator>
</ContentTemplate>
</asp:UpdatePanel>
and on Button Click
protected void btnupload_Click(object sender, EventArgs e)
{
//Reading the file and Checking from Database
if(codefound)
{
//Sending email to the user of the Code
}
else
{
ModalPopupExtender1.Show();
}
}
How can I persists the value of Upload control on post back?

Background::
When a file is selected using FileUpload Control ,then on postback, PostedFile property gets initialized with HttpPostedFile object for the file. Since http request cannot maintain state, so it looses it's state.
NOTE: FileUpload control will not work with asynchronous postback.So a postback is needed to get the file. One way is to set the triggers for your Upload button, i.e. <asp:PostBackTrigger > & NOT <asp:AsyncPostBackTrigger>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:FileUpload ID="fileUploadImage" runat="server"></asp:FileUpload>
<asp:Button ID="btnUpload" runat="server" Text="Upload Image"
OnClick="btnUpload_Click" />
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="btnUpload" />
</Triggers>
</asp:UpdatePanel>
And your Upload button code:
protected void btnUpload_Click(object sender, EventArgs e)
{
if (fileUpload1.HasFile)
{
fileName = fileupload1.FileName;
fileUpload1.SaveAs("~/UploadedContent/" + fileName);
}
}
TO PERSIST THE VALUE OF FILEUPLOAD CONTROL, you can store the fileupload object altogether in session and after postback retrieve the values you require from session.
protected void Page_Load(object sender, EventArgs e)
{
// store the FileUpload object in Session.
// "FileUpload1" is the ID of your FileUpload control
// This condition occurs for first time you upload a file
if (Session["FileUpload1"] == null && FileUpload1.HasFile)
{
Session["FileUpload1"] = FileUpload1;
Label1.Text = FileUpload1.FileName; // get the name
}
// This condition will occur on next postbacks
else if (Session["FileUpload1"] != null && (! FileUpload1.HasFile))
{
FileUpload1 = (FileUpload) Session["FileUpload1"];
Label1.Text = FileUpload1.FileName;
}
// when Session will have File but user want to change the file
// i.e. wants to upload a new file using same FileUpload control
// so update the session to have the newly uploaded file
else if (FileUpload1.HasFile)
{
Session["FileUpload1"] = FileUpload1;
Label1.Text = FileUpload1.FileName;
}
}

This problem is somewhat well documented, the update panel is listed as not working with certain controls.
File upload, and tree view being 2 of the biggies.
To make it work you should use Triggers/PostbackTrigger
<asp:UpdatePanel ID="UpdatePanel3" runat="server" >
<ContentTemplate>
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:RequiredFieldValidator ID="rfvFileupload" ValidationGroup="validate" runat="server" ErrorMessage="* required" ControlToValidate="FileUpload1" />
<asp:Buton ID="btnupload" runat="server" Text="Upload" onclick="btnupload_Click"></asp:Button>
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="btnupload"/>
</Triggers>
</asp:UpdatePanel>

try add
$('form').attr('enctype', 'multipart/form-data');

Related

Updating CSS of Controls in different files via CodeBehind

I have this AJAX button that I want to update some CSS. The problem is that the controls I want it to update are in a different file and can't be moved out of that file.
This is the panel whose CSS I want to update, which is located in the Site.master file:
<asp:ScriptManager ID="ScriptManager" runat="server" />
<asp:UpdatePanel ID="Panel2" runat="server" updatemode="Always">
<ContentTemplate>
<div id="updateThis" runat="server"><p>Test text</p></div>
</ContentTemplate>
</asp:UpdatePanel>
This is the button, located in the Items.ascx file:
<asp:UpdateProgress runat="server" ID="PageUpdateProgress">
<ProgressTemplate>
<img class="ajax-loader" src="/Images/ajax-loader.gif" alt="Loading..." />
</ProgressTemplate>
</asp:UpdateProgress>
<asp:UpdatePanel ID="Panel3" runat="server" updatemode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger controlid="UpdateButton" eventname="Click" />
</Triggers>
<ContentTemplate>
<asp:Button runat="server" OnClick="UpdateButton"
OnClientClick="hideButton()" Text="Update"
class="update" ID="UpdateButton" name="UpdateButton"
type="submit" ></asp:Button>
</ContentTemplate>
</asp:UpdatePanel>
This is the Items.ascx.cs method that is UpdateButton
protected void UpdateButton(object sender, EventArgs e)
{
var masterPage = this.Page.Master;
var updatePanel = masterPage.FindControl("Panel2");
var div = (HtmlGenericControl)updatePanel.Controls[0].FindControl("updateThis");
div.Style.Add("color", "#ff0000");
}
When I click the button it doesn't end up working correctly. As of right now, with the AJAX UpdateProgress template, it shows the loading GIF and then the GIF disappears and the text never changes color.
EDIT
Hopefully this will give a better idea of where things might be going wrong:
THIS WORKS
protected void UpdateButton(object sender, EventArgs e)
{
var masterPage = this.Page.Master;
var updatePanel = masterPage.FindControl("Panel2");
var div = (HtmlGenericControl)updatePanel.FindControl("updateThis");
div.Style.Add("color", "#ff0000");
UpdateButton.Text = "Done!";
}
I had #updateThis in the FindControl() method. Don't be like me!
You should add the runat="server" attribute to the div control, to make it visible in code-behind:
<div id="updateThis" runat="server"><p>Test text</p></div>
You can also remove Controls[0] in the event handler (but it works if you keep it, according to my tests):
protected void UpdateButton(object sender, EventArgs e)
{
var masterPage = this.Page.Master;
var updatePanel = masterPage.FindControl("Panel2");
var div = (HtmlGenericControl)updatePanel.FindControl("updateThis");
div.Style.Add("color", "#ff0000");
}

Textbox remembers its data on page refresh

I have 2 textbox on my page and a Button. When I click on a button, the text from the textbox is emailed. But, then when i refresh the page and no content is there, then also i get an email.
protected void Button1_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(TextBox1.Text) && !string.IsNullOrEmpty(TextBox2.Text))
{
//email logic
TextBox1.Text = "";
TextBox2.Text = "";
}
else
{
//do nothing
}
}
Here, on clicking the button, i get an email but then when i refresh the page, even though there is no data, then also it goes inside the loop and i get an email.
How do i stop this ?
Do the following in your Page_Load event and keep your TextBoxes and Button in an <asp:UpdatePanel>. Then the page will not ask to re-submit each time you refresh the page.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
TextBox1.Text = string.Empty;
TextBox2.Text = string.Empty;
}
}
UPDATE
Keep the controls within an UpdatePanel as follows
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional" >
<ContentTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Send mail" onclick="Button1_Click" />
</ContentTemplate>
</asp:UpdatePanel>
You need to use the the POST > Redirect > GET pattern. Here is explanation link

async button in listview

so basically im in a process of creating my unit project which is an eCommerce website. one of the feature that important is a watch list (ex: watch list in ebay)
now i already finish in designing and succeed in adding/removing db record but what bothers me is that the page is the delay/ page posting back for each item saved/clicked. i tried adding an update panel but there is a still delay when we click the button.
below is my copy of the code
Design
<listview>
<itemTemplate>
......
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<asp:LinkButton ID="lnkSaved" class="btn-icon btn-white btn-star btn-radius" runat="server" CausesValidation="false" CommandName="ToggleSave">
<span></span>
<asp:Label ID="lblSaved" runat="server" Text="Save Activity" AssociatedControlID="lnkSaved"></asp:Label>
</asp:LinkButton>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="lnkSaved" />
</Triggers>
</asp:UpdatePanel>
.......
</itemtemplate>
</listview>
CodeBehind
protected void ListViewActivities_ItemCommand(object sender, ListViewCommandEventArgs e)
{
HiddenField hdnisSaved = e.Item.FindControl("hdnisSaved") as HiddenField;
HiddenField hdnActivityID = e.Item.FindControl("hdnActivityID") as HiddenField;
LinkButton lnkSaved = e.Item.FindControl("lnkSaved") as LinkButton;
Label lblSaved= e.Item.FindControl("lblSaved") as Label;
Guid userID = new MembershipHelper().GetProviderUserKey(WebSecurity.CurrentUserId);
if (Convert.ToBoolean(hdnisSaved.Value))
{
lnkSaved.Attributes.CssStyle.Clear();
if(Convert.toboolean(hdnisSaved.Value))
{
lnkSaved.Attributes.Add("Class", "btn-icon btn-white btn-radius btn-star");
lblSaved.Text ="Save";
}
else
{
lnkSaved.Attributes.Add("Class", "btn-icon btn-white btn-radius btn-starred");
lblSaved.Text ="Saved";
}
new CustomerDAC().ToggleSave(userID, Convert.ToInt32(hdnActivityID.Value,hdnisSaved.Value));
}
}
could you guys give me a direction, what should i do so a user will have a smooth experience(async prefered) when clicking this button.
You probably want to perform the action on the client side (browser side) in javascript/jquery and then sync the changes in the background, so that the user's perception is immediate but the slow part (http roundtrip to the server and persisting the data to DB) happens in the "background".

Persist FileUpload Control Value

I have asp.net FileUpload control inside an update panel. When I click upload button, I am reading the file for some code, if code not found then I am showing ModalPopup for selecting a user from dropdown, otherwise uploading and emailing the file to user of that Code(this code is saved in Database).
If code not found,its displaying ModalPopup and removing the selected file, I want to persist the selected file after post back.
This is my code
<asp:UpdatePanel ID="UpdatePanel3" runat="server" >
<ContentTemplate>
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:RequiredFieldValidator ID="rfvFileupload" ValidationGroup="validate" runat="server" ErrorMessage="* required" ControlToValidate="FileUpload1"></asp:RequiredFieldValidator>
</ContentTemplate>
</asp:UpdatePanel>
and on Button Click
protected void btnupload_Click(object sender, EventArgs e)
{
//Reading the file and Checking from Database
if(codefound)
{
//Sending email to the user of the Code
}
else
{
ModalPopupExtender1.Show();
}
}
How can I persists the value of Upload control on post back?
Background::
When a file is selected using FileUpload Control ,then on postback, PostedFile property gets initialized with HttpPostedFile object for the file. Since http request cannot maintain state, so it looses it's state.
NOTE: FileUpload control will not work with asynchronous postback.So a postback is needed to get the file. One way is to set the triggers for your Upload button, i.e. <asp:PostBackTrigger > & NOT <asp:AsyncPostBackTrigger>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:FileUpload ID="fileUploadImage" runat="server"></asp:FileUpload>
<asp:Button ID="btnUpload" runat="server" Text="Upload Image"
OnClick="btnUpload_Click" />
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="btnUpload" />
</Triggers>
</asp:UpdatePanel>
And your Upload button code:
protected void btnUpload_Click(object sender, EventArgs e)
{
if (fileUpload1.HasFile)
{
fileName = fileupload1.FileName;
fileUpload1.SaveAs("~/UploadedContent/" + fileName);
}
}
TO PERSIST THE VALUE OF FILEUPLOAD CONTROL, you can store the fileupload object altogether in session and after postback retrieve the values you require from session.
protected void Page_Load(object sender, EventArgs e)
{
// store the FileUpload object in Session.
// "FileUpload1" is the ID of your FileUpload control
// This condition occurs for first time you upload a file
if (Session["FileUpload1"] == null && FileUpload1.HasFile)
{
Session["FileUpload1"] = FileUpload1;
Label1.Text = FileUpload1.FileName; // get the name
}
// This condition will occur on next postbacks
else if (Session["FileUpload1"] != null && (! FileUpload1.HasFile))
{
FileUpload1 = (FileUpload) Session["FileUpload1"];
Label1.Text = FileUpload1.FileName;
}
// when Session will have File but user want to change the file
// i.e. wants to upload a new file using same FileUpload control
// so update the session to have the newly uploaded file
else if (FileUpload1.HasFile)
{
Session["FileUpload1"] = FileUpload1;
Label1.Text = FileUpload1.FileName;
}
}
This problem is somewhat well documented, the update panel is listed as not working with certain controls.
File upload, and tree view being 2 of the biggies.
To make it work you should use Triggers/PostbackTrigger
<asp:UpdatePanel ID="UpdatePanel3" runat="server" >
<ContentTemplate>
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:RequiredFieldValidator ID="rfvFileupload" ValidationGroup="validate" runat="server" ErrorMessage="* required" ControlToValidate="FileUpload1" />
<asp:Buton ID="btnupload" runat="server" Text="Upload" onclick="btnupload_Click"></asp:Button>
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="btnupload"/>
</Triggers>
</asp:UpdatePanel>
try add
$('form').attr('enctype', 'multipart/form-data');

Viewstate not preserved when handling exception

I'm using a detailsview for a dialog to the user, and it seems that the viewstate is not preserved when there is an error inserting the data.
I'm using a OnInserted handler on the datasource to check if there was an exception like so:
protected void areaInsertHandler(Object sender, SqlDataSourceStatusEventArgs e)
{
if (e.Exception != null)
{
// There was an error in submitting, show the error dialog
ScriptManager.RegisterClientScriptBlock(Page, GetType(), "DialogHandler", "showError('#overlayAreas');", true);
e.ExceptionHandled = true;
}
}
Which simply calls the client side JS function:
function showError(overlayName) {
$(".msgError").css('visibility', 'visible');
$(overlayName).css('visibility', 'visible');
}
My detailsview looks something like this:
<asp:UpdatePanel ID="AreaUP" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<div id="overlayAreas" class="overlay">
<asp:DetailsView
ID="DetailsView_Areas"
runat="server"
Visible="True"
AutoGenerateInsertButton="False"
AutoGenerateRows="False"
caption="<a style='font-weight: bold;'>Bold</a> = Required field"
CaptionAlign="Bottom"
headertext="Create new area"
EnableViewState="true"
DataKeyNames="Area_Name"
DataSourceID="AreasSource"
DefaultMode="Insert">
<Fields>
...
</Fields>
</asp:DetailsView>
</div>
<br />
<asp:Button width="200" height="30" ID="Button_CreateArea" runat="server" OnClientClick="return btnToggle('#overlayAreas')" Text="Create new area" />
</ContentTemplate>
</asp:UpdatePanel>
It all works fine, but for some reason the ASP viewstate is not preserved. Meaning that if I fill out incorrect information in the form and submit I will get the appropriate error and the dialog will still be displayed. But the fields are not filled out with my old values.
If someone could give me some pointers or help me out I'd greatly appreciate it
EDIT 10-08: Still haven't been able to solve it, any ideas at all?
basically:
avoid DetailsView_Areas.DataBind()
if (DetailsView_Areas.CurrentMode != DetailsViewMode.Insert) DetailsView_Areas.DataBind();
create the ItemInserted event for your DetailsView_Areas and put
if (e.AffectedRows < 0) e.KeepInInsertMode = true;
see http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.detailsviewinsertedeventargs.affectedrows(v=vs.110).aspx

Categories

Resources