Geeks With Blogs

News Awarded Microsoft MVP C#.NET - 2007, 2008 and 2009


I am born in Bangladesh and currently live in Melbourne, Australia. I am a Microsoft Certified Application Developer MCAD Chartered Member (C# .Net)and born in Bangladesh.
I am founder and Chief Executive Officer of
Simplexhub, a highly experienced software development company based in Melbourne Australia and Dhaka, Bangladesh. Co-founder and core developer of Pageflakes www.pageflakes.com.
Simplexhub, is on its mission to build a smart virtual community in Bangladesh and recently launched beta realestatebazaar.com.bd an ASP.NET MVC application written in C#.NET.


Some of My Articles
Flexible and Plugin based .Net Application..
Mass Emailing Functionality with C#, .NET 2.0, and Microsoft® SQL Server 2005 Service Broker'
Write your own Code Generator or Template Engine in .NET
Shahed Khan blog

Introduction

There are many situations where we need to identify if partial rendering is supported in a page, especially when a control uses javascript, to get the control work in partial rendering mode, the script needs to be registered using a ScriptManager Type instead. A classic example will be Validators.

The ASP.NET Page class exposes the Validators property, which is a list of all the IValidator types on the page. A page keeps track of its validators, and registers a javascript array of validators automatically to the page. Example, When we add 3 RequiredFieldValidator in a page the following javascript Array will be automatically generated and added in our page automatically during the page load. 

Page_Validators = new Array(document.getElementById("RequiredFieldValidator1"),
document.getElementById("RequiredFieldValidator2"),
document.getElementById("RequiredFieldValidator3"));

The ASP.NET Page also registers couple of other script which eventually hooks up different events ( onclick, onkeypress, onchange, onblur ) to the the target control (ControlToValidate), to some predefined javascript functions that resides in WebUIValidation.js file. So when we add a validator in our Page we also notice the following script is automatically added. [WebUIValidation.js ships with ASP.NET and resides in the following folder "/aspnet_client/system_web/<version>/WebUIValidation.js".]

<script type="text/javascript">
<!--
var Page_ValidationActive = false;
if (typeof(ValidatorOnLoad) == "function") {
ValidatorOnLoad();
}

function ValidatorOnSubmit() {
if (Page_ValidationActive) {
return ValidatorCommonOnSubmit();
}
else {
return true;
}
}
// -->
</script>

ValidatorOnLoad plays the big role of hooking up the the events mentioned above, and here is a code snippet from this function,

for (i = 0; i < Page_Validators.length; i++) {
val = Page_Validators[i];
if (typeof(val.evaluationfunction) == "string") {
eval("val.evaluationfunction = " + val.evaluationfunction + ";");
}
...

if (typeof(val.controltovalidate) == "string") {
ValidatorHookupControlID(val.controltovalidate, val);
}
...
}

keen eyes may have already noticed the val.evaluationfunction property, yes every validators needs to have this property for it to work properly under the ASP.NET validation framework. Custom validators takes advantage of this property to point to custom js functions. Custom validator developers normally use RegisterExpandoAttribute method to register this attribute.

protected override void AddAttributesToRender(System.Web.UI.HtmlTextWriter writer)
{
   base.AddAttributesToRender(writer);
   if (this.RenderUplevel)
   {
      string clientID = this.ClientID;
      Page.ClientScript.RegisterExpandoAttribute(clientID, "evaluationfunction", "EntryValidatorEvaluateIsValid");
   }
}

Problem
When I used Update Panel with partial rendering enabled the Page.ClientScript.RegisterExpandoAttribute did not work for me. My validators always stopped working after the first postback, which was performed via partial rendering and triggering. I found the "evaluationfunction" in the javascript to be undefined.

Solution
I started looking under the hood, and soon discovered, that the ASP.NET Validators that ships out of the box, ( eg. RangeValidator, RequiredFieldValidator ) uses a different internal method "AddExpandoAttribute" to register the property. Here is a code snippet from the RangeValidator.

protected override void AddAttributesToRender(HtmlTextWriter writer)
{
    base.AddAttributesToRender(writer);
    if (base.RenderUplevel)
    {
        string clientID = this.ClientID;
        HtmlTextWriter writer2 = base.EnableLegacyRendering ? writer : null;
        base.AddExpandoAttribute(writer2, clientID, "evaluationfunction", "RangeValidatorEvaluateIsValid", false);  
        ...
    }
}

and code snippet from BaseValidator, the internal method AddExpandoAttribute.

internal void AddExpandoAttribute(HtmlTextWriter writer, string controlId, string attributeName, string attributeValue, bool encode)
{
    AddExpandoAttribute(this, writer, controlId, attributeName, attributeValue, encode);
}

After digging further I realized, AddExpandoAttribute checks the ASP.Page whether partial rendering is supported, then it registers the attribute using ScriptManager instead. I did the same with my validation control and it works for me. Here is the piece of code that solved my problem.

protected override void AddAttributesToRender(System.Web.UI.HtmlTextWriter writer)
       {
           base.AddAttributesToRender(writer);
           if (this.RenderUplevel)
           {
               string clientID = this.ClientID;
               if (!this.IsPartialRenderingSupported)
               {
                   Page.ClientScript.RegisterExpandoAttribute(clientID, "evaluationfunction", "EntryValidatorEvaluateIsValid");                   
               }
               else
               {
                   Type scriptManagerType = BuildManager.GetType("System.Web.UI.ScriptManager", false);
                   scriptManagerType.InvokeMember("RegisterExpandoAttribute", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object[] { this, clientID, "evaluationfunction", "QuantityEntryValidatorEvaluateIsValid", false });
               }
           }
       }

Note, the I am first checking whether Partial Rendering is Supported and using the ScriptManager  Type to register the property instead.

The following piece of code uses Reflection to figure out whether partial rendering is supported.

internal bool IsPartialRenderingSupported
{
    get
    {
        if (!this.PartialRenderingChecked)
        {
            Type scriptManagerType = BuildManager.GetType("System.Web.UI.ScriptManager", false);
            if (scriptManagerType != null)
            {
                object obj2 = this.Page.Items[scriptManagerType];
                if (obj2 != null)
                {
                    PropertyInfo property = scriptManagerType.GetProperty("SupportsPartialRendering");
                    if (property != null)
                    {
                        object obj3 = property.GetValue(obj2, null);
                        this.IsPartialRenderingEnabled = (bool)obj3;
                    }
                }
            }
            this.PartialRenderingChecked = true;
        }
        return this.IsPartialRenderingEnabled;
    }

}

private bool PartialRenderingChecked
{
    get
    {
        object val = ViewState["PartialRenderingChecked"];
        if (val != null)
            return (bool)val;
        return false;
    }
    set
    {
        ViewState["PartialRenderingChecked"] = value;
    }
}

private bool IsPartialRenderingEnabled
{
    get
    {
        object val = ViewState["IsPartialRenderingEnabled"];
        if (val != null)
            return (bool)val;
        return false;
    }
    set
    {
        ViewState["IsPartialRenderingEnabled"] = value;
    }
}

 

Conclusion

The Page.ClientScript.RegisterExpandoAttribute may not work in Partial Rendiring mode, when a postback is performed via triggering,
to get this work we need to determine whether partial rendering is supported and use the ScriptManager Type instead like described above.

Hope this helps, and saves some of your time, Thank you for being with me so far.

Posted on Tuesday, June 17, 2008 5:43 AM | Back to top


Comments on this post: ASP.NET tips, Making Custom Validators work in Partial Rendering mode.

# re: ASP.NET tips, Making Custom Validators work in Partial Rendering mode.
Requesting Gravatar...
Great!

I've had same problem.
I solved my problem without digging further.

Thank you very much!!
Left by lovekiwi on Sep 07, 2008 11:00 PM

# re: ASP.NET tips, Making Custom Validators work in Partial Rendering mode.
Requesting Gravatar...
I Love U Man

http://forums.asp.net/t/1342221.aspx
Left by Matelin on Nov 03, 2008 4:06 AM

# re: ASP.NET tips, Making Custom Validators work in Partial Rendering mode.
Requesting Gravatar...
Great post. I just solved this problem myself by adding

writer.AddAttribute("evaluationfunction", "ValidatorIsValid");

but your solution is much more elegant. I have run across another situation in that I have several updatepanels that have visible=false to prevent rendering. I set them visible when I am about to display them server side. The problem is that the evaluationfunction doesn't get rendered in time and the validator control fails. Is there a way around this?
Left by David Adams on Nov 16, 2008 3:54 AM

# re: ASP.NET tips, Making Custom Validators work in Partial Rendering mode.
Requesting Gravatar...
Hi,

Thanks for this great article! It resolved HALF my problem.

I've got a page which loads a checkboxlist (CBL) after PostBack. And this CBL will have the validator as described above in your article.

Here's the flow:

1. DropDownList (DDL) with AutoPostBack and OnSelectedIndexChanged.
2. When item is selected on DDL, it will AutoPostBack, and then display the items in the CBL based on the DDL item selected.
3. CBL will then display the records accordingly.
4. And the CBL will have a customCBLValidator, which will validate/ensure that some item is selected.

The problem here is that the customCBLValidator is not working, even though I have implemented the expando as you have mentioned above.

Greatly appreciate some help here.

Thanks! :)

