Friday 15 April 2011

ASP.NET AJAX: Page Method Timeout

Hi,

While working with PageMethods I came to know that there is no default timeout for PageMethods and in one of my project timeout was required to set for my PageMethods calls. I found a way to do this and would like to share it with you.

You can add a timeout to your PageMethod calls using javascript in one simple line as:

PageMethods._staticInstance._timeout = 3000; // 3000 is in milliseconds

Note: 
  • Timeout value is in milliseconds.
  • On timeout, callback method attached to OnFailure event is fired .i.e. If you call your PageMethod as PageMethods.HelloWorld(onSuccess, onFailure); then on timeout method onFailure will be called.

ASP.NET AJAX: Calling PageMethods Synchronously

Hi,

Few days back i had a situation where i need to call PageMethods synchronously. But as you all know PageMethods are asynchronous call with callbacks for Success and Failure cases.
There are many tutorials which explains What are PageMethods and How to use PageMethods? So I'm not focusing into this.

Now, In order to call PageMethods synchronously we have to use following javascript code before calling a PageMethod:

<script type="text/javascript" language="javascript">
  
XMLHttpRequest.prototype.original_open = XMLHttpRequest.prototype.open;
 

XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
 

async = false;
 

var eventArgs = Array.prototype.slice.call(arguments);

return this.
original_open.apply(this, eventArgs);

// Call to your PageMethods

</script>


Code Understanding:
PageMethods are called using open method exposed via XMLHttpRequest object.
Now open method is called with 5 parameters as seen above, one of which specifies whether the call will be synchronous or not and the parameter name is async (true by default).
Here we have to change this async parameter to false and this is done using above javascript code in steps as:
1. First Saved the original open function to another variable named as original_open.
2. Modified original open function to make async parameter to false and finally called original_open (created in step 1.) method with all original parameters except for async parameter which we have changed to false.

Remember once you execute this javascript code all PageMethods call will be synchronous.

Now if you want some of your PageMethod calls should be synchronous and some not, then you will have to change code as:

<script type="text/javascript" language="javascript">

var asyncState = true;
 
XMLHttpRequest.prototype.original_open = XMLHttpRequest.prototype.open;

XMLHttpRequest.prototype.open = function(method, url, async, user, password) {

    async =
asyncState;

    var eventArgs = Array.prototype.slice.call(arguments);

    return this.original_open
.apply(this, eventArgs);
}

</script>


If you want to make a Synchronous PageMethod call, use asyncState = false before calling your PageMethod as:
asyncState = false;
PageMethods.HelloWorld(onSuccess, onError);



And for Asynchronous PageMethod  call:
asyncState = true;
PageMethods.HelloWorld(onSuccess, onError);


Note:  HelloWorld is a method exposed as a PageMethod and onSuccess and onError are callbacks in javascript for success and failure respectively.

Demo:
Expose a method in your page as PageMethod using WebMethod attribute:

Default.aspx.cs
[System.Web.Services.WebMethod]
    public static string HelloWorld()
    {

        System.Threading.Thread.Sleep(1000);
        return "Hello from server side";
    }


This method will just return a string "Hello from server side".
System.Threading.Thread.Sleep(1000) is used to hold the PageMethod call for 1 sec.

Default.aspx
Now create a javascript function to call this PageMethod with callbacks OnSuccess and OnFailure.
function JavascriptHelloWorld() {
            PageMethods.HelloWorld(onSuccess, onError);
            alert("End of Javascript Method");
        }


function onSuccess(result) {
            alert(result);
        }

function onError(result) {
            alert("Error");
        }


At the end of function, JavascriptHelloWorld alert is fired indicating end of function is reached.


Now call function, JavascriptHelloWorld on click of button as:
<input type="button" value="Hello World" onclick="JavascriptHelloWorld();" />

In normal case, onclick of button alert "End of Javascript Method" will be shown first followed by
"Hello from server side" (This delay is due to System.Threading.Sleep(1000);)
This shows that PageMethod call was asynchronous.


Now to call this PageMethod synchronously execute code mentioned at top and then call JavascriptHelloWorld(); now you will see alert "Hello from server side" followed by "End of Javascript Method"  
This shows that PageMethod call was synchronous.

Thursday 24 March 2011

Asp.Net Validation Summary: How to show ValidationSummary using JavaScript

Hi,
Few days back i got a situation that i need to run Validation of a particular ValidatorControl (RequiredFieldValidator) using ValidatorEnable function and was need to show ValidationSummary to show its result.
Achieved the same using ValidationSummaryOnSubmit(); function exposed at client side.

<script type="text/javascript" language="javascript">

function PerformValidation() {
              ValidatorValidate(document.getElementById('rfvName'));
              ValidationSummaryOnSubmit();
 }


</script>
 
Note:  ValidationSummaryOnSubmit takes an argument as validationGroup. If you want to show ValidationSummary for a particular validation group, then call function passing name of validation group.
If function is called without any arguments, then it will show all ValidationSummary (if error) in page.





Asp.Net Validators: Useful Client-Side Properties & Methods

Hi,
This post expose few useful property and methods of Asp.Net Validators at client-side in order to interact with them when needed using JavaScript.

1. Page_IsValid
Use: This is a property exposed by Asp.Net validators in order to check the status of validations performed. Similarly to Page.IsValid property at server-side.
Value: 
True - If all Validations are successful
False - If any one of the Validation fails

