Integrating ASP.NET Ajax WebPart with SharePoint 3.0
 
Published: 25 Aug 2008
Abstract
In this article, Abdulla examines the creation of a custom Ajax WebPart from scratch and the deployment of it into SharePoint Server 3.0. He illustrates how to add a script manager tag inside SharePoint page dynamically and how you can deal with the UpdatePanel and UpdateProgress controls programmatically. Finally, he shows how to add the newly created Ajax WebPart into SharePoint Page. Abdulla examines the relevant steps with the help of the source code and related screenshots, and he also provides the complete Visual Studio project files.
by Abdulla Hussein AbdelHaq
Feedback
Average Rating: 
Views (Total / Last 10 Days): 61014/ 107

Introduction

In this article I am going to show you how to integrate ASP.NET Ajax 1.0 with SharePoint 3.0. We will create a new Ajax WebPart from scratch and then we will deploy it into SharePoint 3.0 site. Moreover, I will demonstrate how to add that webpart into SharePoint Page.

Building Webpart DLL Project

To create a web part class, open your visual studio, create a new Class Library Project and name it as "TestAbdelHaqWebpart." Then add a new class and name it "MyAjaxWebPart."

First of all, you have to add some references to the project which are listed below:

·         System.Web

·         System.Web.Extensions

·         System.Web.Extensions.Design

In addition, you need to inherit the WebPart class.

Take a look at listing 1; it is our Ajax WebPart class.

Listing 1

Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Data
Imports System.Data.SqlClient
 
