Source code for this article can be downloaded from http://udooz.net/index.php?option=com_docman&task=doc_download&gid=2&Itemid=5

This article is continuation of Part I.  In this part, I explain the different data binding options in ASP.NET AJAX 4.0 templates.  Just a recap that I’ve consumed an ADO.NET data services to fetch AdventureWorks’s Product table records.  In this article, I explain how to update/add new record from client side.

Bindings

Template supports the following bindings:

  • One-time – The expression is evaluated only once when the template rendering happen
  • One-way Live Binding – The expression is evaluated and update the value, if items in the data source changed
  • Two-way Live Binding – If the data source value changed, the value in the expression updated.  And if the value in the expression is updated, it will update data source also.

The below diagram depicts the binding.

ASP.NET 4.0 Live Binding

In the above diagram, the red dashed arrow shows one-time data binding.  Once the data from data source has been fetched by DataView using AdoNetDataContext.  The one-way live binding has  been shown as purple shadowed arrow.  The purpose shadow here is whenever a data updated at data source, it is being updated to data view through AdoNetDataContext.  The two-way live binding has been shown as  green shadowed two-head arrow.  In this case, data context should have the knowledge about update operation on data source and provide an interface to data view to send the modified values.

The these three bindings, ASP.NET AJAX provides the following expression convention:

  • {{ <data_item_name> }} – One-time (can be used on any HTML controls for example <p>{{ Name }}</p>)
  • { binding <data_item_name> } – One-way if other than user input HTML controls for example <td>{ binding Name } </td)
  • {binding <data_item_name> } – Two-way  if INPUT HTML controls for example <input type=”text” sys:value=”{{ binding Name }}” />)

Here, the input controls binds the values using sys:value attribute for two-way binding.

Before going into the updatable data source, let us see how can we design master-detail layout to display Product name and Product details.

Master-Detail Layout

 

<body xmlns:sys="javascript:Sys"
xmlns:dataview="javascript:Sys.UI.DataView"
sys:activate="*">
  <form id="form1" runat="server">
 
<div>
      <!--Master View-->
     
<ul sys:attach="dataview" class=" sys-template"
          dataview:autofetch="true"
          dataview:dataprovider="{{ dataContext }}"
          dataview:fetchoperation="Products"
          dataview:selecteditemclass="myselected"            
          dataview:fetchparameters="{{ {$top:'5'} }}"
          dataview:sys-key="master"            
      >
         
	<li sys:command="Select">{binding Name }</li>
     </ul>
      <!--Detail View-->
     
<div class="sys-template"
          sys:attach="dataview"
          dataview:autofetch="true"
          dataview:data="{binding selectedData, source={{master}} }">
          <fieldset>
            <legend>{binding Name}</legend>
            <label for="detailsListPrice">List Price:</label>
            <input type="text" id="detailsListPrice"
                sys:value="{binding ListPrice}" />
           
            <label for="detailsWeight">Weight:</label>
            <input type="text" id="detailsWeight" sys:value="{binding Weight}" />
           
             
          </fieldset>
          <button onclick="dataContext.saveChanges()">Save Changes</button>
     </div>
 </div>
  </form>
</body>

Selectable And Editable

An unordered list shows the master details, here the product name (line 15).   This line also indicates that the list item is selectable using sys:command=”Select”.   For maintaining master-detail or selectable item, primary key needs to be specified.  The  sys-key  property of data view refers that primary key.  In this example, I call the primary key as “master” (line 13).  Also, you can see that I’ve passed a filter option using fetchparameter property of data view (line 12).  In this example, I request the ADO.NET data service to give only top five records using its filter syntax.

Whenever an item in the master list is selected, the details view needs to be notified.  The widget for the details view and binding details should be identified using regular sys:attach=”dataview” and dataview’s data property.  In this example, dataview:data=”{binding selectedData, source={{master}} }” specifies that binding with data view with sys-key name “master”.  The fieldset is used to show set of values for a product.  Here, the list price and weight can be editable.

