Partial update doesn't work with master pages - asp.net

I am working on a C# asp.net web forms project. It has two master pages. I
have an user control which reads data from database,
creates an un-ordered list in html string and populates a placeholder with
it. This user control has to be automatically
refreshed every 2 minutes. I have included this usercontrol on the parent
master page. I have the following code to refresh the
user control, which I have obtained through another stackoverflow answer.
The problem is that the entire master page refreshes, and I am not sure why.
Is there a way to make that only the user control which has the UpdatePanel
refreshes?
Outer Master Page:
<body>
<form id="frmMain" role="form" method="post" runat="server">
<div>
<uc2:PendingOrders runat="server" ID="PendingOrders" />
</div>
<asp:ContentPlaceHolder ID="MainBodyContent" runat="server">
</asp:ContentPlaceHolder>
</form>
</body>
User Control:
<asp:ScriptManager ID="myScriptManager" runat="server"
EnablePartialRendering="True"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" UpdateMode = "Conditional"
runat="server">
<ContentTemplate>
<asp:Timer ID="Timer1" runat="server" Interval="20000"
OnTick="Timer1_Tick"></asp:Timer>
<asp:PlaceHolder runat="server" id="lblMyOrders"></asp:PlaceHolder>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
</Triggers>
</asp:UpdatePanel>
User Control Code behind:
protected void Timer1_Tick(object sender, EventArgs e)
{
//This method creates the html string with data as an unordered list
and
//populates asp:PlaceHolder inte updatepanel
GetData();
}

UpdatePanel1's Content will be update by Timer1_Tick.
"entire master page refreshes" means master page's Page_Load will be call while Timer1 been trigger?
UpdatePanel always post entire page back server and only render UpdatePanel1's Content.

I had the same problem, but in our project the EnablePartialRendering was set to false on the Master Page, if set to true the whole project breaks.
To fix the problem, I defined another master page without ScriptManager and added the ScriptManager to the page in which I wanted to use UpdatePanels with the EnablePartialRendering attribute set to True.
This fixed the problem.
<asp:ScriptManager ID="myScriptManager" runat="server" EnablePartialRendering="True"></asp:ScriptManager>

Related

Script controls may not be registered before PreRender. when using timer control

