Pranay Rana: Ajax
Showing posts with label Ajax. Show all posts
Showing posts with label Ajax. Show all posts

Tuesday, June 12, 2018

Way to handle Parallel Multiple Requests

In web application Multiple requests means when there is need of making more then one Http requests to get result response and display to end user on web page. Multiple requests can be
  • Dependent Request
    Http Request is dependent request when it waits for result which needs to be given by other Http request i.e. parent request. Read more about how to perform Dependent request in angular here : Angular Dependent Request
  • Parallel Request
  • When client code fire more then one Http request on server and that all fired request get executed on server simultaneously.
Parallel Http requests are required when application need to make simultaneously to get data and display result to end user. For Example - In online shopping application, on order history page when use clicks on old Order to get detail , details page should display order details with all products detail which is associated with order.
Mostly in application database when order get saved its will save order details with associated product ids not full product. so to achieve this requirement once order data available with product ids, client code need to get fire multiple requests basically for each product id to get detail of product associated with order.

Below picture shows how parallel request get executed by approach going to discuss below.




Below are the way client code make parallel Http request and handle response of the requests to display final result with help of RxJs functions.

1. MergeMap

RxJs function mergeMap allows to fire out multiple request and handle response of each request to produce result. Function flatten inner observable(s) and allow to control each observable. Read more : MergeMap

    import { mergeMap, catchError } from 'rxjs/operators'; 
    megeMapTest() {
    const prouctIds: number[] = [1, 2, 3];
    const requests = from(prouctIds)
      .pipe(
      mergeMap(id => this.productService.getProduct(id))
      );

    requests.subscribe(
      data => console.log(data), //process item or push it to array 
      err => console.log(err));
 } 

In above code, important thing to note out is mergeMap, it merges all parallel requests fired to get product in one observable stream (array of observable) and then allows that request to handle individually.


Advantage
a. One of the advantage with mergemap is, it create single stream of observable and allows to process response of each request individually.
So if there is any request fails i.e. throws server side error, then it doesn't affect other parallel requests. Failed request(s) call error function in above code and succeeded request calls success function. (Which is advantage over second approach i.e. forkJoin function discussed below)

b. mergmap function start processing request as it get response i.e. in case of multiple parallel request it process request which completes first ,doen't wait for other request to get completed. (Which is advantage over second approach i.e. forkJoin function discussed below)

Disadvantage
a. It doesn't preserve sequence (i.e. order in which it fire) of requests, means if there are 10 request fired parallelly then which request complete first will display result first.

Solution to this is

    import { mergeMap, catchError } from 'rxjs/operators'; 
    list: Product[] = [];
    megeMapTest() {
    const prouctIds: number[] = [1, 2, 3];
    const requests = from(prouctIds)
      .pipe(
      mergeMap(id => this.productService.getProduct(id))
      );

      requests.subscribe(
      data => {
        this.list.push(data);

        this.list.sort((a: Product, b: Product) => {
          const aIndex = prouctIds.findIndex(id => id === a.Id);
          const bIndex = prouctIds.findIndex(id => id === b.Id);
          return aIndex - bIndex;
        });
      }, //process item or push it to array 
      err => console.log(err));
 } 

above solution code sort order of received response using index of array.

b. megeMap only merge request of same return type only. To understand this have look to above code again, all request is going to return observable of Product type which is going to be return by getProduct method of productservice.

Making use of forkJoin function can resolve this issue. Which is second approach discussed below.

2. ForkJoin

RxJs function forkJoin take one or more observable as input and provide steam of observable as result, which contains value last value emitted by each  inputted observable to function. Read more : forkJoin

import { catchError } from 'rxjs/operators';
import { of } from 'rxjs/observable/of';
import { forkJoin } from 'rxjs/observable/forkJoin';
  forkJoinTest() {
    const prouctIds: number[] = [1, 2, 3];
    const productRequests = prouctIds.map(id => this.productService.getProduct(id).pipe(
      catchError(error => of(`Bad Promise: ${error.message}`))
    ));

    const requests = forkJoin(productRequests);
    requests.subscribe(
      data => console.log(data) //process item or push it to array 
    );
  } 

In above code, as per definition forkJoin takes observable requests as input and returns result.

Advantage
a. forkJoin  reserve sequence (i.e. order in which request sent), so order in which requests inputted to forkJoin in same order it gives response result.

b. forkJoin can take multiple request which returns different type observable.