Once an item has been edited, this needs to be notified to the data source through data context.  The button with caption “Save Changes” specifies that whenver this button is clicked, save the items in the details view into data source through data context’s saveChanges() method.  The corresponding data source’s update option should be set on data context’s set_saveOperation().  The following JavaScript code explains this.

 

var dataContext = new Sys.Data.AdoNetDataContext();
dataContext.set_serviceUri("AWProductDataService.svc");
dataContext.set_saveOperation("Products(master)");
dataContext.initialize();

The ADO.NET Product data service’s Products(id) method is used on set_saveOperation.  An item can be updated, when Product service of ADO.NET data service is being invoked with product primary key as argument.  Here, again I’m referring master layout’s “master” sys-key as primary key of Product.

The output of the above code is

ASP.NET 4.0 Live Binding

The top one is master view where Sport-100 Helmet, Red is selected and the details has been shown in the bottom page.  You can edit and update the data source.

The selecteditemclass property of data view is used to show the selected item.

Tags Tags: , ,
Categories: ASP.NET
Posted By: udooz
Last Edit: 27 Aug 2009 @ 08 26 PM

EmailPermalinkComments (0)
 24 Apr 2009 @ 9:02 AM 

Sample VS2008 Project is available at http://snipurl.com/asp_net_extendercontrol_sample.zip

This is the continuation  of ASP.NET Extender Control: Decorating & Componentizing Web Controls with Client Behavior.  In this walkthrough, the following things are explained:

  • Decorating or extending web control behavior.  A mouse hover effect which is implemented in JavaScript would be applied to controls of  type Button.
  • Packaging client side implementation along with the extender control assembly.

The client side implementation should consume  ASP.NET AJAX JavaScript API, in order to get the benefit of this.

As explained in previous section,  this walkthrough explains how to add mouse over and mouse out effect to controls of type Button.

Steps

  1. Implement decorator class based on ExtenderControl
  2. Implement client side behavior
  3. Make client side script as ASP.NET AJAX web resource
  4. Consume extender control

Decorator Class Implementation

Based on your application architecture and/or decorator usage, define the decorator class either within web project or separate assembly.  HoverExtension is the decorator class which extends ExtenderControl.

Based on figure 3 in the previous post, the following are the steps need to be completed:

  1. Define decorated properties in control
  2. Map control and client side properties
 

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Generic;

namespace Udooz
{
    [TargetControlType(typeof(Button))]
    public class HoverExtension : ExtenderControl
    {
        private string _hoverCssClass;

        public string HoverCssClass
        {
            get { return _hoverCssClass; }
            set { _hoverCssClass = value; }
        }
        private string _normalCssClass;

        public string NormalCssClass
        {
            get { return _normalCssClass; }
            set { _normalCssClass = value; }
        }

        protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors(Control targetControl)
        {
            ScriptBehaviorDescriptor descriptor = new ScriptBehaviorDescriptor("Udooz.HoverExtension", targetControl.ClientID);
            descriptor.AddProperty("hoverCssClass", this.HoverCssClass);
            descriptor.AddProperty("normalCssClass", this.NormalCssClass);           
            return new ScriptBehaviorDescriptor[] { descriptor };
        }

        protected override IEnumerable<ScriptReference> GetScriptReferences()
        {
            ScriptReference reference = new ScriptReference();
            reference.Assembly = "HoverExtension";
            reference.Name = "Udooz.HoverExtension.js";
            return new ScriptReference[] { reference };
        }
    }
}

Define decorated properties in control

The TargetControlTypeAttribute (line 10 ) enables to specify to which web controls this decorator can be applied.  HoverExtension can only be applied to Button type.  The next step is to define decorated properties for the server side so that it can be used in ASPX page. NormalCssClass and HoverCssClass are two properties defined to set style name for normal and hover state (line 15 – 26).

Map control and client side properties