I'm a newbie to ASP.net (vb), and i'm working with the timer controls. I've once again researched the answer to this and done as said (overloading prerender method). My problem is I have a master page which i've added a timer control, in order to update a count down field, on going to the sites index page i keep getting the error : "Script controls may not be registered before PreRender." The timer works well on other pages except the index page.
<form id="fMain" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:Timer ID="timer1" runat="server" Interval="1000" OnTick="timer1_tick"></asp:Timer></div>
<div>
<asp:UpdatePanel id="updPnl" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Literal ID="litTimer" runat="server"></asp:Literal>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="timer1" EventName ="tick" />
</Triggers>
</asp:UpdatePanel>
</div>
The Codebehind:
Sub timer1_tick() Handles timer1.Tick
ltr1.text = "test"
End Sub`
Thank you in advance.
This is because you are using Telerik controls and have overridden the OnPreRender method.
You need to add the following to this method:
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);

ASP.NET WebForms: Asynchronous UpdatePanel?

First off, I know that what I am doing here seems entirely impractical and not good design, but I am trying to increase performance in this ASPX that contains 8,000+ lines of markup. Because of the complexity of this page (not to mention messiness) and short deadline, rewriting it to use clientside binding with AJAX/JSON is just not an option, so I have to continue to use serverside binding.
The page I am working on contains around 13 individual sections, each one loading its own entity from the database. Right now, the page initially loads ALL entities synchronously, so you can imagine that this page can sometimes take 5 seconds or longer to load. My goal here is to employ a quick fix that will load these sections only when the section is expanded so that we load only the sections that are requested by the user, thus increasing performance and conserving database resources.
The sample code below should be easy to paste right into a VB.NET WebForm if you're interested in trying this out for yourself. Just name the page asyncupdatepanels.aspx.
The problem:
Overall, my solution is working fairly well. In cmUpdate_Click, I use Threading.Thread.Sleep(2000) to simulate a call to the database to retrieve data. When you click one of the buttons, it pauses for 2 seconds and then sets the appropriate Panel's .Visible property to True.
The issue occurs when you click one button and then click the the other before the first one is finished updating. For example, if you click Show Panel 1 then quickly click Show Panel 2, only Panel 2 shows even though both button clicks are triggered in the codebehind.
Maybe asynchronous UpdatePanel is the wrong term to use here. Regardless, I need to find a way to show the panels as if they were executed in separate asyncronous threads. I want to be able to click these buttons pretty much near the same time and have both panels show.
If anyone has any other solutions to my problem that will not require major changes to the way I bind controls in each section, I'd love to hear it. The method I am using now is pretty much a hack, but it will work for now until we eventually rewrite this whole thing in MVC/c#.
Edit: The production code doesn't actually call a Javascript function by use of a button's OnClientClick. Instead, it uses a jQuery accordion. I just wanted to keep the sample code simple. For now, focus on __doPostBack("<%=cmUpdate.ClientID %>", ButtonId); regardless of how it's ultimately called.
ASPX
<%# Page Language="vb" AutoEventWireup="false" EnableEventValidation="false" CodeBehind="asyncupdatepanels.aspx.vb" Inherits="JsonJqueryDevex.asyncupdatepanels" %>
<!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>
<script language="javascript" type="text/javascript">
function UpdateIt(ButtonId) {
__doPostBack("<%=cmUpdate.ClientID %>", ButtonId);
return false;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
<asp:Button ID="cmShow1" Text="Show Panel 1" ClientIDMode="Static" OnClientClick="javascript:return UpdateIt(this.id);" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:Panel ID="pnl1" Visible="false" runat="server">
Panel 1 content
</asp:Panel>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="cmUpdate" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
<asp:Button ID="cmShow2" Text="Show Panel 2" ClientIDMode="Static" OnClientClick="javascript:return UpdateIt(this.id);" runat="server" />
<asp:UpdatePanel ID="UpdatePanel2" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:Panel ID="pnl2" Visible="false" runat="server">
Panel 2 content
</asp:Panel>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="cmUpdate" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
<div style="display: none">
<asp:UpdatePanel UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:Button ID="cmUpdate" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</div>
</form>
</body>
</html>
Codebehind:
Public Class asyncupdatepanels
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Private Sub cmUpdate_Click(sender As Object, e As System.EventArgs) Handles cmUpdate.Click
Dim Param As String = Request("__EVENTARGUMENT")
Threading.Thread.Sleep(2000)
Select Case Param
Case "cmShow1"
pnl1.Visible = True
Case "cmShow2"
pnl2.Visible = True
End Select
End Sub
End Class
How about disabling the appropriate buttons on click?
Say,
function UpdateIt(ButtonId) {
$('#<%=cmShow1.ClientID %>').attr('disabled', true);
$('#<%=cmShow2.ClientID %>').attr('disabled', true);
__doPostBack("<%=cmUpdate.ClientID %>", ButtonId);
return false;
}
Then, in your code behind, after the sleep, enable them again (cmShow1.Enabled = true / cmShow2.Enabled = true) - the UpdatePanel call will handle the rest.
I would do an AJAX call to your server-side in the page_load event of the page where your updated panel is. You would then call the Update method of your update panel when your processing is done.
You won't have to wait for the processing to be done to do whatever you want to do meanwhile.
Javascript(with jQuery):
function ajaxCall() {
$.ajax({
url: "YourPage.aspx"
});
}
You can process your AJAX call in the Page_Load in your .NET.
I know that you said using AJAX wouldn't be a good option, but this is fairly short and simple.

Refresh content-page asynchronously?

I have a master page "PartialUpdate.Master" and 2 simple content pages "WebForm1.aspx" and "WebForm2.aspx"
WebForm1.aspx/WebForm2.aspx: the content-pages just display their filename
The master page "PartialUpdate.Master" has 2 buttons and a ContentPlaceHolder
in an UpdatePanel. When clicking on a button I want to see the corresponding content-page
Here's what it looks like...
PartialUpdate.Master :
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
Master Page
<asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional"
runat="server">
<ContentTemplate>
<asp:Button ID="btnForm1" CommandArgument="WebForm1.aspx"
runat="server" Text="Form1" OnClick="ChangeForm_Click" />
<asp:Button ID="btnForm2" CommandArgument="WebForm2.aspx"
runat="server" Text="Form2"
OnClick="ChangeForm_Click" />
<hr />
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnForm1"
EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="btnForm2"
EventName="Click" />
</Triggers>
</asp:UpdatePanel>
</div>
</form>
</body>
The code behind of PartialUpdate.Master.cs
protected void ChangeForm_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
Response.Redirect(btn.CommandArgument);
}
Problem here is that Response.Redirect() triggers a full-page postback.
I just want the Master to refresh the content located in the 'ContentPlaceHolder' asynchronously (that's why I added the AJAX UpdatePanel)
In other words, I'd like to dynamically change the content-page that the Master is displaying whitout causing a full-page postback.
Is this possible? If so how?
thank you
Chris
You can call with WebRequest in ajax call and write the content you recieve to the page...
But you can`t "knowing" the browser that you want to redirect to another page without post back.

