Building AJAX-enabled Composite applications in SharePoint

possumneckvegetableSoftware and s/w Development

Jul 4, 2012 (4 years and 11 months ago)

478 views



Building AJAX-Enabled Killer Composite
Applications in SharePoint


Rakesh Gupta
Portal Solutions Practice





Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 

 

Table of Contents 
Summary: ...................................................................................................................................................... 1 
Introduction: ............................................................................................................................................. 1 
Design: .......................................................................................................................................................... 1 
Architecture: ................................................................................................................................................. 3 
User initiated Webpart to server communication on client side: ............................................................ 4 
Adding ASP.NET AJAX 1.0 to SharePoint web.config files:.................................................................... 5 
Adding  ScriptManager into a SharePoint MasterPage ........................................................................ 9 
Using UpdatePanels within SharePoint ................................................................................................ 9 
Webpart to webpart communication on client side: .............................................................................. 10 
Client Event driven Webpart to server communication on client side: .................................................. 11 
Code: ........................................................................................................................................................... 12 
Listener_PPC Web Part: .......................................................................................................................... 12 
Master_PPC Web Part: ........................................................................................................................... 14 
PPC_CustomEventHandler.js .................................................................................................................. 15 
 


Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
1  
 

Summary:   
A composite application is a software system that “mashes up” features, functionality, processes, and
data from different systems all into one user interface. This article provides a strategy to build rich
Asynchronous JavaScript and XML (AJAX)-enabled composite applications, with inter-connected web
parts, in portals like SharePoint. This strategy can also be applied to any other portal products, such as
BEA AquaLogic or homegrown .Net2.0 portals.

Introduction: 
Wikipedia describes composite application as follows:
In computing, the term composite application expresses a perspective of software
engineering that defines an application built by combining multiple services. A composite
application consists of functionality drawn from several different sources within service
oriented architecture (SOA). The components may be individual web services, selected
functions from within other applications, or entire systems whose outputs have been
packaged as web services (often legacy systems).
Most portals products in the market, like SharePoint, provide an ability to build web parts (variously called
portlets, widgets, or gadgets). Each of these web parts can be connected to different systems/sources.
Two or more such web parts drawing data from different sources when hosted on one page of the portal
provide a user with single interface to monitor multiple underlying applications. Composite applications
built with Web parts take it one step further by allowing each of the single-page hosted web parts to fetch
data for a common query. As an example, if we are building a composite case management solution and
if the underlying web parts need to draw data from multiple sources such as Documentum, a relational
SQL database, eRoom, or CRM, we probably would want each of the corresponding web parts to retrieve
data for a particular case (be it by name, description, or specific case number), and we probably would
want to enter the case details that we are searching for in one place as opposed to entering it multiple
times in each of the web parts separately and let the corresponding web parts get their relevant content.
In other words, we would want the web parts to be connected to our master case search web part. To
make this composite application a killer application, we would need to add AJAX to the composite
application modules.
Design: 
The screenshot in Exhibit 1 below shows an example of an AJAX-enabled killer composite case
management application. On the left there is a master “Case Search” web part, which provides a Google-
like search for finding and locating a particular case. The user types a case number or some description
of the case and hits the search button. In the screenshot below, the user is searching for any case that
has the word “Costco” in its name or description. The user browses the search results and locates the
case in which he/she is interested. When the user clicks the case from the search result, a custom event
is raised and all the other web parts listening to the custom event fetch data for the selected case
from

Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
2  
 
their corresponding data source. The table in Exhibit 2 below lists the web parts shown in Exhibit 1 and
the source system to which they connect.
 
Exhibit 1.  [Composite Case Management Application] 


Web Part Name
Source System
Case Docket SQL database 1
Case Participants SQL database 2
Case Documents Documentum
Related Documents eRoom
Abbreviations Home Grown
Repository
Exhibit 2. [Composite Case Management source systems]


In the process of searching, locating the case, and seeing relevant data in each of the other web parts,
the entire page is never refreshed, but only the web parts are regenerated with the relevant content,
providing a much richer experience.




Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
3  
 
Architecture:  
The request response pipe for the design depicted in Exhibits 1 and 2 involves architecting three
communication components:
1. User-initiated Web part to server communication on client side.
2. Web part to web part communication on client side.
3. Client Event-driven Web part to server communication on client side.
These are depicted in Exhibit 3:

Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
4  
 
 
Exhibit 3. Composite Application Communication Components