As discussed in the previous post, the decorated class implements IExtenderControl’s methods GetScriptDescriptors (line 28-34) and GetScriptReferences (line 36-42).  The ScriptBehaviorDescriptor does two things here:

  • Based on the target server control given as an argument in the constructor, it specifies the client class to target control’s client ID (line 30).
  • Map the server side properties to client side properties (line 31, 32).

The ScriptReference is used to specify on which assembly the client behavior script file will be included (line 39) and the script file name (line 40).

Client Side Behavior Implementation

Based on figure 3 in the previous post, the following are the steps need to be completed those are implemented in HoverExtension.js:

  1. Define decorated properties for client side
  2. Implement client side behavior
 

Type.registerNamespace('Udooz');

Udooz.HoverExtension = function(element)
{
    Udooz.HoverExtension.initializeBase(this, [element]);

    this._hoverCssClass = null;
    this._normalCssClass = null;
}

Udooz.HoverExtension.prototype =
{
    initialize: function() {
        Udooz.HoverExtension.callBaseMethod(this, 'initialize');             
        $addHandlers(this.get_element(),
                     { 'mouseover': this._onMouseOver,
                         'mouseout': this._onMouseOut
                     },
                     this);

        this.get_element().className = this._normalCssClass;
    },

    dispose: function() {
        $clearHandlers(this.get_element());

        Udooz.HoverExtension.callBaseMethod(this, 'dispose');
    },

    _onMouseOver: function(e) {
        if (this.get_element() && !this.get_element().disabled) {
            this.get_element().className = this._hoverCssClass;
        }
    },

    _onMouseOut: function(e) {       
        if (this.get_element() && !this.get_element().disabled) {
            this.get_element().className = this._normalCssClass;
        }
    },

    get_hoverCssClass: function() {
        return this._hoverCssClass;
    },

    set_hoverCssClass: function(value) {
        if (this._hoverCssClass !== value) {
            this._hoverCssClass = value;
            this.raisePropertyChanged('hoverCssClass');
        }
    },

    get_normalCssClass: function() {
        return this._normalCssClass;
    },

    set_normalCssClass: function(value) {
        if (this._normalCssClass !== value) {
            this._normalCssClass = value;
            this.raisePropertyChanged('normalCssClass');
        }
    }
}

// Optional descriptor for JSON serialization.
Udooz.HoverExtension.descriptor = {
    properties: [{ name: 'hoverCssClass', type: String },
                    { name: 'normalCssClass', type: String}]
}

// Register the class as a type that inherits from Sys.UI.Control.
Udooz.HoverExtension.registerClass('Udooz.HoverExtension', Sys.UI.Behavior);

if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

A client side class Udooz.HoverExtension is defined.  The constructor initialize the given “element”.  The element reference is the target web control which will be given by ASP.NET at run time using ASP.NET AJAX $create() method.

Define decorated properties for client side

There are two properties normalCssClass (line 56-65) and hoverCssClass (line 45-54) defined.

Implement client side behavior

The mouse over and mouse out events are registered (line 17-21) and those handlers are defined (line 32-42).

Make Client Side Script As ASP.NET AJAX Web Resource

To package the HoverExtension.js into HoverExtension.dll, this script needs to be declared as web resource so that ASP.NET AJAX identifies and consumes this as web resource and invoke this via ScriptResource.axd handler.  In the AssemblyInfo.cs file of HoverExtension.dll, the following code needs to be added.

 

[assembly: System.Web.UI.WebResource("Udooz.HoverExtension.js", "text/javascript")]

 

Consume Extender Control

Build the HoverExtension project and refer this into a ASP.NET 3.5 web project. The page should register HoverExtension type and can use wherever require.

 

<%@ Register Assembly="HoverExtension" Namespace="Udooz" TagPrefix="udooz" %>

Before consuming the control, the actual styles should be required.

 

<style type="text/css">
.Hover
{
    background-color:Red;
    border-color:Yellow;
}