2.ValidatorEnable(val, enable)
Parameters:
val:  object, Validator Control Object
enable: bool, Enables/Disables Validation control
How To Call:
ValidatorEnable(document.getElementById('validatorid')); //enable will be true - default or
ValidatorEnable(document.getElementById('validatorid'), true);
Use: To enable/disable Validation Control and to fire Validation of a particular Validator control and it updates Page_IsValid property of page.
It performs 3 things
1. Enable/Disable Validation control (based on parameter, enable)
2. Fires Validation
3. Updates Page_IsValid property to reflect result of Validation performed.
If you want to perform only Step 2 (Fires Validation), you can use below function

3. ValidatorValidate(val, validationGroup, event)
Parameters:
val: object, Validator Control Object
validationGroup: string, Group of validation control
event: event, Event caused Validation to fire
How to call: 
ValidatorValidate(document.getElementById('validatorid')); or
ValidatorValidate(document.getElementById('validatorid'), 'grpAdd'); or
ValidatorValidate(document.getElementById('validatorid'), 'grpAdd', event);
Use: To fire Validation of a particular Validator control but it doesn't updates Page_IsValid property of page.

4.ValidationSummaryOnSubmit(validationGroup)
Parameters:
validationGroup: string, Used to show Validation Summary of this group (if not supplied it will work on all ValidationSummary in page)
How To Call:
ValidationSummaryOnSubmit(); or
ValidationSummaryOnSubmit('grpAdd');
Use: It is used to show ValidationSummary of particular group(if specified). Suppose you have called  ValidatorEnable of a ValidationControl and want to show ValidationSummary on failure, you can use function ValidationSummaryOnSubmit to achieve this.
http://abhijit-j-shetty.blogspot.com/2011/03/aspnet-validation-summary-how-to-show.html




Asp.Net Validations: Execute OnClientClick after Validator Controls completed their validations.

Hi,
Suppose you want to call a function using OnClientClick property of a button; but this call should be after your Asp.Net Validators validation is done, then you can use following approach:

In Short:
Instead of calling your javascript function directly call it using window.setTimeout with 0 millisec as,
<asp:Button ID="Button1" runat="server" Text="Button1" OnClientClick="window.setTimeout(TestValidation,0);"/>
OR (If need to pass parameters to your function)
<asp:Button ID="Button1" runat="server" Text="Button1" OnClientClick="window.setTimeout(function(){ TestValidation(param1, param2); },0);"/>


Your Client Side function:
function TestValidation() {

            //This is executed after your Validation

            if (Page_IsValid) {
                //Validation is successful
            }
            else {
                //Validation Failed
            }

}

In Long:
Lets demonstrate this:
1. Get a textbox control in your page, which will be validated.

 <asp:TextBox ID="txtName" runat="server"></asp:TextBox>

2. Get a RequiredFieldValidator for your TextBox to validate.
<asp:RequiredFieldValidator ID="rfvName" runat="server" ControlToValidate="txtName" ErrorMessage="Please enter a name" ValidationGroup="grpName"></asp:RequiredFieldValidator>

3. Get a button; on postback of which Validation is to be fired.
<asp:Button ID="btnShow" runat="server" Text="Show Name" OnClientClick="showName();" ValidationGroup="grpName" />

I have ValidationGroup property set to  grpName for Button and RequiredFieldValidator so that they belong to same group on Validation.

Now i want to show Name from TextBox  in alert only if RequiredFieldValidation is successful. i.e. Show Name from TextBox if it's not blank. To do this i have attached  showName() function to OnClientClick property of Button which is as:

function showName() {
            if (Page_IsValid) {
                var txtName = document.getElementById("txtName");
                alert(txtName.value);
            }

}
Note: Page_IsValid is a property exposed at client side to check status of Validations that is fired (similarly to property, Page.IsValid at server side)

Now when you run your page and click Show Name button without entering any text in TextBox, you will first see an alert which shows nothing and then ErrorMessage is displayed as "Please enter a name".
This means OnClientClick is executed before Validation is performed.

In order to get our function  showName to execute after Validation is performed you just have to change one thing:
<asp:Button ID="btnShow" runat="server" Text="Show Name" OnClientClick="window.setTimeout(showName,0);" ValidationGroup="grpName" />

Yes, Instead of directly calling your method in OnClientClick call it using window.setTimeout with 0 millisec as: OnClientClick="window.setTimeout(showName,0);"

Note: You can call your method with parameters using setTimeout: window.setTimeout(function(){ funcName(param1, param2, ...); },0);

Now on click of button Show Name you will only see an alert if Textbox contains any text else you will see an ErrorMessage (without any alert).










Javascript: Get topmost parent window in series of nested child windows.

Hi,
Suppose you have opened a pop up window using window.open which in turn opens a new popup window and so on.
For Ex: Parent > Child1 > Child2 > Child3 > ...
Here, > indicates relationship Parent Window > Child Window

Now suppose you want topmost parent window (Parent) from any child window (say, Child3) then you can get this using below function:

Insert this code in your Child3 page:

<script type="text/javascript" language="javascript">

function getTopMostParentWindow() {
           var win = window;
           var topWindow = null;
           while (win = win.opener) {
                topWindow = win;
            }
            return topWindow;
 }


</script>

Now this method will return top most parent window if exists, else null.