The rest of the section describes how to build these three components.
User initiated Web part to server communication on client side: 
This can be achieved by applying the ASP.NET AJAX framework.
• First, you will need to download and install ASP.NET AJAX on SharePoint servers in your farm.
(The download can be found at http://asp.net/ajax/downloads/
.
)

Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
5  
 
• Second, you need to add (wire) asp.net Ajax to the SharePoint web.config file to enable the
ASP.NET AJAX technology. You need to extend web.config with some settings (see next
section, titled “Adding ASP.NET AJAX 1.0 to SharePoint web.config files”).
• Third, you will need to add the ASP.NET AJAX Script Manager into your master page to enable
scenarios such as Extenders or UpdatePanels.

Adding ASP.NET AJAX 1.0 to SharePoint web.config files: 
Extending SharePoint web.config files with ASP.NET AJAX requires that you interleave some AJAX
registration entries in-line with WSS registration entries. To do this you will need to edit your SharePoint
web.config file and the following seven entries to your web.config file typically located in a directory such
as c:\inetpub\wwwroot\wss\virtualdirectories\80.

1. Add a <sectionGroup> element to the <configSections> tag:
<configSections>
<!-- Rakesh: -->
<sectionGroup name="system.web.extensions"
type="System.Web.Configuration.SystemWebExtensionsSectionGroup,
&#xD;&#xA; System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, &#xD;&#xA; PublicKeyToken=31bf3856ad364e35">

<sectionGroup name="scripting"
type="System.Web.Configuration.ScriptingSectionGroup, &#xD;&#xA;
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral,
&#xD;&#xA; PublicKeyToken=31bf3856ad364e35">

<section name="scriptResourceHandler"
type="System.Web.Configuration.ScriptingScriptResourceHandlerSect
ion, &#xD;&#xA; System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, &#xD;&#xA; PublicKeyToken=31bf3856ad364e35"
requirePermission="false" allowDefinition="MachineToApplication"
/>

<sectionGroup name="webServices"
type="System.Web.Configuration.ScriptingWebServicesSectionGroup
, &#xD;&#xA; System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, &#xD;&#xA;
PublicKeyToken=31bf3856ad364e35">

<section name="jsonSerialization"
type="System.Web.Configuration.ScriptingJsonSerializationSect
ion, &#xD;&#xA; System.Web.Extensions,
Version=1.0.61025.0, Culture=neutral, &#xD;&#xA;
PublicKeyToken=31bf3856ad364e35" requirePermission="false"
allowDefinition="Everywhere" />

<section name="profileService"
type="System.Web.Configuration.ScriptingProfileServiceSection
, &#xD;&#xA; System.Web.Extensions, Version=1.0.61025.0,

Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
6  
 
Culture=neutral, &#xD;&#xA;
PublicKeyToken=31bf3856ad364e35" requirePermission="false"
allowDefinition="MachineToApplication" />

<section name="authenticationService"
type="System.Web.Configuration.ScriptingAuthenticationService
Section,&#xD;&#xA; System.Web.Extensions,
Version=1.0.61025.0, Culture=neutral, &#xD;&#xA;
PublicKeyToken=31bf3856ad364e35" requirePermission="false"
allowDefinition="MachineToApplication" />
</sectionGroup>
</sectionGroup>
</sectionGroup>
<!-- End Rakesh -->
</configSections>

2. Add a <controls> section as a child of the <system.web>/<pages> tag.
<pages>
<!-- Rakesh: -->
<controls>
<add tagPrefix="asp" namespace="System.Web.UI"
assembly="System.Web.Extensions, Version=1.0.61025.0,
&#xD;&#xA; Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</controls>
<!-- End Rakesh: -->
</pages>

3. Add the following tag to the <assemblies> tag, within <compilation>:
<assemblies>
<!-- Rakesh: -->
<add assembly="System.Web.Extensions, Version=1.0.61025.0,
&#xD;&#xA; Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/>
<!-- End Rakesh: -->
</assemblies>

4. Add some new registrations to the end of the <httpHandlers> section:
<httpHandlers>
<!-- Rakesh: -->
<add verb="*" path="*.asmx" validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory, &#xD;&#xA;

Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
7  
 
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral,
&#xD;&#xA; PublicKeyToken=31bf3856ad364e35" />
<add verb="*" path="*_AppService.axd" validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory, &#xD;&#xA;
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral,
&#xD;&#xA; PublicKeyToken=31bf3856ad364e35" />