async forkJoinTest() {
    const customerRequest =this.customerService.getCustomer(1).pipe(
      catchError(error => of(`Bad request: ${error.message}`))
    );    
    const orderRequest =this.orderService.getOrder(1).pipe(
      catchError(error => of(`Bad request: ${error.message}`))
    ); 
    const productRequest =this.productService.getProduct(1).pipe(
      catchError(error => of(`Bad request: ${error.message}`))
    );

    const requests = await forkJoin(customerRequest,orderRequest,productRequests).toPromise();
    
    console.log('Customer ' + requests[0]);
    console.log('order ' + requests[1]);
    console.log('product ' + requests[2]);
  } 

In above code , forkJoin takes three requests (customer, product, order) which returns different type of observable. Also code make use of async/await advance typescript/javascript concept, which allows to wait till request completes. (Which is advantage over first approach i.e. mergeMap function discussed below)

Disadvantage
a. forkJoin waits for all inputted Http requests to get completed before calling subscribe function. So even though some request get completed it has to wait till other or lets say last request to complete. (This can be avoided with mergeMap function as it process requests as it get completed).

b. if one of the inputted request to forkJoin fails , then forkJoin also fails and return error even other inputted request completed successfully. To check run code as below and return error from server

import { catchError } from 'rxjs/operators';
import { of } from 'rxjs/observable/of';
import { forkJoin } from 'rxjs/observable/forkJoin'; 
  forkJoinTest() {
    const prouctIds: number[] = [1, 2, 3];
    const productRequests = prouctIds.map(id => this.productService.getProduct(id));

    //.pipe(
    //catchError(error => of(`Bad Promise: ${error.message}`))
    //));

    const requests = forkJoin(productRequests);
    requests.subscribe(
      data => console.log(data), //process item or push it to array
      err => console.log(err) 
    );
  } 

In above code catchError function is commented, that means if any of request fails then forkJoin also fails and return that error. (this is not case with mergeMap)
To avoid the make use of catchError function as given in above code.

Which one is better
Both of them is not good or not bad. It all depends on requirement at the end. Because there might be case when have requirement to wait for all request to complete or want to parallely executed request which return different value or do not want to produce result if one of sent requests fails then go for forkJoin and there might be case when have requirement for do not wait till all request get compete or do not want to reserve order of request or want to process requests even one of the request fails then go for mergeMap.  

Friday, March 30, 2012

Cascading with jQuery AutoComplete

Source Code


In this post I am going to show how to achieve cascading functionality with the help of jQuery AutoComplete UI control rather than we are doing with the help of comobo-box controls till date.

By the following screen shot I am going to explain what I am going to achieve in this post and in later on post I am going to explain the part of the code did by me.

Screen 1: Loading Suggestion
When user start typing in country textbox  loader image shows that its loading suggestion for the character typed in textbox.

Screen 2: Display Suggestion
List of suggestion displayed to the end user , which is in turn fetch from the server.

Screen 3: Display State aftter country selection
Select State textbox get visible once user select country name from the suggestion list.

Screen 4: Display City after State selection
Select city textbox get visible once user select state name from the suggestion list.

Screen 5: Display Search button after selecting city
Search button get visible once user done with the selection of city name from the suggested cities.

Screen 6: Displaying Search data
Search Data get displayed in the gridview control once user click on search button.

Screen 7: "No Data Found" Error Message
Error message get displayed when user types in the textbox and suggestion is not available to display.

Screen 8: "Enter valid Data" Error Message

Alert Message of enter data get displayed when search button is press and one of the textbox value is not present.

Screen 9: "Enter valid Data" Error Message
Alert Message of enter data get displayed when search button is press and one of the textbox having value for which suggestion is not present.

As you can see in the screen shot when I type auto-complete functionality show me the suggestion and once I select suggestion , selected value get placed in the textbox and another row get visible which does the same functionality.

Now in the below post I am going to discuss about cascading thing with one textbox only but you can see whole by downloading the full source code of this post.

Aspx page i.e html markup
First start with the Aspx page, what the changes I did for the autocomplete textbox which is going to cascade other autocomplete textbox
<tr id="trCountry">
  <td>
   <label id="lblCountry" runat="server" text="Select Country" width="150px">   
   </label>
  </td>
  <td>
    <div style="float: left;">
TextBox id="txtCountry"
attached class="autosuggest", which tells that when you start typing in its going to display list of suggestion which fetched from the database using ajax and autocomplete plug-in.
<textbox class="autosuggest" font-size="10px" id="txtCountry" runat="server" 
                  width="250px"></textbox>
