Calls through UpdatePanel cause ASP.NET validations (css) to not show up - asp.net

I have an ASP.NET AJAX form with ASP.NET validations baked in. When I push the code to the production environment and use the form, the validations do not show up after an ajax call has been made (the validations are still working, but the css is not showing up - ex. * Field Required message). If I don't make any ajax calls, the validations show up just fine. I have read that UpdatePanel has a bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=103134, and I read this blog which has a workaround for it - which didn't work for me: http://weblogs.asp.net/alessandro/archive/2007/12/31/updatepanel-css-stylesheet-upon-partial-refresh-bug-in-ie.aspx
Can someone shed some light to this? Thank you.

An easy fix is to put the style in the updatepanel.
The exampel directly taken from the link http://weblogs.asp.net/alessandro/archive/2007/12/31/updatepanel-css-stylesheet-upon-partial-refresh-bug-in-ie.aspx
<asp:UpdatePanel ID="TheUpdatePanel" runat="server">
<ContentTemplate>
<style type="text/css">
div
{
display:block;
overflow:auto;
}
.collapsed
{
height:50px;
}
.expanded
{
height:inherit;
}
</style>
<asp:Panel CssClass="collapsed" runat="server" ID="pnlMain">
1<br />2<br />3<br />4<br />5<br />6<br />
</asp:Panel>
<asp:Button ID="btnExpCol" runat="server" Text="Expand" />
</ContentTemplate>
</asp:UpdatePanel>

Related

Div is hidden after submit in UpdatePanel