<add verb="GET,HEAD" path="ScriptResource.axd"
type="System.Web.Handlers.ScriptResourceHandler, &#xD;&#xA;
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral,
&#xD;&#xA; PublicKeyToken=31bf3856ad364e35" validate="false" />
<!-- End Rakesh: -->
</httpHandlers>

5. Add a new registration to the HttpModules section, beneath any existing registrations.
<httpModules>
<!-- Rakesh: -->
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule,
&#xD;&#xA; System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, &#xD;&#xA; PublicKeyToken=31bf3856ad364e35"
/>
<!-- End Rakesh: -->
</httpModules>

6. Add a SafeControl entry for the System.Web.UI namespace from Microsoft Ajax Extensions, within the
<SharePoint>/<SafeControls>section:
<SafeControls>
<!-- Rakesh: -->
<SafeControl Assembly="System.Web.Extensions, Version=1.0.61025.0,
&#xD;&#xA; Culture=neutral, PublicKeyToken=31bf3856ad364e35"
Namespace="System.Web.UI" TypeName="*" Safe="True" />
<!-- End Rakesh: -->
</SafeControls>

7. Finally, add the following configuration tags at the bottom of web.config, near the bottom before the
end <configuration> tag.
<!-- Rakesh: -->
<system.web.extensions>
<scripting>
<webServices>
<!-- Uncomment this line to enable the authentication service.
Include requireSSL="true" if appropriate. -->
<!--
<authenticationService enabled="true" requireSSL =
"true|false"/>

Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
8  
 
-->
<!-- Uncomment these lines to enable the profile service.
To allow profile properties to be retrieved and
modified in ASP.NET AJAX applications,
you need to add each property name to the
readAccessProperties
and writeAccessProperties attributes. -->
<!--
<profileService enabled="true"
readAccessProperties="propertyname1,propertyname2"
writeAccessProperties="propertyname1,propertyname2"/>
-->
</webServices>
<!--
<scriptResourceHandler enableCompression="true"
enableCaching="true" />
-->
</scripting>
</system.web.extensions>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules>
<add name="ScriptModule"
preCondition="integratedMode"
type="System.Web.Handlers.ScriptModule,
System.Web.Extensions, &#xD;&#xA;
Version=1.0.61025.0, Culture=neutral, &#xD;&#xA;
PublicKeyToken=31bf3856ad364e35" />
</modules>
<handlers>
<remove name="WebServiceHandlerFactory-Integrated" />
<add name="ScriptHandlerFactory" verb="*" path="*.asmx"
preCondition="integratedMode"
type="System.Web.Script.Services.ScriptHandlerFactory,
&#xD;&#xA; System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, &#xD;&#xA;
PublicKeyToken=31bf3856ad364e35" />

<add name="ScriptHandlerFactoryAppServices" verb="*"
path="*_AppService.axd" preCondition="integratedMode"
type="System.Web.Script.Services.ScriptHandlerFactory,
&#xD;&#xA; System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, &#xD;&#xA;
PublicKeyToken=31bf3856ad364e35" />

<add name="ScriptResource" preCondition="integratedMode"
verb="GET,HEAD" path="ScriptResource.axd"
type="System.Web.Handlers.ScriptResourceHandler, &#xD;&#xA;
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral,
&#xD;&#xA; PublicKeyToken=31bf3856ad364e35" />
</handlers>
</system.webServer>
<!-- End Rakesh: -->


Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
9  
 

Adding  ScriptManager into a SharePoint MasterPage

Most components of ASP.NET AJAX (including UpdatePanel) require the inclusion of a .NET
ScriptManager control within a page.
Although it may be possible to dynamically insert a script manager from within a control, in most cases
the control may not be able to insert the script manager early enough in the page lifecycle, depending on
how the control is used, making this tricky to get right. Also, the control implementer will need to ensure
that multiple instances of the control (or other controls) do not result in the addition of multiple script
managers within the page. For these reasons, dynamic insertion of a ScriptManager control from another
control is not recommended.
To statically embed a script manager into a page, it is recommended that you add the ScriptManager into
the master page of a site.
The easiest way to do this is to first open up the master page for your site. Typically, this is be located at
<site url>/_catalogs/masterpage. Then edit this file by opening it in an editor such as Microsoft
SharePoint Designer, or directly in Notepad by opening your master page library via DAV (typically
\\server\<pathtosite>\_catalogs\masterpage).
Add the following into the markup of your page. A recommended location is right beneath the
WebPartManager registration (search for <WebPartPages:SPWebPartManager id="m"
runat="Server" />):
<!-- Rakesh: -->
<asp:ScriptManager runat="server" ID="ScriptManager1">
</asp:ScriptManager>
<!-- End Rakesh: -->