FileUpload in FormView inside an UpdatePanel

The Scenario:
I have an ASP.Net webpage which I intend to use for letting the user(not the real users, but content manager basically) insert and edit the records in a table using a FormView. This FormView is inside an UpdatePanel, as I'm also using cascading dropdownlists to let the user select some values.
Now, this FormView also contains 4 FileUpload controls, and as you might know that these fileupload controls require a full postback since most browsers do not let Javascript access the disk. So, this problem would have been solved by doing something like:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<Triggers>
<asp:PostBackTrigger ControlID="InsertButton" />
<asp:PostBackTrigger ControlID="UpdateButton" />
</Triggers>
<ContentTemplate>....</ContentTemplate>
</asp:UpdatePanel>
Edit: Forgot to add that the fileuploading takes place in the OnUpdating and OnInserting events of the SqlDataSource.
The Problem:
Since the InsertButton and the UpdateButton reside inside the Formview, I cannot directly access their ID's through markup. And MSDN says that:
Programmatically adding
PostBackTrigger controls is not
supported.
Please suggest some solution to make this work. Any insight on the matter is highly appreciated. Thanks.
P.S.- A workable solution for me was to set the UpdatePanel's PostBackTrigger as the whole FormView itself:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<Triggers>
<asp:PostBackTrigger ControlID="FormView1" />
</Triggers>
<ContentTemplate>....</ContentTemplate>
</asp:UpdatePanel>
But now due to a bit of change in requirements, this solution(if you call it a solution) is not acceptable.
Have you given a though about using Iframe for doing the postback ? something like:
<iframe name="uploader" id=uploader
src="uploaderSender.aspx?AllowedExtension=<%= AllowedExtension %>&StoringPath=<%= StoringPath %>&StoringFileName=<%= StoringFileName %>&OldFileName=<%= OldFileName %>&MaximumSize=<%= MaximumSize %>"
width="450" height="50" frameborder=0 scrolling=no >
</iframe>
with uploaderSender.aspx like :
<form action="UploaderReceiver.aspx" method="post" enctype="multipart/form-data">
<input type="file" name="file" id="file" onchange="document.getElementById('IsFileUploading').style.visibility = 'visible'; document.forms[0].submit()"/>
<span id="IsFileUploading" style="visibility: hidden">
<asp:Image ID="Image1" runat="server" ImageUrl="~/immagini/Ajax-loader.gif" />
</span>
</form>
and UploaderReceiver.aspx like :
protected void Page_Load(object sender, EventArgs e)
{
//if there is one file to process
if (Request.Files.Count > 0)
//create the folder if it does'nt exists and returns the local path to get it
string StoringPathToBeSaved = StoringPath.GetFolderPath();
// append the name of the file to upload to the path.
StoringPathToBeSaved = StoringPathToBeSaved + StoringFileName + Extension;
Request.Files[0].SaveAs(StoringPathToBeSaved);
}
this is just bits of code just for you to figure out if you would be interested in this way of dealing with the upload, I can give you more if you want after.
see you, and good luck with your code,
Yay!! Finally got it to work!
Here's How:
Well contrary to what MSDN says, we can in fact add PostBack Triggers Programmatically. Not necessarily to the UpdatePanel, but to the ScriptManager.
After hours of playing around, here's what worked:
We are not able to access controls inside a FormView, untill the template has been rendered, so we can only add postback triggers after the formview's OnDataBound Event.
protected void FormView1_DataBound(object sender, EventArgs e)
{
if (FormView1.CurrentMode == FormViewMode.Edit)
{
LinkButton lb = (LinkButton)FormView1.FindControl("UpdateButton");
ScriptManager.GetCurrent(Page).RegisterPostBackControl(lb);
}
//Similarily you can put register the Insert LinkButton as well.
}
And now, if your UpdatePanel causes ConditionalUpdate, you can do something like this to make it work:
The Markup:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>..
<EditItemTemplate>
...
<asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" OnClick="Cause_PostBack"CommandName="Update">Update</asp:LinkButton>
...
</EditItemTemplate>
..</ContentTemplate>
</asp:UpdatePanel>
CodeBehind:
//call this function as the OnClick Event Handler for the Controls you want to register as
//triggers.
protected void Cause_PostBack()
{
UpdatePanel1.Update();
}
Otherwise, if your situation allows it(as mine does), just set the UpdatePanel's UpdateMode="Always"
This is old, but was trying to solve another problem and ran into this. This wasn't my problem, but here's an alternative for anyone new who runs into this as well.
You stated your problem as:
Since the InsertButton and the UpdateButton reside inside the Formview, I cannot directly access their ID's through markup
You actually can access their ID's through markup to use as the ControlID in the PostBackTrigger. You just have to use the button's name that is created in the page html mark-up as the ControlID. You can find the name created by viewing the page source when you're viewing the page in the browser. It typically is the name of the FormView + $ + name of the button.
For example, let's say you have a FormView named "FormView1" that contains an Insert button which you gave the ID of "btnInsert" during design. If you open up your page in the browser to view it live and then view the page's source, you'll notice that the html mark-up of the button will actually be given the name "FormView1$btnInsert".
Use that name as the ControlID in your PostBackTrigger and your update panel will work.
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<Triggers>
<asp:PostBackTrigger ControlID="FormView1$btnInsert" />
</Triggers>
<ContentTemplate>....</ContentTemplate>
</asp:UpdatePanel>

FileUpload control postback problem

I'm having a FileUpload control on a aspx page inside a UpdatePanel with a button on click of which I want to set a label with the filename of the selected file.
Here is the code I have:
ASPX PAGE:
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:FileUpload runat="server" ID="fuSimple"></asp:FileUpload>
<asp:Button runat="server" Text="Button" ID="btnPostback"
onclick="btnPostback_Click" />
<br />
<asp:Label ID="lblFileName" runat="server" Text="File Name: "></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
</div>
Code Behind:
protected void btnPostback_Click(object sender, EventArgs e)
{
lblFileName.Text = "File Name: " + fuSimple.FileName;
}
Every time I hit the button, I'm getting an empty string. What am I missing?
Also, when I do this without UpdatePanel it works fine.
Comments/help appreciated.
The FileUpload control is not supported with ASP.NET AJAX and Asynchronous Postbacks. They require a full postback due to the nature of how a file upload works (multipart form data).
The following question should have useful answers: FileUpload control inside an UpdatePanel without refreshing the whole page?

Resources