.Normal
{
    background-color:Aqua;
    border-color:Blue;
}
</style>

 ASP.NET AJAX ScriptManager is required for runtime behaviors.

 

 
<pre>
 

<asp:ScriptManager ID="ScriptManager1" runat="server" />

 The actual button control definition and extender control usage would be

 

 
<pre>
 

<asp:Button ID="button" Text="Extended Button" runat="server" />       
<udooz:HoverExtension ID="extender1" HoverCssClass="Hover" NormalCssClass="Normal" TargetControlID="button" runat="server" /> 

When executing this page, ASP.NET AJAX creates the following for extension.

 <span lang="EN">
<script type="text/javascript">

//<![CDATA[

Sys.Application.initialize();

Sys.Application.add_init(function() {

$create(Udooz.HoverExtension, {"hoverCssClass":"HighLight","normalCssClass":"LowLight"}, null, null, $get("button"));

});

//]]>

</script>
Tags Tags: , , , ,
Categories: ASP.NET, JavaScript
Posted By: udooz
Last Edit: 25 Apr 2009 @ 08 22 AM

EmailPermalinkComments (2)
If you are new to AjaxView, read my previous post Ajax View – Rewrite Web App Code at Production Stage.  In this post, I am going to identify performance bottleneck of this blog site without touching the soul of my blog using AjaxView.  If you do not have AjaxView, download it from http://tinyurl.com/ajax-view-download.

Start Walking

  1. Configuring your browser.  AjaxView is running as a proxy (localhost) at port number 8888 so that you should configure your browser to listen from this proxy.  Since, this is a proxy tool, you can use any browser.  I am using Firefox, because IE is running for this blog post writing.
  2. Execute AjaxView.  AjaxView is running in a console window.
  3. Enter the URL.  Type http://www.udooz.net/blog.

Injected Instrumentation

You can do whatever you want in the site to profile the event you want to capture.  You can see the instrumented code based on the performance policy injected into the blog site code.  AjaxView injects necessary code for performing profiling, logging an send it to AjaxView at the head of the page.

<head profile=”http://gmpg.org/xfn/11″>
  <script>
      var PageLoadStart = new Date().getTime();
      // other var declarations
      var emk_OkToSendNextLog = true;
      var verbose = false;

      function emk_CheckLogs() {
          if( emk_LogRecords.length >= emk_MAX_LOG_RECORDS_BEFORE_FLUSH ) {
              emk_FlushLogs();
          }
      }
      function emk_FlushLogs() {
          // implementation
      }
      // other functions
</script>
</head>
<!– actual page code –>

Whereever required, it injects the profile code like the following