Left by Dennis Wong on Apr 26, 2009 3:20 AM

# re: ASP.NET tips, Making Custom Validators work in Partial Rendering mode.
Requesting Gravatar...
I am trying to get this to work in VB but there are a lot of issues with it. Does anyone know how to translate this to VB or anything else that will get this effect in vb? Thanks
Left by ryan on Aug 08, 2009 5:22 AM

# re: ASP.NET tips, Making Custom Validators work in Partial Rendering mode.
Requesting Gravatar...
I am trying to get this to work in VB but there are a lot of issues with it. Does anyone know how to translate this to VB or anything else that will get this effect in vb? Thanks admin add site
sesli chat
Güzeldi
kilo verme
Left by sesli sohbet on Sep 03, 2009 9:54 AM

# re: ASP.NET tips, Making Custom Validators work in Partial Rendering mode.
Requesting Gravatar...
Thanks admin nice post
I am trying to get this to work in VB but there are a lot of issues with it. Does anyone know how to translate this to VB or anything else that will get this effect in vb? Thanks

mankenler
güzel bence
manken resimleri
Left by manken on Sep 03, 2009 9:56 AM

# re: ASP.NET tips, Making Custom Validators work in Partial Rendering mode.
Requesting Gravatar...
I am trying to get this to work in VB but there are a lot of issues with it. Does anyone know how to translate this to VB or anything else that will get this effect in vb? Thanks
Thanks admin nice post
su pompası
adadadad
hot car picture
Left by tatil on Sep 03, 2009 9:59 AM

Your comment:
 (will show your gravatar)


Copyright © Shahed Khan | Powered by: GeeksWithBlogs.net