<span id="spCountry" style="display:none;color:Red;">No Data Found</span>
Span id="spCountry"
It get display when there is no suggestion avaialbe for the character typed in textbox.
<div style="display: none;">
As you see above div having style display=none that means the button and textbox both remains hidden when the page get display on browser.
Button id "btnCountry"
on click event get fire when of of the suggestion get selected. So this button fire up the server side event from javascript and make visible the next level textbox. How it fires the event
<button font-size="10px" id="btnCountry" onclick="btnCountry_Click" 
                runat="server" width="250px"></button>
TextBox id="txtCountryID"
this textbox stores the value of the country id which is going to be selected from the suggestion list.
<textbox id="txtCountryID" runat="server"></textbox>
       </div>
    </div>
  </td>
</tr>
this layout is same for the State and City next level selection textboxes that you can see in full source code.

jQuery/Javascript
Following is jQuery method that going be utilize for the showing the suggestion , which is provided by autocomplete plug-in.

autocomplete - method
method provided by the pug-in which is in turn get attach with the textbox control which than show the suggestion when user types in. In the above code its attached with the Country textbox, which is same for the State and city textbox that you can see in full code.
var pagePath = window.location.pathname;
         $(function() {

         $("#" + "<%=txtCountry.ClientID %>").autocomplete(
             {
Attribute of autocomplete
source - is from which suggestion will come up, as I am fetching data from the server side page/function I used jQuery ajax function to get the list from server.
Sucess - function attached with this attribute of the ajax function get the data for suggestion list as you can see if the data length is equal to 0 than it display span element which shows that data is not present.
source: function(request, response) {

                     $.ajax({
                     url: pagePath + "/GetCountry",
                         data: "{ 'id': '" + request.term + "'}",
                         dataType: "json",
                         type: "POST",
                         contentType: "application/json; charset=utf-8",
                         dataFilter: function(data) { return data; },
                         success: function(data) {
                             if (data.d.length == 0) 
                                 $("#spCountry").show();
                             else
                                 $("#spCountry").hide();
                             response($.map(data.d, function(item) {
                                 {
                                     value = item.Name + " : " + item.ID;
                                     return value;
                                 }
                             }))
                         },
                         error: function(XMLHttpRequest, callStatus, errorThrown) {
                             alert(callStatus);
                         }
                     });
                 },
minLength - no of char typed by use in textbox before the suggestion come up i.e after this many character typed by user than the source get query for suggestion. over here is having value 1 means its start showing suggestion once you start writing in it.
minLength: 1,
select - function associated with this attribute get fire when the use select the item from suggestion list. This is most useful function that do postback and do execute code on serverside by calling serverside button click function , button click function enable State row. As well as this break the string and assign text value to country textbox and id to countryid textbox which is hidden one and which value utilize by the state texbox to display suggestion.
select: function(event, ui) {
                     var str = ui.item.label.split(":");
                     $("#" + "<%=txtCountry.ClientID %>").val(str[0]);
                     $("#" + "<%=txtCountryID.ClientID %>").val(str[1]); 
                     $("#" + "<%=btnCountry.ClientID %>").click();
                 }
             });
         });

Validate function
The function get fire when user click on search button to search people resides in which city once done with selection of country,satate and city.
function Validate() {
      var retVal = true;
      if ($("#spCountry").is(":visible")||
            $("#spSatate").is(":visible") ||
            $("#spCity").is(":visible"))
          retVal = false;
      if($("#" + "").val()=="" ||
         $("#" + "").val()=="" ||
         $("#" + "").val()=="")
          retVal = false;
         if(!retVal) 
      alert("Enter Valid Data"); 
      return retVal;
  }
the code checks for is any of the span element associated with the textbox control is visible which display error message "No Data Found" and also check that is any on textbox contrains blank value. If its all proper it return true value otherwise return false.

CodeBehind Files - aspx.cs file
In cs file I designed class for the testing purpose the name of the class is Common which is going to be utilize by GetCountry, GetState and GetCity methods
public class Common
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int ParentID { get; set; }
}
ID - is the unique value to detect each element uniquely.
Name - is value string value for each element.
ParentID - is value to detect element is child of which element.

People class is used to bind data with the gridview control once user press the search button.
public class People
{
    public string Name { get; set; }
    public string Email { get; set; }
    public int CityID { get; set; }
}
Name- name of the person
Email - email Address
CityID - is the id of city which user belongs.