Using UpdatePanels within SharePoint

UpdatePanels are a very useful addition to ASP.NET AJAX, and represent the simplest way to convert
existing, standard ASP.NET controls and parts to take advantage of Ajax techniques. However, there are
some changes within Windows SharePoint Services which may get in the way of working with ASP.NET
AJAX.

Windows SharePoint Services JavaScript has a “form onSubmit wrapper” which is used to override the
default form action. This work is put in place to ensure that certain types of URLs, which may contain
double byte characters, will fully work across most postback and asynchronous callback scenarios.
However, if your scenarios do not involve double byte character URLs, you may successful disable this
workaround and gain the ability to use ASP.NET AJAX UpdatePanels.

To do this, you may need to register a client startup script which disables this workaround. You can do so
by adding the following lines of code in the Page_Load event of your .aspx page:

Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
10  
 
ScriptManager.RegisterStartupScript(this, typeof(Listener_PPC),
"UpdatePanelFixup", "_spOriginalFormAction = document.forms[0].action;
_spSuppressFormOnSubmitWrapper=true;", true);
In the code shown in the later section this is done in ”EnsureUpdatePanelFixups()” method called
from the main method called “CreateChildControls()”
Webpart to webpart communication on the client side: 
An important feature of the Master-Child or Broadcaster-Listener model of communication is being able to
do so on the client side. A javascript file file called “PPC_CustomEventHandler.js”, provided at the end of
this paper, contains all the code necessary to handle this. This javascript library should be loaded on all
the pages where webpart-webpart communication is sought on client side. The easiest way to do so is by
adding the reference to this file in the Master page in the <HEAD section, as shown below. (Make sure
the java script file exists at the mapped physical path before you add the following reference in master
page.)

<HEAD runat="server">
<META Name="GENERATOR" Content="Microsoft SharePoint">
<META Name="progid" Content="SharePoint.WebPartPage.Document">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
<META HTTP-EQUIV="Expires" content="0">
<SharePoint:RobotsMetaTag runat="server"/>
<Title ID=onetidTitle><asp:ContentPlaceHolder id=PlaceHolderPageTitle
runat="server"/></Title>
<SharePoint:CssLink runat="server"/>
<SharePoint:Theme runat="server"/>
<SharePoint:ScriptLink language="javascript" name="core.js"
Defer="true" runat="server" />
<SharePoint:CustomJSUrl runat="server" />
<SharePoint:SoapDiscoveryLink runat="server" />
<asp:ContentPlaceHolder id="PlaceHolderAdditionalPageHead"
runat="server"/>
<SharePoint:DelegateControl runat="server"
ControlId="AdditionalPageHead" AllowMultipleControls="true"/>
<!-- Rakesh: -->
<script
src="/_layouts/images/customJS/PPC_CustomEventHandler.js"></script>
<!-- End Rakesh: -->
</HEAD>

Before calling an event in a Master Web Part it is a good practice to check if the .js has been loaded. You
can do so by calling if(document.ppc_CustomClientCommunication)
An event from Master Web Part can be raised by calling
document.ppc_CustomClientCommunication.RaiseEvent This RaiseEvent expects three
parameters: Unique Namespace, Name of the custom event, and Parameter to be passed to the listener.
You can pass an empty parameter or serialize multiple values using a delimiter like ”_”, but the parameter

Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
11  
 
being passed is expected to be a string. Following is an example of how a “NameClicked” custom event is
raised from Master_PPC Web Part:
document.ppc_CustomClientCommunication.RaiseEvent('urn:schemas.ppc.com:Test',
'NameClicked', strUserID);
Once the above event is raised, all the other web parts on the page registered for the event can listen to it
and respond as defined in their code. A Listener Web Part can register for the custom event by calling
document.ppc_CustomClientCommunication.RegisterForEvent. The RegisterEvent call
expects three parameters: Unique Namespace, Name of the custom event, and Name of the function to
be called when the event occurs. The function name should expexct a string parameter. Following is an
example of how a “NameClicked” custom event is registered from Listener_PPC Web Part:
document.ppc_CustomClientCommunication.RegisterForEvent('urn:schemas.ppc.com:
Test', 'NameClicked', RakeshCustomBtnClickScript);
The function definition being called “RakeshCustomBtnClickScript” should resemble the following:
function RakeshCustomBtnClickScript(strUserID){}
Whatever code is defined in this function would be executed as soon as the 'NameClicked' event is
raised in the Master Web Part.

Client Event‐driven Web part to server communication on the client side:  
The idea behind an event-driven web part to server communication is to have multiple stand-alone web
part codes respond to an event raised by the master web part. Please note that in Master-Child
communication, any web part can act as Master if it raises an event and any other web part listening for
the same event becomes child. The key is to have the child or listener web part respond to the event and
rengenerate response from its server. To do so, __doPostBack should be called or the submit button on
the listener form should be clicked without any interaction. In the following screen shot, the Listener_PPC
web part label is updated with the userid of the user clicked in the Master_PPC Web Part data grid.
Continuing with our Master_PPC and Listener_PPC web parts, when the 'NameClicked' event is
raised, RakeshCustomBtnClickScript() is called in the Listener webpart. The function populates a
text box and calls submit button click which posts the listener form to itself.
document.ppc_CustomClientCommunication.RegisterForEvent('urn:schemas.ppc.com:
Test', 'NameClicked', RakeshCustomBtnClickScript);

function RakeshCustomBtnClickScript(strUserID){
document.forms[0].elements['myTextBox'].value = strUserID ;
cntrlMyButton.click();
}

Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
12  
 
Code: 
The screen shot in Exhibit 4 shows a simple Master_PPC Web Part that lists a datagrid of links that,
when clicked, raises a client side custom event called “NameClicked”. Any other web part on the same
page can register and listen for this custom event. In our screen shot below we have Listener_PPC Web
Part , registered to the “NameClicked” event. As such , when a user clicks “Dale Tuttle” in the Master
Web Part data grid, the custom event “NameClicked” is raised. This is listened to by Listener Web Part,
which then auto-refreshes itself, and the ASP.Net Label control is updated with the userid of the name
clicked (in this case, “dtuttle”). During this message transfer , the entire page is never refreshed,
communication between two (or more) web parts takes place at the client side, and, using AJAX in
UpdatePanel, the Listener Web Part is auto-refreshed.
 
Exhibit 3. Master – Listener Web Parts 

This script may be directly embedded in the page or could be emitted by a control that uses the
UpdatePanel. The following is an example of a very simple ASP.NET Web Part called Listener_PPC
WEB Part (shown in the above diagram), which uses UpdatePanel capabilities:
[Please contact Rakesh Gupta rgupta@ppc
for sample code]
Listener_PPC Web Part: 
WebControls;
namespace Listener
{
[Guid("0bf90c5a-42ba-43ac-911f-ffc4cec349ae")]
public class Listener_PPC : System.Web.UI.WebControls.WebParts.WebPart
{




// ASP.NET AJAX Controls declaration
protected UpdatePanel udatePanel;
protected UpdateProgress updateProgress;

protected System.Web.UI.HtmlControls.HtmlInputHidden txtUserID;

protected override void CreateChildControls()
{

base.CreateChildControls();

Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
13  
 

// Fix Form Action
this.EnsureUpdatePanelFixups();

udatePanel = new UpdatePanel();
updateProgress = new UpdateProgress();

udatePanel.ID = "_UpdatePanel";
updateProgress.ID = "_UpdateProgress";

//Create Update Progress Template
string templateHTML = "<div><img alt=\"Loading...\"
src=\"/_layouts/images/loader.gif\"/>Loading...</div>";

updateProgress.ProgressTemplate = new
ProgressTemplate(templateHTML);

updateProgress.AssociatedUpdatePanelID = udatePanel.ClientID;

udatePanel.UpdateMode = UpdatePanelUpdateMode.Conditional;

this.Controls.Add(udatePanel);

this.label = new Label();

this.label.Text = "Enter 1st Number: ";

//Adding Controls
udatePanel.ContentTemplateContainer.Controls.Add(this.label);




}

//Fixing Form Action
private void EnsureUpdatePanelFixups()
{
if (this.Page.Form != null)
{
string formOnSubmitAtt =
this.Page.Form.Attributes["onsubmit"];
if (formOnSubmitAtt == "return _spFormOnSubmitWrapper();")
{
this.Page.Form.Attributes["onsubmit"] =
"_spFormOnSubmitWrapper();";
}
}
ScriptManager.RegisterStartupScript(this, typeof(Listener_PPC),
"UpdatePanelFixup", "_spOriginalFormAction = document.forms[0].action;
_spSuppressFormOnSubmitWrapper=true;", true);
}
}
//Class for Building progress tempales
public class ProgressTemplate : ITemplate

Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
14  
 
{
private string template;

public ProgressTemplate(string temp)
{
template = temp;
}

public void InstantiateIn(Control container)
{
LiteralControl ltr = new LiteralControl(this.template);
container.Controls.Add(ltr);
}
}


}

Master_PPC Web Part: 

namespace Master
{
[Guid("dcd2087b-4a48-4423-9a63-57abae1e3ee5")]
public class Master_PPC : System.Web.UI.WebControls.WebParts.WebPart
{
public Master_PPC()
{
this.ExportMode = WebPartExportMode.All;
}
DataGrid dg;
DataTable _table;
/* protected override void Render(HtmlTextWriter writer)
{
// TODO: add custom rendering code here.
// writer.Write("Output HTML");
}*/
protected override void CreateChildControls()
{
base.CreateChildControls();
dg = new DataGrid();
PopulateCustomDataGrid();
this.Controls.Add(dg);

string strRakeshCustomRaiseEventScript = "";

strRakeshCustomRaiseEventScript += "function
RaiseCustomPPCEvent_1(strUserID) \n";
strRakeshCustomRaiseEventScript += "{ \n" ;
strRakeshCustomRaiseEventScript +=
"if(document.ppc_CustomClientCommunication) \n" ;
strRakeshCustomRaiseEventScript += "{ \n" ;

Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
15  
 
strRakeshCustomRaiseEventScript +=
"document.ppc_CustomClientCommunication.RaiseEvent('urn:schemas.ppc.com:Test'
, 'NameClicked', strUserID); \n" ;
strRakeshCustomRaiseEventScript += "} \n" ;
strRakeshCustomRaiseEventScript += "} \n" ;
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
"RakeshCustomRaiseEventScript", strRakeshCustomRaiseEventScript, true);
}
protected void PopulateCustomDataGrid()
{
_table = new DataTable();

DataColumn col = new DataColumn();
col.DataType = typeof(string);
col.ColumnName = "Name";
_table.Columns.Add(col);

col = new DataColumn();
col.DataType = typeof(string);
col.ColumnName = "Address";
_table.Columns.Add(col);

col = new DataColumn();
col.DataType = typeof(int);
col.ColumnName = "ZIP Code";
_table.Columns.Add(col);

DataRow row = _table.NewRow();
string strAnchor = "<a href='#'
onclick='javascript:RaiseCustomPPCEvent_1(\"rgupta\");'> Rakesh Gupta </a>" ;
row["Name"] = strAnchor;
row["Address"] = "123 Main Street";
row["ZIP Code"] = 98000;
_table.Rows.Add(row);

row = _table.NewRow();
strAnchor = "<a href='#'
onclick='javascript:RaiseCustomPPCEvent_1(\"dtuttle\");'> Dale Tuttle </a>";
row["Name"] = strAnchor;
row["Address"] = "1760 Old Meadow Road";
row["ZIP Code"] = 22033;
_table.Rows.Add(row);

dg.DataSource = _table;
dg.DataBind();
}
}
}


PPC_CustomEventHandler.js 
Please contact Rakesh Gupta rgupta@ppc.com
for complete sample code.

Building AJAX-Enabled Killer Composite Applications
in SharePoint

    September 20, 2007   
 
16  
 

About the Author:
Mr. Gupta is the Practice Lead for Project Performance Corporation’s (PPC) Enterprise Portal Solutions
practice and is PPC’s Senior Portal/SOA architect. He has over 10 years of hands on experience in
leading and architecting enterprise portal deployments, application development, database design and
SOA implementation. Mr. Gupta is also responsible for leading the best practices and code
standardization efforts in PPC. He is a certified BEA AquaLogic (previously called Plumtree) Instructor
and has authored popular white paper called “Portlet Development Best Practices
” which discusses
various considerations to be taken when designing a portlet/web part to take best advantages of the
portal architecture. As a strategist Mr. Gupta is frequently called upon to design “to be architecture”,
compare various Portal/SOA tools and discuss implementation strategies.