Public Class MyAjaxWebPart
    Inherits WebPart
 
    Private _grdSearch As GridView
    Private _txtSearch As TextBox
    Private _btnSearch As Button
    Private _lblMsg As Label
    Private _updatePanel As UpdatePanel
    Private _updateProgress As UpdateProgress
    Private Shared ReadOnly EventSubmitKey As New Object()
    Public NewAjaxWebPart12()
 
    Public Sub New()
        Me.ExportMode = WebPartExportMode.All
    End Sub
 
    <WebBrowsable(True), _
        Personalizable(PersonalizationScope.Shared), _
        Category("AbdHaq Property") _
        > _
        Public Property LoadingImageURL() As String
        Get
            Dim _obj As Object = ViewState("LoadingImageURL")
            If _obj Is Nothing Then
                Return String.Empty
            Else
                Return DirectCast(ViewState("LoadingImageURL"), String)
            End If
 
        End Get
        Set(ByVal value As String)
            ViewState("LoadingImageURL"= value
        End Set
    End Property
    Public Custom Event Submit As EventHandler
        AddHandler(ByVal value As EventHandler)
            Events.AddHandler(EventSubmitKey, value)
        End AddHandler
        RemoveHandler(ByVal value As EventHandler)
            Events.RemoveHandler(EventSubmitKey, value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, _
            ByVal e As System.EventArgs)
            CType(Events(EventSubmitKey), _
                EventHandler).Invoke(sender, e)
        End RaiseEvent
    End Event
 
    Private Sub _btnSearch_Click(ByVal source As ObjectByVal e As EventArgs)
 
        _grdSearch.Visible = False
 
        System.Threading.Thread.Sleep(1500)
 
        '//Create DataTable Structure
        Dim Dtable = New DataTable("tmpTable")
        '//User_ID Col
        Dtable.Columns.Add("User_ID", GetType(Integer))
        Dtable.Columns("User_ID").AutoIncrement = True
        Dtable.Columns("User_ID").AutoIncrementSeed = 1
        '//User_Name Col
        Dtable.Columns.Add("User_Name", GetType(String))
        '//User_Department Col
        Dtable.Columns.Add("User_Department"GetType(String))
 
 
        Dim dr As DataRow
 
        dr = Dtable.NewRow
        dr("User_Name"= "Abdulla Abdelhaq"
        dr("User_Department"= "Technical"
        Dtable.Rows.Add(dr)
 
        dr = Dtable.NewRow
        dr("User_Name"= "Noura Ahmad"
        dr("User_Department"= "Technical"
        Dtable.Rows.Add(dr)
 
        dr = Dtable.NewRow
        dr("User_Name"= "Oday Mohammad"
        dr("User_Department"= "Production"
        Dtable.Rows.Add(dr)
 
        Dim _searchFor As String = "%"
 
        If _txtSearch.Text <> String.Empty Then
            _searchFor = _txtSearch.Text
        End If
 
        Dim dtView As New DataView(Dtable)
        dtView.RowFilter = "User_Name LIKE '%'+'" & _searchFor & "'+'%'"
 
        If dtView.Count > 0 Then
            _grdSearch.Visible = True
            _grdSearch.AutoGenerateColumns = True
            _grdSearch.DataSource = dtView
            _grdSearch.DataBind()
            _lblMsg.Text = String.Empty
        Else
            _lblMsg.Text = "<font color='red'>Sorry, No Data Found!.</font>"
            _grdSearch.Visible = False
        End If
 
    End Sub
 
    Protected Overrides Sub CreateChildControls()
        Controls.Clear()
 
        _updatePanel = New UpdatePanel
        With _updatePanel
            .ID = "UpdatePanel1"
            .ChildrenAsTriggers = True
            .UpdateMode = UpdatePanelUpdateMode.Conditional
 
        End With
 
        _updateProgress = New UpdateProgress
        _updateProgress.ID = "UpdateProgress1"
 
        Dim _templateHTML As String
        If LoadingImageURL = String.Empty Then
            _templateHTML = "<span>Loading ...</span>"
        Else
            _templateHTML = "<div><img alt='Loading...' src='" & _
              LoadingImageURL.Trim & "'/></div>"
        End If
 
        _updateProgress.ProgressTemplate = New ProgressTemplate(_templateHTML)
 
        _updateProgress.AssociatedUpdatePanelID = _updatePanel.ClientID
 
        Me.Controls.Add(_updatePanel)
 
        _grdSearch = New GridView
        _grdSearch.ID = "GrdSearch"
 
        _txtSearch = New TextBox
        _txtSearch.ID = "txtSearch"
 
        _btnSearch = New Button
        _btnSearch.Text = "Search"
        _btnSearch.ID = "BtnSearch"
 
        _lblMsg = New Label
        _lblMsg.ID = "lblMsgError"
 
        AddHandler _btnSearch.Click, AddressOf _btnSearch_Click
 
        _updatePanel.ContentTemplateContainer.Controls.Add(_txtSearch)
        _updatePanel.ContentTemplateContainer.Controls.Add(_btnSearch)
        _updatePanel.ContentTemplateContainer.Controls.Add(_grdSearch)
        _updatePanel.ContentTemplateContainer.Controls.Add(_lblMsg)
        _updatePanel.ContentTemplateContainer.Controls.Add(_updateProgress)
 
    End Sub
 
    Protected Overrides Sub OnInit(ByVal e As EventArgs)
 
        MyBase.OnInit(e)
 
        'get the existing ScriptManager if it exists on the page
        Dim _AjaxManager As ScriptManager = ScriptManager.GetCurrent(Me.Page)
        If _AjaxManager Is Nothing Then
 
            'create new ScriptManager and EnablePartialRendering
            _AjaxManager = New ScriptManager()
            _AjaxManager.EnablePartialRendering = True
 
            'Fix problem with postbacks and form actions (DevDiv 55525)
            Page.ClientScript.RegisterStartupScript(Me.GetType, Me.ID, _
              "_spOriginalFormAction = document.forms[0].action;"True)
 
            'tag:"form" att:"onsubmit" val:"return _spFormOnSubmitWrapper()"
            'blocks async postbacks after the first one
            'not calling "_spFormOnSubmitWrapper()" breaks all postbacks
            'returning true all the time, somewhat defeats the purpose of the
            '_spFormOnSubmitWrapper() which is to block repetitive postbacks, 
            'but it allows MS AJAX Extensions to work properly
 
            If Not Me.Page.Form Is Nothing Then
                Dim formOnSubmitAtt As String = Me.Page.Form.Attributes("onsubmit")
                If Not String.IsNullOrEmpty(formOnSubmitAtt) And _
                  formOnSubmitAtt = "return _spFormOnSubmitWrapper();" Then
                    Me.Page.Form.Attributes("onsubmit") =_
                      "_spFormOnSubmitWrapper();"
                End If
                'add the ScriptManager as the first control in the Page.Form
                Me.Page.Form.Controls.AddAt(0, _AjaxManager)
 
            End If
        End If
 
    End Sub
 
    Protected Overrides Sub RenderContents(ByVal writer As _
      System.Web.UI.HtmlTextWriter)
        _updatePanel.RenderControl(writer)
    End Sub
End Class
'Class for Building progress tempales 
Public Class ProgressTemplate : Implements ITemplate
    Private template As String
 
    Public Sub New(ByVal temp As String)
        template = temp
    End Sub
 
    Public Sub InstantiateIn(ByVal container As Control) Implements _
      Web.UI.ITemplate.InstantiateIn
        Dim ltr As New LiteralControl(Me.template)
        container.Controls.Add(ltr)
    End Sub
 
End Class
Adding Script Manager

I have read many articles that talked about adding the Script Manager to the SharePoint manually; that you have to go to the master page of your SharePoint page, and then write a script manager tag to the HTML code manually!

Actually, I do not prefer this way. As a developer, I would like to add it dynamically by the code.

Go back to Listing 1 and take a look on OnInit subroutine. Here we will add the script manager dynamically. We are checking if there is an existing script manager on the page. If it is not, then we will create a new script manager and we will add it in the page controls.

Dealing with UpdatePanel and UpdateProgress

If you try to add controls to UpdatePanel programmatically, you will notice that the UpdatePanel requires you to add server controls only. So you need to choose the proper server control that matches your requirement after rendering time. For example, if you want to add HTML div inside the UpdatePanel, you should add the panel control instead of the HTML div element.

Since the UpdateProgress control is a template control, you have to create a template class that represents the container of the UpdateProgress controls. Listing 1 contains a public class called ProgressTemplate, I have created an instance from that class in CreateChildControls subroutine and then I have added the loading animation image inside the UpdateProgress using that instance.

To make our Ajax webpart more reusable, there is a public property called LoadingImageURL which enables you to set path of the loading animation image. So you can upload the image you want into your Sharepoint site, and then you can use it as loading image by using LoadingImageURL public property.

Deploying Webpart into SharePoint 3.0

Deploying DLL file into SharePoint bin folder

After you have built the project successfully, all you need is to get the DLL file from the bin folder of your project. We are going to deploy that DLL file into the SharePoint site; you can do that simply by copying that DLL and pasting it into the bin folder of the SharePoint site. Or you can change the build output path of the webpart project into the bin folder of the SharePoint site so that it will deploy the DLL file automatically after any build operation.

To change the build output path, use the following steps:

1. From the Solution Explorer, right click over the Solution name, and click on Properties.

2. New window will be opened, click on Compile tab, and then click on browse button in the

    Build output path.

3. Find out the bin folder of your SharePoint site, and then set it as "Build output path" for the webpart project.

Now if you rebuild the project again, it will deploy the project DLL file into the bin folder of the SharePoint site.

Adding SafeControl to the SharePoint Web.Config file

The second step in deploying webpart project into SharePoint site is to add the SafeControl of our webpart project into the SharePoint web.config file.

So you have to navigate to the following path:

C:\InetPub\wwwroot

And open your SharePoint Site folder, then you will find a web.config file in the root of the SharePoint site. Open it and add a new SafeControl element as shown in Listing 2.

Listing 2

<SafeControl Assembly="TestAbdelHaqWebPart" 
Namespace=" TestAbdelHaqWebPart" TypeName="*" />

That is it; you have deployed a webpart project into a SharePoint site.

Extending SharePoint web.config file with Ajax 1.0

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.

1. Add a <sectionGroup>element to the <configSections>tag:

Listing 3

<configSections>    
<sectionGroup name="system.web.extensions" 
type="System.Web.Configuration.SystemWebExtensionsSectionGroup, 
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35">
      <sectionGroup name="scripting" 
type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, 
Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
          <section name="scriptResourceHandler" 
type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, 
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35" requirePermission="false" 
allowDefinition="MachineToApplication"/>
        <sectionGroup name="webServices" 
type="System.Web.Configuration.ScriptingWebServicesSectionGroup, 
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35">
          <section name="jsonSerialization" 
type="System.Web.Configuration.ScriptingJsonSerializationSection, 
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35" requirePermission="false" 
allowDefinition="Everywhere" />
          <section name="profileService" 
type="System.Web.Configuration.ScriptingProfileServiceSection, 
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35" requirePermission="false" 
allowDefinition="MachineToApplication" />
          <section name="authenticationService" 
type="System.Web.Configuration.ScriptingAuthenticationServiceSection, 
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35" requirePermission="false" 
allowDefinition="MachineToApplication" />
        </sectionGroup>
      </sectionGroup>
    </sectionGroup>
</configSections>    

2. Add a <controls> section as a child of the <system.web>/<pages> tag.

Listing 4

<pages>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, 
Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</controls>
</pages>    

3. Add the following tag to the <assemblies> tag, within <compilation>.

Listing 5

<assemblies> 
<add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35"/>
</assemblies>

4. Add some new registrations to the end of the <httpHandlers> section.

Listing 6

<httpHandlers> 
      <add verb="*" path="*.asmx" validate="false" 
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, 
Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add verb="*" path="*_AppService.axd" validate="false" 
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, 
Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add verb="GET,HEAD" path="ScriptResource.axd" 
type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, 
Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
validate="false"/>
</httpHandlers> 

5. Add a new registration to the HttpModules section beneath any existing registrations.

Listing 7

<httpModules> 
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, 
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35"/>
</httpModules>

6. Add a SafeControl entry for the System.Web.UI namespace from Microsoft Ajax Extensions, within the <SharePoint>/<SafeControls>section.

Listing 8

<SafeControls> 
      <SafeControl Assembly="System.Web.Extensions, Version=1.0.61025.0, 
Culture=neutral, PublicKeyToken=31bf3856ad364e35" Namespace="System.Web.UI" 
TypeName="*" Safe="True" />
</SafeControls> 

7. Finally, add the following configuration tags at the bottom of web.config, near the bottom before the end <configuration> tag.

Listing 9

<system.web.extensions>
    <scripting>
      <webServices>
      <!-- Uncomment this line to enable the authentication service. 
Include requireSSL="true" if appropriate. -->
      <!--
        <authenticationService enabled="true" requireSSL = "true|false"/>
      -->
      <!-- 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. -->
  <p class=Code-GenericCxSpMiddle>      <!--
      <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, 
Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    </modules>
    <handlers>
      <remove name="WebServiceHandlerFactory-Integrated" />
      <add name="ScriptHandlerFactory" verb="*" path="*.asmx" 
           preCondition="integratedMode"
           type="System.Web.Script.Services.ScriptHandlerFactory, 
           System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, 
           PublicKeyToken=31bf3856ad364e35"/>
      <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" 
preCondition="integratedMode" 
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, 
Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" 
path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, 
System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35" />
    </handlers>
</system.webServer>
Adding New WebPart into SharePoint Site

To add a WebPart to the SharePoint site, you have to add it first to the SharePoint WebPart Gallery.

Adding New WebPart to the SharePoint WebPart Gallery

To do this, follow the subsequent steps.

1.    Click Site Actions tab, and select Site Settings. The Site Settings page will appear.

2.     Under gallery column, click on web parts link. This takes you to the WebPart Gallery page.

3.    Click on the New button as shown in Figure 1, it will move you to a new page that displays all WebParts that are included in the sharepoint webconfig file.

Figure 1

4.    Check your webpart project name which is "TestAbdelHaqWebPart" and then click on Populate Gallery button as illustrated in Figure 2, which adds the WebPart to the WebPart gallery so that you can add it later to the page.

Figure 2

Now let us go and add our new WebPart to the home page.

Adding WebPart to SharePoint page

To add our new WebPart to the home page, follow the subsequent steps.

1. From the home page, click on Site Actions tab and select choose Edit Page.

Figure 3

2. Click on Add a Web Part as shown in Figure 4

Figure 4

3. From the popup page, check "MyAjaxWebPart" and then click on Add button.

Figure 5

4. Click Exit Edit Mode.

And that is it; we have added our new WebPart to the home page of our SharePoint website.

Type the name that you want to search and click the search button. Notice that the Loading image will be displayed and the result will be represented inside the GridView.

So no post back, no flashing on the page, which is what we are talking about, "Ajax WebPart." It represents what is called Progress Indicator, which helps in maintaining the user's attention and communicates that the system is still alive even if a response has not yet occurred.

Figures 6 and 7 show you how Ajax WebPart works on the page.

Figure 6

Figure 7

 

Downloads

Conclusion

In this article, an overview about how to create a new Ajax WebPart and deploy it into SharePoint 3.0 site was explained. In addition, we learned how to add Script Manager Element dynamically inside SharePoint page; also I illustrated how to deal with UpdatePanel and UpdateProgress controls programmatically. And finally, we have added our new Ajax WebPart into SharePoint site.

I encourage you to download the source code so that you can learn what we have done in a more detailed manner. If you have any questions or wish to share your comments, do not hesitate to contact me.

I hope that you have found this tutorial as informative as possible.



User Comments

Title: Mr   
Name: Dinesh
Date: 2010-11-15 5:48:03 AM
Comment:
Awesome code and I feel it is the best one for understanding Ajax in Sharepoint. But one small request can u write/give the code in C#. I will be very happy if u do this favor for me. Thanks a lot.
Title: Mr   
Name: James
Date: 2010-10-02 9:57:49 AM
Comment:
Awesome code, and great references too. } Really thumbs up for the code, this is the best tutorial so far!
Will study how all of this works... =)
Title: Mr   
Name: Hiep
Date: 2010-06-18 12:47:50 AM
Comment:
This article is useful. thanks much
Title: Mr   
Name: Jafari
Date: 2009-10-19 8:47:26 AM
Comment:
Thanks Abdulla,
could you explain how to use ajax with multiple updatepanels?
Title: Mr   
Name: ashwin
Date: 2009-02-06 12:54:08 PM
Comment:
Cool stuff
Title: Mr   
Name: Daniel Partridge
Date: 2009-01-21 5:02:39 AM
Comment:
This looks really good!!!!
Title: Dan   
Name: Dan
Date: 2008-12-27 9:45:50 AM
Comment:
Really Liked the oninit code.
Title: mrs   
Name: Madhuri
Date: 2008-12-15 4:32:54 PM
Comment:
This is really very useful. Thanks






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2017 ASPAlliance.com  |  Page Processed at 2017-08-18 7:56:43 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search