As I explained before when user start typing in the textbox suggestion list come from the serverside method, following is the one of the method you find other in full code. GetCountry method get called when start typing in Country textbox.
[WebMethod]
    public static List GetCountry(string id)
    {
        try
        {
            List<common> country = new List<common> 
            {
                new Common(){ ID=1 ,Name = "India",ParentID=0 },
                new Common(){ ID=2 ,Name = "USA",ParentID=0 },
                new Common(){ ID=3 ,Name = "Ireland",ParentID=0 },
                new Common(){ ID=4 ,Name = "Australia",ParentID=0 }
            };
As I am going to call the method from server side its having attribute WebMethod. In the above code I initialize the collection of country and country is parent element all element have the parentid 0.
Method has parameter called id which is contains the value of the textbox which is typed in textbox. ajax calling function in source pass the id as json parameter to method that you can see in above method of jQuery/javascript.

List lstcountry =
                        (from c in country
                         where c.Name.StartsWith(id)
                         select c).ToList();
            return lstcountry;
 
        }
        catch (Exception ex)
        {
            return null;
        }
    }
Above code as you can see apply linq query on the collection and locate the match element which starts by the character typed in textbox.

Conclusion
So the above post demonstrate that its easy to achieve the cascading with the help of the auto suggest functionality provided by jQuery autosuggest plug-in.

Note : 
Find download code at the start of article and if you have any problem in downloading source code and if you have any query regarding this please mail me at : pranayamr@gmail.com or post comment at below.

Monday, January 16, 2012

Calling Server Side function from Client Side Script

The post is about how you can call your code behind file function i.e server side written function from your client side code i.e using jQuery.
Recently I got requirement in my project that I have to check that ApplicationCode i.e Value entered by user is already available in database or not i.e unique value.

Output of the will look like as below if record exists its shows error "Record exists" otherwise it doesn't display any record.

Now in following post I am going to discuss about the what are the prerequisite need and why to use that. 

Server Code
Below method get called from the client side script, as you can see there are some changes in the method attribute, declaration and definition which I am going to discuss
    [WebMethod]
    public static string IsExists(string value)
    {
        //code to check uniqe value call to database to check this
        return "True";
    }
WebMethod Attribute
Attached WebMethod attribute with Public method indicates that the method exposed as part of the XML Web service. The attribute tells .NET that a particular public method is exposed as a web-callable method. To make use of this attribute you need to make use of System.Web.Services You can read about this attribute at : WebMethodAttribute Class
Static method
Static method is not associated with the instance of the class which get called by using only classname.methodname() i.e no need to create instance.
So that's why I marked method as static one. It cannot interact with the instance properties and methods of your Page class, because a page method call creates no instance of the Page or any of its controls. Page methods are roughly equivalent to shorthand for standalone web services.

.CS file
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Services;//needed for the webmethod attribute
public

partial class _Default : System.Web.UI.Page
{
     protected void Page_Load(object sender, EventArgs e)
     {
          if (!IsPostBack)
               txtData.Attributes.Add("onblur", "focuslost()");
     }

     [WebMethod]
     public static string IsExists(string value)
     {
          return "True";
     }
}
in above code I have registered client event with onblur and attahced function focuslost.


Client Code on .ASPX page code
jQuery .ajax() call
To called method from the client side code I made use of the jQuery function called ajax to get more details about this function you can read about my blog post : Jquery Ajax Calling functions
function IsExists(pagePath, dataString, textboxid, errorlableid) {
 
$.ajax({
     type:"POST",
     url: pagePath,
     data: dataString,
     contentType:"application/json; charset=utf-8",
     dataType:"json",
     error:
          function(XMLHttpRequest, textStatus, errorThrown) {
               $(errorlableid).show();
               $(errorlableid).html("Error");
          },
     success:
          function(result) {
               var flg = true;
               if (result != null) {
                    flg = result.d;
                    if (flg == "True") {
                         $(errorlableid).show();
                    }
                    else {
                         $(errorlableid).hide();
                    }
          }
     }
    });
}
In client script :
As I have to check code is exists or not I attached focusout() event with my textbox control, so when the focus get lost it make ajax call to the TextChanged event of code behind file.
url -                Contains path of the page which is get called from the client side code i.e from aspx page.
data -              Data sent to server from the client it basically json string.
contentType - Content type sent to server.
dataType -      Expected data format from server
error -            Called when call to server method fails
success -         Called when call to server method is successes and return data from called method can be processed in this method
 .Aspx page code
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Async="true" Inherits="_Default" %>








     
          

as in above code focuslost function get call IsExists function which in-turn call the serverside function and inform the entered value is unique or not.

Monday, November 7, 2011

AJAX presentation

Friday, July 8, 2011

Jquery Ajax Calling functions

Download Code

Recently I am working on Website with the asp.net and jQuery. While working with jquery library I found that there are 5 diffrent function that used to make ajax call to page and to fetch data. I am going to discuss about that five function one by one.