(tmpCache_emk_LogRecords.push(‘\r\nLM:PerformancePolicy:PerformancePolicy:SCRIPTENTER,’),
tmpCache_emk_LogRecords.push(new Date().getTime()),

During the loading and other execution of your web application, the above profile codes send the log details back to AjaxView using XMLHttpRequest.  See the following figure.

AjaxView Console

AjaxView Console

Getting the Results

Enough logging, now let us see the analyzed results of the logs by opening new tab in FireFox and type http://fakeurl.com/?&AJAXVIEWREQUEST=GET=main.html.  This is a fake URL for getting analyzed reports from AjaxView proxy.  A two column page will appear.  The left side contains the following links:

  • JS Performance Statistics
  • Proxy Statistics
  • LM Policies
  • Clear Statistics

Our focus in on JS Performance Statistics.

JS Performance Statistics

When clicking on JS Performance Statistics link, JavaScript related performance statistics will appear on the right side.  The result is in a three column tabular, with following items:

  • Site – Actual pages where JavaScript code find
  • Num Functions – The number of JavaScript functions in the page.
  • Worst Performance (ms) – Performance of the slowest function in the page.

In my blog web site, http://fakeurl.com//PerformancePolicy/PerformancePolicy/1646706643?&AJAXVIEWREQUEST=LMINFO shows slowest performance of 164 milliseconds.  By clicking the file displays another tabular results which contains number of JavaScript functions in the selected page.  Meantime (ms) for the function at http://udooz.net/blog/wp-includes/js/jquery/jquery.js?ver=1.2.6 actually shows lowest performance function with line and column details.  Here, it is 164 millisecond.  By clicking this shows the actual code.

Comparison with IE Development ToolBar Profiler

Let us verify the results with IE Development ToolBar’s JavaScript profiler.  The profiler shows the same set of functions with correct count details also.  But it varies in the time.  The highest maximum time was 109.38 taken by three functions.

Tags Tags: , , ,
Categories: JavaScript
Posted By: udooz
Last Edit: 30 Mar 2009 @ 12 09 AM

EmailPermalinkComments (0)
Problem
Monitor and control the client side behavior of a web application without modifying the current implementation normally in the case of production stage.

Forces

  • Finding client side performance of a web application in the production environment.
  • Making changes or adding instrumentation on client side code at production stage is dangerous.
  • HTTP profiling tools do not provide rendering time details.
  • Make the web application behavior uniform across different execution environments like IE 6, IE8, FireFox, Chrome, etc, since Array.sort() consumes processor utilization in IE than other browsers and Array.join() takes very less in IE than others.

SolutionWe are doing performance engineering of our web based product and now we are more concentrated on client side performance improvements.  With the help of available toolset like Fiddler, IE Development Toolbar and some others, it is possible to tweak the code points based on download time and size of the critical ASPX pages.  In addition to this, We would like to know the browser rendering or loading time of a behavior, however none of the tools do not provide such clarity.  IE Development Toolbar enables to profile JavaScript but in an ad-hoc manner. I was googled various places, and failed to get such tool.  I finished my journey at Microsoft Research where I found a tool called “AjaxView”, which enables to inject instrumentation code  such as performance profiling, infinite loop detection, etc on the fly even in the production environment by the following nature of web applications:

  • Easy and instant deployment
  • Dynamic extension (you can add any stuff on the response of a web request)

Thanks to Emre Kiciman and Benjamin Livshits at Microsoft Research for implementing this great tool.

How Does It Works

AjaxView sits between the web server and clients, acts as server-side proxy.  It intercepts and rewrites the JavaScript code generated from the web server for a web request by a client.  It does not affect the production (or development) environment.  See the following figure.

AjaxView Platform

AjaxView Platform

 The instrumented code is sent to the client browser and the instrumentations results are sent back as logs to the proxy by the adaptive and distributed instrumentation.  These log results are then analyzed and based on the instrumentation policies, the tool generates reports.  There are four components in AjaxView platform does this instrumentation.  See the following figure.  This image was taken from Kiciman and Wang’s Live Monitoring: Using Adaptive Instrumentation and Analysis to Debug and MaintainWeb Applications white paper at Microsoft Research.
AjaxView Components

AjaxView Components

 
These components are designed to achive the following based on the adaptive instrumentation approach:
  • A component (Transformer) which automatically rewrites the actual code to serve differently instrumented versions.
  • One or more components (Controller and Log Collector) which should continuously observe the end-to-end application behavior on the client side.
  • The observed results are then analysed and used to guide the adaptation of the dynamic instrumentation policy (Dynamic Extension Generator).

AjaxView supports the following broad categories of instrumentation policies:

  • Performance
  • Runtime analysis and debugging
  • Usability evaulation

Let us see a practical walk-through on the next post for better understanding of this tool.

References

Tags Tags: , , , , ,
Categories: JavaScript
Posted By: udooz
Last Edit: 29 Mar 2009 @ 11 01 PM

EmailPermalinkComments (1)
\/ More Options ...
Change Theme...
  • Users » 1
  • Posts/Pages » 54
  • Comments » 39
Change Theme...
  • VoidVoid « Default
  • LifeLife
  • EarthEarth
  • WindWind
  • WaterWater
  • FireFire
  • LightLight