I have a div inside an UpdatePanel, this div is shown when a use click on an edit link. The submit buttons to save are inside this div. Now when the use click on the submit button everything is fine except that this div is automatically hidden! the visibility is changed client side using jQuery's show().
Why is the UpdatePanel hiding my div even though it was shown by me? I have tried to set the runat='server' and enableing viewstate but I am getting the same result.
How do I just tell the UpdatePanelto leave thediv` as it is prior to the submit?
Here is a mini project that shows the problem:
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
edit
</div>
<div id="edit-div" style="display:none; border: 2px black solid;">
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
</form>
<script>
$(document).ready(function(){
$('#edit-link').on('click', function () {
$('#edit-div').show();
});
});
</script>
The code for the submit button:
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = DateTime.UtcNow.ToString();
}
The simplest solution to this problem would be: -
don't use jQuery to show edit-div
make edit-div a server control
convert your edit to an <asp:LinkButton> control, and in its server-side click event, show your edit div
The problem is that the UpdatePanel is restoring the original state as per the markup for the page; edit-div is not a server control and you are showing it via client script, the UpdatePanel is unaware of this and will always return you the original markup.
There are ways to get jQuery to play nice with UpdatePanels in these scenarios, but it is more involved than the simple solution above.
Hope that helps.

VB.NET Ajax UpdatePanel Unwanted Postbacks

GOAL: Create a page that shows a loading image on button click, which disappears after the processing is complete.
ISSUE: I have a page with an Ajax UpdatePanel that initially works correctly, displaying a loading page on button click, and then displays a GridView. However, after that happens, the page constantly refreshes and returns my GridView to its original state (I do some manual column adjustments OnRowDataBound like adding a legend row, merging some cells, cell background color changes, etc.)
The page is structured like so:
I am trying to include an Ajax UpdatePanel that shows a loading image after the Generate Report button is pressed.
On the content page, I essentially wrap the user control (report control shown in blue above and named filterControl below) and the content (gridview defined in .aspx page and bound in the code-behind) in the update panel:
<asp:UpdatePanel ID="updatePanelControls" runat="server">
<ContentTemplate>
<uc:MultiLevelReportFilter ID="filterControl" runat="server"
ReportTitle="Default Title"
InvisiblePanels="pnlMonths,pnlPeriods,pnlBusinessGroups,pnlDisplay,pnlBrands"
DefaultAccountLevel="level4">
</uc:MultiLevelReportFilter>
<asp:LinkButton ID="thelink2" runat="server"></asp:LinkButton>
<asp:UpdateProgress ID="updateProgress" runat="server">
<ProgressTemplate>
<div id="dvProgress" runat="server" style="background-color: aliceblue; left: 40%; position: absolute; text-align: center; top: 35%; vertical-align: middle;">
<div id="Div1" runat="server" style="background-color: #ffffff; border: 4px solid #DBE5F1; height: 100px; padding: 5px; text-align: center; vertical-align: middle; width: 100px; width: 300px; z-index: 1002;">
<asp:Image ID="Image2" runat="server" Style="margin-top: 25px" Height="50px" Width="50px"
ImageUrl="~/Images/New/ajax-loader.gif" />
</div>
</div>
</ProgressTemplate>
</asp:UpdateProgress>
<% Gridview here composed of manually bound ItemTemplate columns %>
</ContentTemplate>
</asp:UpdatePanel>
I wanted to add a trigger on the content page for btnGenerate, the Generate Report button seen in the user control, but the page errors out because btnGenerate is not actually on the page, rather it's in the control:
A control with ID 'btnGenerate' could not be found for the trigger in UpdatePanel 'updatePanelControls'.
Is this structured incorrectly? Should I have the Ajax on the user control, or content page? I'm trying to follow this MSDN example, but it doesn't have any examples with master pages and user controls.
POSSIBLE REASON?: I should note that I am using an updatePanel on the master page to asynchronously update a label with the current time, like so:
<asp:Timer ID="Clock" runat="server" Interval="10000"></asp:Timer>
<asp:UpdatePanel ID="updatePanelClock" runat="server">
<ContentTemplate>
<asp:Label ID="ClockLabel" runat="server"></asp:Label>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Clock" EventName="Tick"></asp:AsyncPostBackTrigger>
</Triggers>
</asp:UpdatePanel>
Is this what's causing the constant refreshes?
EDIT: I've added the UpdateMode property and set it to Conditional on the content page where I'm calling the report control. However, the page is still refreshing incessantly.
Yes, the entire page lifecycle will execute for every updatepanel postback. Anything outside of that update panel will not be refreshed by what the server processed, but all the code will execute as if it were a full page postback.
try javascript function
function myFunction() {
var myVar = setInterval(function () { myTimer() }, 1000);
function myTimer() {
var d = new Date();
var t = d.toLocaleTimeString();
document.getElementById("Label1").innerHTML = "Current Time : " + t;
}
this function call on form body
<body onload="myFunction()">

Make the container of a validation summary visible when the validation summary becomes visible

I have the following markup. The errorPanel was first only used to show server side exception messages, and works fine like that. Now I'd like to incorporate my validation summary into that same errorPanel.
<asp:Panel ID="errorPanel" runat="server" CssClass="error" Visible="false">
<div style="float: right;">
Close</div>
<asp:Label ID="errorLabel" runat="server"></asp:Label>
<asp:ValidationSummary ID="validationSummary" runat="server" EnableClientScript="true" />
</asp:Panel>
<fieldset>
<legend>Create New Role</legend><asp:Label ID="newRoleNameLabel" runat="server" AssociatedControlID="newRoleNameText">Role Name:</asp:Label>
<asp:TextBox ID="newRoleNameText" runat="server" Width="100px"></asp:TextBox>
<asp:RequiredFieldValidator ID="newRoleNameRequired" runat="server" EnableClientScript="true" ControlToValidate="newRoleNameText" Display="Dynamic" ErrorMessage="Please enter a role name.">*</asp:RequiredFieldValidator>
<asp:Button ID="createButton" runat="server" Text="Create" OnClick="createButton_Click" />
</fieldset>
My problem now is that the required validation happens client side, and I want to keep that, so I have no server side opportunity to make errorPanel visible, in order to make the validation summary visible.
I see I have two options: Do validation server side, and use my code there to make the panel visible, or hook into the client side code somehow and catch an event there when the summary should be made visible, and then also make the errorPanel visible. How could I go about the latter?
Here is an approach which is really not recommended, but I had fun writing it, and it might lead you to some zany ideas!
(p.s. I am using jQuery to make life easier)
Take the Visible="false" off your asp:Panel, we'll do it all client side.
<asp:Panel ID="errorPanel" runat="server" CssClass="error">
Now, at document ready time we will hide the panel, and mess with ASP.NET's validation code.
$(document).ready(function () {
// This is more like it!
$("#<% =errorPanel.ClientID %>").hide();
eval('ValidatorCommonOnSubmit = ' + ValidatorCommonOnSubmit.toString().replace('return result;', 'myValidatorHook(result); return result;'));
});
That eval takes the ValidatorCommonOnSubmit() function which is generated by the ASP.NET validators, and modifies it in place so just before it returns its result, it calls myValidatorHook() with that result.
(see this StackOverflow question for where I got the idea)
Now, our hook:
function myValidatorHook(validated) {
if (validated) {
$("#<% =errorPanel.ClientID %>").hide();
}
else {
$("#<% =errorPanel.ClientID %>").show();
}
}
Simple enough - if the validator returned true (page validates), hide the panel; if it returned false (page did not validate), show it.
Use at your own risk! If the JavaScript generated by the ASP.NET validators changes, this will break horribly - but I did test it in ASP.NET 2.0, 3.5 and 4.0, and it worked the same in all three.
I had a similar problem where I had a containing div around a set of ASP validation fields, I wanted to only show the container if there was an error to show.
I used jQuery to hide the container as per Carson63000's answer, but then used jQuery to look at the visibility of the errors and show the container again if something was visible.
jQuery(function () {
jQuery(".checkout-validation").hide();
var show = false;
jQuery(".checkout-validation span").each(function () {
if (jQuery(this).css('display') != 'none' && jQuery(this).css('visibility') != 'hidden') {
show = true;
}
});
if (show == true) {
jQuery(".checkout-validation").show();
}
});
The only clarification other clarification I would add is that standard validation fields are set to visibility: hidden by default and Display="Dynamic" validations are display: none
Old question, but anyway.
I found one simple and clean solution to this. No server-side, no javascript needed.
You can simply put your content of errorPanel in HeaderText of ValidationSummary Control.
Like said on MSDN site:
The HeaderText property is not HTML encoded. Therefore, HTML tags can
be included in HeaderText.
Your example:
<asp:ValidationSummary ID="validationSummary" runat="server" EnableClientScript="true" CssClass="error"
HeaderText='<div style="float: right;">Close</div><span ID="errorLabel" runat="server"></span>'/>
<fieldset>
...
And PLBlum also nailed it on Microsoft asp.net forum:

How to check if client script is already registered during a partial postback

Below is the code I've currently implemented.
if (!Page.ClientScript.IsStartupScriptRegistered(Page.GetType(), scriptKey))
{
ScriptManager scriptManager = ScriptManager.GetCurrent(page);
if (scriptManager != null && scriptManager.IsInAsyncPostBack)
{
//if a MS AJAX request, use the Scriptmanager class
ScriptManager.RegisterStartupScript(Page, Page.GetType(), scriptKey, script, true);
}
else
{
//if a standard postback, use the standard ClientScript method
Page.ClientScript.RegisterStartupScript(Page.GetType(), scriptKey, script, true);
}
}
I'm doing as suggested in this answer so that I can register startup script on both times i.e. when there is partial postback and a full postback.
The problem is Page.ClientScript.IsStartupScriptRegistered(Page.GetType(), scriptKey) always (even when the script is registered before) returns false when it is partial postback. And I couldn't find ScriptManager.IsStartupScriptRegistered (static) method. As a result of this, additional script is emitted on all partial/async postbacks.
Please note that I'm using script manager of AjaxControlToolkit version 4.1 i.e. ToolkitScriptManager in my masterpage. But I don't thing it has something to do with this.
UPDATE
<asp:UpdatePanel ID="ContactDetailsUpdatePanel" UpdateMode="Conditional" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="UpdateContactDetailsButton" EventName="Click" />
</Triggers>
<ContentTemplate>
<div id="ContactDetailsContent" class="contact_details_content">
<div class="customer_contactdetails_left_pane">
<div class="customer_name_field">
<asp:Label ID="CustomerNameLabel" runat="server" Text="Customer" />
<asp:TextBox ID="CustomerNameValue" runat="server" />
</div>
<div class="customer_address_field">
<asp:Label ID="CustomerAddressLabel" runat="server" Text="Address" />
<asp:TextBox ID="CustomerAddressValue" runat="server" />
<asp:TextBox ID="CustomerAddressValue1" runat="server" />
<asp:TextBox ID="CustomerAddressValue2" runat="server" />
<asp:TextBox ID="CustomerAddressValue3" runat="server" />
</div>
<div class="customer_postcode_field">
<asp:Label ID="CustomerPostcodeLabel" runat="server" Text="Postcode" />
<asp:TextBox ID="CustomerPostcodeValue" runat="server" />
</div>
</div>
<div class="customer_contactdetails_right_pane">
<div>
<asp:Label ID="CustomerContactLabel" runat="server" Text="Contact" />
<asp:TextBox ID="CustomerContactValue" runat="server" />
</div>
<div>
<asp:Label ID="CustomerTelephoneLabel" runat="server" Text="Telephone" />
<asp:TextBox ID="CustomerTelephoneValue" runat="server" />
</div>
<div>
<asp:Label ID="CustomerMobileLabel" runat="server" Text="Mobile" />
<asp:TextBox ID="CustomerMobileValue" runat="server" />
</div>
<div>
<asp:Label ID="CustomerFaxLabel" runat="server" Text="Fax" />
<asp:TextBox ID="CustomerFaxValue" runat="server" />
</div>
<div>
<asp:Label ID="CustomerEmailLabel" runat="server" Text="Email" />
<asp:TextBox ID="CustomerEmailValue" runat="server" />
</div>
<div>
<asp:Label ID="CustomerWebLabel" runat="server" Text="Web" />
<asp:TextBox ID="CustomerWebValue" runat="server" />
</div>
</div>
</div>
<div class="update_button_field">
<asp:Button ID="UpdateContactDetailsButton" runat="server" Text="Update"
onclick="UpdateContactDetailsButton_Click" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
Thanks in advance.
NOTE: To be able to understand the progress on this problem, please see the comments on this answer before replying.
UPDATE
I have implemented a temporary solution to this problem by putting a check in javascript that if the script is already executing then do not execute twice. Javascript is still being spitted multiple times on every partial postback. Couldn't prevent it.
As the views to this post are increasing, I can see that there are other people who might also want answer to this problem.
If you are using this;
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "noPasswordMatch", script, true);
Then to check if it has been registered you must use this:
if (Page.ClientScript.IsClientScriptBlockRegistered(this.GetType(), "noPasswordMatch"))
if (Page.ClientScript.IsClientScriptBlockRegistered("noPasswordMatch")) doesn't work!
I ran into this same issue when writing a composite control in ASP.Net. When the control was inside an update panel Page.ClientScript.IsStartupScriptRegistered didnt work. From within the method protected override void CreateChildControls() i was doing something like
ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), initializeTokenInputScriptKey, initializeTokenInputScript, true);
Hence I ran into a situation similar to what you describe here. What solved my problem was passing the control and its type instead of the page and page type to ScriptManager.RegisterStartupScript. Hence the code now looks,
ScriptManager.RegisterStartupScript(this, this.GetType(), initializeTokenInputScriptKey, initializeTokenInputScript, true);
Once I did this change I no longer needed to check Page.ClientScript.IsStartupScriptRegistered. Now my control works with or without update panels. No unnecessary js spitouts either. Hope this helps
I had implemented a temporary solution to this problem by putting a check in javascript that if the script is already executing then do not execute twice. Javascript is still being spitted multiple times on every partial postback. Couldn't prevent it.
I've written an extension method to check whether the script has already been registered with the ScriptManager. You can use the same principle to check startup scripts:
public static bool IsClientScriptBlockRegistered(this ScriptManager sm, string key)
{
ReadOnlyCollection<RegisteredScript> scriptBlocks = sm.GetRegisteredClientScriptBlocks();
foreach (RegisteredScript rs in scriptBlocks)
{
if (rs.Key == key)
return true;
}
return false;
}
Keep in mind your first line of code is the inverse of the method return value because of the !.
if (!Page.ClientScript.IsStartupScriptRegistered(Page.GetType(), scriptKey))
If IsStartupScriptRegistered is returning false as you say, then the if statement should evaluate true because of the !. This should cause the script to be registered as expected.
Your code is based on my answer here, which was based on ASP.NET AJAX 1.0 and ASP.NET 2.0. It may have something to do with .NET 3.5, although I believe I've used the above already in a newer project we did under 3.5 and it worked fine...
Can you post some markup to go with the code?
EDIT: Thanks for posting the markup.
I notice 2 things now:
You mentioned you are using ToolkitScriptManager. It is a control that inherits from ScriptManager. I didn't notice this before, but your code is still referencing ScriptManager directly. You said it was during async postbacks that the script isn't working, which leads me to believe it is an issue with your reference to ScriptManager. I've never used ToolkitScriptManager before so I can't give you exact code, but I can tell you that you'll likely need to update your code-behind, changing all references to ScriptManager and its methods/properties to the equivalent in ToolkitScriptManager.
Try adding a breakpoint on the if statement and make sure it's evaluation to true. I wouldn't be surprised if scriptManager is null, or scriptManager.IsInAsyncPostBack is false because you're using ToolkitScriptManager.
ScriptManager scriptManager = ScriptManager.GetCurrent(page);
if (scriptManager != null && scriptManager.IsInAsyncPostBack)
{
//if a MS AJAX request, use the Scriptmanager class
ScriptManager.RegisterStartupScript(Page, Page.GetType(), scriptKey, script, true);
}
Lastly - Your markup looks okay, other than you don't need the <Triggers> section. Triggers allow you to specify control which are outside of your update panel to cause partial renders. Any child control of the update panel within the <ContentTemplate> section will do this automatically. The button you are targeting in the Triggers section is already within the updatepanel. While I don't think this is the cause of your issue, I'd remove it anyway.
Hope this helps.
Did you mean this: ClientScriptManager.IsStartupScriptRegistered Method

asp:UpdateProgress - suppressing the line-break

I've started working with ASP.net AJAX (finally ☺). and I've got an update panel together with a asp:UpdateProgress. My Problem: The UpdateProgress always forces a line-break, because it renders out as a div-tag.
Is there any way to force it being a span instead? I want to display it on the same line as some other controls without having to use a table or even shudders absolute positioning in CSS.
I'm stuck with ASP.net AJAX 1.0 and .net 3.0 if that makes a difference.
simply place your UpdateProgress inside a span with style="position:absolute;"
I've had the same issue. There is no easy way to tell the updateProgress to render inline. You would be better off to roll your own updateProgress element. You can add a beginRequest listener and endRequest listener to show and hide the element you want to display inline. Here is simple page which shows how to do it:
aspx
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="sm" runat="server"></asp:ScriptManager>
<asp:UpdatePanel runat="server" ID="up1" UpdateMode="Always">
<ContentTemplate>
<asp:Label ID="lblTest" runat="server"></asp:Label>
<asp:Button ID="btnTest" runat="server" Text="Test" OnClick="btnTest_OnClick" />
</ContentTemplate>
</asp:UpdatePanel>
<img id="loadingImg" src="../../../images/loading.gif" style="display:none;"/><span>Some Inline text</span>
<script>
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(function(sender, args) {
if (args.get_postBackElement().id == "btnTest") {
document.getElementById("loadingImg").style.display = "inline";
}
});
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function(sender, args) {
if (document.getElementById("loadingImg").style.display != "none") {
document.getElementById("loadingImg").style.display = "none";
}
});
</script>
</div>
</form>
cs
public partial class updateProgressTest : System.Web.UI.Page
{
protected void btnTest_OnClick(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(1000);
this.lblTest.Text = "I was changed on the server! Yay!";
}
}
My solution:
In CSS
.progress[style*="display: block;"] {
display:inline !important;
}
And ASP
<asp:UpdateProgress class="progress" ID="UpdateProgress1" runat="server">
I just blogged about my own solution to this problem.
http://www.joeaudette.com/solving-the-aspnet-updateprogress-div-problem.aspx
What I did was borrow the UpdateProgress control from the Mono project and modified it to render as a span instead of a div. I also copied an modifed the ms-ajax javascript associated with the control and modified it to toggle between display:inline and display:none instead of using display:block
There is a .zip file linked in my post which contains the modified files.
A better and simplest way is use UpdateProgress inside UpdatePanel with span. I've tested this and work properly in IE, FF, Chrome browsers. like this:
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
..........
<span style="position:absolute;">
<asp:UpdateProgress ID="UpdateProgress1" runat="server"
AssociatedUpdatePanelID="UpdatePanel1">
<ProgressTemplate>
<img alt="please wait..."src="/Images/progress-dots.gif" />
</ProgressTemplate>
</asp:UpdateProgress>
</span>
</ContentTemplate>
</asp:UpdatePanel>
My solution was to wrap it as follows...
<div class="load-inline">LOADER HERE</div>
And in my CSS I use...
.load-inline {display:inline-block}
Just apply float:left to your label/textbox etc.
Like this:
in the header:
<style type="text/css">
.tbx
{
float:left;
}
in the body:
<asp:TextBox CssClass="tbx" .... />
You can make a div inline like this:
<div style="display:inline">stuff</div>
I'm skeptical of it rendering the div for you though... I don't remember having this problem on my pages...

Resources