Following is list of that five function availale in jquery libaray to make ajax call.
  1. Load
  2. getJson
  3. GET
  4. POST
  5. Ajax
Load
Method allow to make ajax call to the page and allows to send using both Get and Post methods.
var loadUrl = "TestPage.htm";
$(document).ready(function () {
   $("#load_basic").click(function () {
     $("#result").html(ajax_load).load(loadUrl, function (response, status, xhr) {
                    if (status == "error") {
                        var msg = "Sorry but there was an error: ";
                        $("#dvError").html(msg + xhr.status + " " + xhr.statusText);
                    }
                }
                );
                return false;
});
As you can see in above code you can easily make call to any page by passing it Url. The call back function provide more control and allows to handle the error if any by making use of the Status value.
One of the important thing about the load method is its allow to load part of page rather than whole page. So get only part of the page call remains same but the url is
var loadUrl = "TestPage.htm #dvContainer";   
So by the passing above url to load method it just load content of the div having id=dvContainer. Check the demo code for detail.



Firebug shows the repose get return by when we call the page by Load method.

Important Feature
  • Allow make call with both Get and Post request
  • Allow to load part of the page.
getJson
Method allow get json data by making ajax call to page. This method allows only to pass the parameter by get method posting parameter is not allowed. One more thing this method treat the respose as Json.
var jsonUrl = "Json.htm";
            $("#btnJson").click(function () {
                $("#dvJson").html(ajax_load);

                $.getJSON(jsonUrl, function (json) {
                    var result = json.name;
                    $("#dvJson").html(result);
                }
                );
                return false;
            });
Above code make use of getJSON function and displays json data fetch from the page.
Following is json data return by the Json.htm file.
{
"name": "Hemang Vyas",
"age" : "32",
"sex": "Male"
}

Following image displays the json Data return as respose.


Important Feature
  • Only send data using get method, post is not allowed.
  • Treat the response data as Json only

get
Allow to make ajax request with the get method. It handles the response of many formats including xml, html, text, script, json, and jonsp.
var getUrl = "GETAndPostRequest.aspx";
            $("#btnGet").click(function () {
                $("#dvGet").html(ajax_load);

                $.get(getUrl, { Name: "Pranay" }, function (result) {
                    $("#dvGet").html(result);
                }
                );
                return false;
            });
As in code I am passing Name parameter to the page using get request.
On server side you can get the value of the Name parameter in request object querycollection.
if (Request.QueryString["Name"]!=null)
{
    txtName.Text = Request.QueryString["Name"].ToString();
} 

The firebug shows the parameter passe by me as Get request  and  value of the parameter is pranay



Important Feature
  • Can handle any type of the response data.
  • Send data using get method only.

post
Allow to make ajax request with the post method. It handles the response of many formats including xml, html, text, script, json, and jonsp. post does same as get but just send data using post method.
var postUrl = "GETAndPostRequest.aspx";
            $("#btnPost").click(function () {
                $("#dvPost").html(ajax_load);

                $.post(postUrl, { Name: "Hanika" }, function (result) {
                    $("#dvPost").html(result);
                }
                );
                return false;
            });
As in code I am passing Name parameter to the page using post request.
On server side you can get the value of the Name parameter in request object formcollection.
if (Request.Form["Name"] != null)
{
    txtName.Text = Request.Form["Name"].ToString();
}

The firebug shows the parameter passe by me as Get request  and  value of the parameter is Hanika



Important Feature
  • Can handle any type of the response data.
  • Send data using post method only.

ajax
Allow to make the ajax call. This method provide more control than all other methods we seen. you can figure out the difference by checking the list of parameter.
var ajaxUrl = "Json.htm";
            $("#btnAjax").click(function () {
                $("#dvAjax").html(ajax_load);


                $.ajax({
                    type: "GET", //GET or POST or PUT or DELETE verb
                    url: ajaxUrl, // Location of the service
                    data: "", //Data sent to server
                    contentType: "", // content type sent to server
                    dataType: "json", //Expected data format from server
                    processdata: true, //True or False
                    success: function (json) {//On Successfull service call
                        var result = json.name;
                        $("#dvAjax").html(result);
                    },
                    error: ServiceFailed// When Service call fails
                });


                return false;
            });
In above code you can see the all the parameter and comment related to each parameter describe the purpose of each one.

Fire bug shows the called page return json data and Ajax function treat the respose as Json because in code datatype = json


Important Feature
  • Provide more control on the data sending and on response data.
  • Allow to handle error occur during call.
  • Allow to handle data if the call to ajax page is successfull.

Summary
So each method of jQuery ajax is different and can use for the difference purpose.