Monday, May 25, 2009

Bind a Microsoft ASP .NET Chart Control within a SharePoint web part to a DataSet

Bind a Microsoft ASP .NET Chart Control embedded in an Ajax refreshable SharePoint Web Part to a DataSet obtained from a call to a Web service

Summary

Introduction
1 - Prerequisites
2 - Tutorial Overview
3 - Tutorial
 
1 - Step 1 Creating the Web Service used as a datasource
1.1 Creating the IIS Web Site for the Web Serice
1.2 Compiling the Web Service
1.3 Deploying the Web Service
1.4 Testing the Web Service


2 - Step 2 Binding an ASP .Net Chart Control embedded in a SharePoint Web Part to the Dataset
2.1 Create the web part project
2.2 Deploy WSPBuilder
2.3 Add a Web Reference to the web Service
2.4 Code of the Web Part (without Ajax feature)
2.4 Web Part SharePoint Solution Creation with WSPBuilder
2.5 Web Part SharePoint Solution Deployment
2.5 Web Part testing
2.6 Modify the Code Access Security Policy with WspBuilder
2.7 Adding Ajax feature to the Web Part
2.8 Adding Ajax Timer to the Web Part

Introduction

This tutorial is the following of the last tutorial about ASP .NET Chart Control for SharePoint that I have posted on 2008 December 10, Create a SharePoint AJAX-refreshable Web Part which wraps an ASP .NET Chart Control, and that was showing how to place an Microsoft ASP .NET Chart Control inside an Microsoft AJAX refreshable web Part. In this previous tutorial, the web part was not bound to any datasource.

In the present tutorial I will show how to bind a Microsoft Asp .net Chart Control embedded in  a SharePoint Web Part to a DataSet. There is many examples of datasource binding in the Samples Environment for Microsoft Asp .Net Chart Controls   but most of them bind the Chart Control to a SQL Datareader.
I will rather show how to bind the control to a DataSet and will use a DataSet coming from a call to a Web Service.

Furthermore, I will still place the chart control inside an update panel in order to improve the user experience.


1 - Prerequisites

  • Usual development environment for SharePoint (Windows 2003 Server or Windows Server 2008 with a SharePoint installation).
  • Microsoft Chart Controls for Microsoft .NET Framework 3.5 are installed on the development environment. You can download installation package here
  • Microsoft Visual Studio 2008 is installed on the development environment.
  • Microsoft Chart Controls Add-on for Microsoft Visual Studio 2008is installed on the development environment.
  • Your SharePoint environment is properly configured for ASP .Net Chart Controls. If you are not sure you can check the configuration in my previous post, sections 3.3 and 3.4, or do the quick tutorial of this previous post in order to validate your environment by displaying the Chart Control Sample on a SharePoint page.
  • Your SharePoint environment is properly configured for AJAX. If you are not sure you can check the configuration in my previous post, sections 4.1, or do the quick tutorial of this previous post in order to validate your environment by displaying the Chart Control Sample inside an Ajax refreshable Web Part.
  • You have downloaded WSPBuilder Package in order to be able to use WSPBuilder to deploy the Web part.
  • You have a SharePoint team site ready to welcome the Asp .Net Chart control Web part.

2 - Tutorial Overview

In this tutorial, first, we are going to develop a Web Service that will provide a datasource for that web part.
Then we will develop a web part that will embed an ASP .Net Chart Control an display a trend based on the data coming from the call to the Web Service.
We will for this web part use the minimal configuration to respect the best practices:
  • we will place the web part dll in the bin directory of the SharePoint Application,
  • we will use WspBuilder to deploy the web part and modify the Code Access Security of our web application in order the web part code will be authorized to run.

There is anyway an exception I will use in a matter of demonstration.
I WILL NOT sign the web part dll with a strong name to show that, if you deploy a web part dll in the bin directory , there is no real need to sign it with a strong name, except to prevent unauthorized versions of the Web Part in the future. As mentioned in the MSDN documentation:

Deploying Web Parts in Windows SharePoint Services

[...]

Strong Naming a Web Part Assembly

Strong naming uses a private key to digitally sign an assembly. Strong naming also stamps the assembly with a public key to validate the signature. This technique guards against unauthorized versions of a Web Part. If the public key fails to validate the digital signature, Windows SharePoint Services will refuse to run the module.

When deploying a Web Part to the bin, the recommend practice is to strong name the assembly. When deploying a Web Part to the Global Assembly Cache, the assembly must have a strong name. An assembly without a strong name is not recommended in Windows SharePoint Services.

[...]

Furthermore, since we are not creating signed code, we do not need to tell our assembly to allow partially trusted code calls, so we do not need to use the AllowPartiallyTrustedCallers attribute

I will perform these different operations of configuration when required by a SharePoint or an ASP .Net exception so as we can examine what a specific configuration is for. Furthermore, as we cannot anticipate certain exceptions like Code Access Security exceptions, waiting for exceptions before configuring a SharePoint element is often the usual way of programming for SharePoint. 

Last, we will place the ASP .NET Chart Control of the Web Part in an Update Panel in order to improve user experience.

This tutorial includes the following steps:

  • Step 1: Creating the IIS Web Site for the Web Service
  • Step 2: Compiling the Web Service
  • Step 3: Deploying the Web Service
  • Step 4: Testing the Web Service
  • Step 5: Create the web part project
  • Step 6: Deploy WSPBuilder
  • Step 7: Add a Web Reference to the web Service
  • Step 8: Copy the Code of the Web Part (without Ajax feature)
  • Step 9: Web Part SharePoint Solution Creation with WSPBuilder
  • Step 10: Web Part SharePoint Solution Deployment
  • Step 11: Web Part testing
  • Step 12: Modify the Code Access Security Policy with WspBuilder
  • Step 13: Adding Ajax feature to the Web Part
  • Step 14: Adding Ajax Timer to the Web Part

3 - Tutorial

 

1 - Step 1 Creating the Web Service used as a datasource

1.1 Creating the IIS Web Site for the Web Service

Open IIS manager then right click on the Web Sites node then point to "New", click "Web Site".



On the opening dialog of the Web Site Creation Wizard click "Next".



In the web Site Description dialog, type "Web Service Test Charting  - 201"



In "IP Address and Port Settings" dialog for the IP Address type 201 in the input box "TCP port this Web site should use".



In "Web Site Home Directory" dialog click "Browse", then create a new folder under the Inetpub\wwwroot directory and name it "Web service Test Charting - 201".



In "Web Site Access Permissions" dialog click check "Run scripts" and "Execute".



As specified in the last dialog, you have successfully completed the Web Site creation.



1.2 Compiling the Web Service


Open Visual Studio.
Create a New web service project in file mode and C# named WebServiceTestCharting.




In the Service1.asmx.cs file, copy the following code:

using System;

using System.Collections;

using System.ComponentModel;

using System.Data;

using System.Linq;

using System.Web;

using System.Web.Services;

using System.Web.Services.Protocols;

using System.Xml.Linq;

using System.Timers;

using System.Diagnostics;

 

namespace WebServiceTestCharting

{

    /// <summary>

    /// Summary description for Service1

    /// </summary>

    [WebService(Namespace = "http://tempuri.org/")]

    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

    [ToolboxItem(false)]

    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.

    // [System.Web.Script.Services.ScriptService]

    public class Service1 : System.Web.Services.WebService

    {

        static Timer timer1 = new Timer();

        DataSet myDataSet;

        DataTable myDatatable;

        static System.Collections.Generic.SortedList<DateTime, double> myValues = new System.Collections.Generic.SortedList<DateTime, double>();

 

        static Service1()

        {

            if (timer1.Enabled == false)

            {

                Debug.WriteLine("contructor ");

 

                timer1.Elapsed += new ElapsedEventHandler(OnElapsedTime);

                timer1.Interval = 1000;

 

                timer1.Enabled = true;

            }

        }

 

        static protected void OnElapsedTime(object sender, EventArgs e)

        {

            DateTime now = DateTime.Now;

            Debug.WriteLine(now);

 

            myValues.Add(now, Math.Sin((double)DateTime.Now.Second));

        }

 

        [WebMethod]

        public DataSet Sinusoid()

        {

            myDataSet = new DataSet();

            myDatatable = new DataTable("myTable");

 

            DataColumn myDataColumnTime = new DataColumn("Time", System.Type.GetType("System.DateTime"));

            DataColumn myDataColumnValue = new DataColumn("Value", System.Type.GetType("System.Double"));

 

            myDatatable.Columns.Add(myDataColumnTime);

            myDatatable.Columns.Add(myDataColumnValue);

            myDataSet.Tables.Add(myDatatable);

 

            for (int i = 0; i < myValues.Keys.Count; i++)

            {

                myDataSet.Tables["myTable"].Rows.Add();

                myDataSet.Tables["myTable"].Rows[i][0] = myValues.Keys[i];

                myDataSet.Tables["myTable"].Rows[i][1] = myValues[myValues.Keys[i]];

            }

 

            Debug.WriteLine("number of rows in DataTable :  " + myDataSet.Tables["myTable"].Rows.Count);

            return myDataSet;

        }

    }

}

Then build the project.

1.3 Deploying the Web Service


Right click the Project node in Visual Studio and click "Open Folder in Window Explorer".
Then copy the following elements and paste them in the previously created folder of the IIS Web Site (C:\Inetpub\wwwroot\Web Service Test Charting - 201)

  • web.config
  • bin folder
  • Service1.asmx
  • Service1asmx.cs


1.4 Testing the Web Service


Then go back to IIS, locate the web service IIS web site and display in the right pane the web service files.
Right click the Service1.asmx file picture and click "Browse".



The opening page shows the supported operation and you notice the presence of the web method: Sinusoid.



Click the Sinusoid link in order to display the Web Method page.



On this page click "Invoke" button. The opening page displays the xml view of the DataSet. Notice that no rows are present yet.



Close the page and click invoke a second time As the timer has started, the dataset contains now several rows.



If you are using debug view, as I have put Debug trace instruction in the code you should obtain this:




2 - Step 2 Binding an ASP .Net Chart Control embedded in a SharePoint Web Part to the Dataset

2.1 Create the web part project

In Visual Studio, create a new class library project and name it BindableChartWebParts.



Rename the Class1.cs in MsChartingWebPart

Add the following references to the project:

System.Drawing;
System.Web;
Microsoft.SharePoint
System.web.DataVisualisation




2.2 Deploy WSPBuilder

In Visual Studio, in the Solution Explorer, right click the project node and click "Open Folder in Window Explorer".
Then create a new folder named "WSPBuilder".



In the folder create a "80" folder and in this folder, create a "bin" folder.




Then in the WSPBuilder folder place the following elements of the WSPBuilder package downloaded on CodePlex:

CabLib.dll
WSPBuilder.exe
WSPBuilder.exe.config



Then go back to Visual Studio, right click your project node in the Solution Explorer and click "Properties".
In the project properties  pane click the "Build" left menu entry.
Then using the "browse" button change the output path so as it point to the WSPBuilder bin folder.



2.3 Add a Web Reference to the web Service

In the Visual Studio Explorer, right click the "References" node and choose add a service reference.



In the "Add Service Reference" dialog, click "Advanced" button.



In the "Service Reference Settings" dialog click the "Add web reference" button.
In the "Add Web Reference" dialog, in the URL input box type the previously created Web Service URL:
http://localhost:201/Service1.asmx (if you are working on the server) then click go.

The wizard connects to the web service and display the supported operation page.

In the "Web reference name" input box, type "WebServiceTestCharting201"
Then click the "Add Reference" Button




You can check the new Web Reference in the Visual Studio Solution Explorer.



2.4 Code of the Web Part (without Ajax feature)

Copy the following code inside the MsChartingWebPart.cs file.

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Text;

using System.Drawing;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using Microsoft.SharePoint.WebPartPages;

using System.Web.UI.DataVisualization.Charting;

using System.Data;

using System.Diagnostics;

 

namespace BindableChartWebParts

{

    [ToolboxData("<{0}:MsChartingWP runat=server></{0}:MsChartingWP>")]

    public class MsChartingWebPart : WebPart

    {

        System.Web.UI.DataVisualization.Charting.Chart Chart1 = new System.Web.UI.DataVisualization.Charting.Chart();

 

        protected override void OnInit(EventArgs e)

        {

            base.OnInit(e);

        }

 

        protected override void CreateChildControls()

        {

            //to change the style of the chart and add a title

 

            Chart1.ChartAreas.Add("datedLabel");

            Chart1.Series.Add("Series 1");

 

            Chart1.Series["Series 1"].ChartType = SeriesChartType.Spline;

            //to change the style of the line

            //Chart1.Series["Series 1"].MarkerStyle = MarkerStyle.Diamond;

            //Chart1.Series["Series 1"].MarkerSize = 7;

            //Chart1.Series["Series 1"].MarkerColor = Color.White;

            //Chart1.Series["Series 1"].MarkerBorderColor = Color.Black;

 

            Chart1.ChartAreas["datedLabel"].AxisX.IsLabelAutoFit = true;

            Chart1.ChartAreas["datedLabel"].AxisX.LabelStyle.Angle = 30;

            Chart1.ChartAreas["datedLabel"].AxisX.LabelStyle.IsEndLabelVisible = true;

 

            string strTimeFormat = "hh:mm:ss";

            Chart1.ChartAreas["datedLabel"].AxisX.LabelStyle.Format = strTimeFormat;

 

 

 

            WebServiceTestCharting201.Service1 myService = new BindableChartWebParts.WebServiceTestCharting201.Service1();

 

            System.Data.DataSet myDs = myService.Sinusoid();

 

            string str30secBefore = DateTime.Now.AddSeconds(-30).ToString();

            string expression = "Time > '" + str30secBefore + "'";

 

            DataView myFilteredView = new DataView(myDs.Tables[0], expression, "", DataViewRowState.CurrentRows);

 

            Chart1.Series["Series 1"].Points.DataBindXY(myFilteredView, "Time", myFilteredView, "Value");

 

            Chart1.Width = 412;

            Chart1.Height = 296;

 

            this.Controls.Add(Chart1);

        }

    }

}

 

Then build the project

2.4 Web Part SharePoint Solution Creation with WSPBuilder

Go back to the WspBuilder folder. Double click the WspBuilder.exe.
Notice that a command prompt is opening , that a .wsp file is created and also a solutionId.txt file.
We are going to write a little .bat file to make the WspBuilder.exe command prompt stay open, and to give build instructions to the WspBuilder.exe.

Create a text file and rename it to genWsp.bat.
Right click the file and choose Edit.
Inside this file type the following:

wspbuilder.exe -WSPname BindableChartWebParts.wsp
pause


Then double click the .bat file and notice that the command prompt stays open and allows you to check if the build was successful.



Notice also that the new generated .wsp file has now a friendlier name.


2.5 Web Part SharePoint Solution Deployment


Open a command prompt, and if you have added the path of the SharePoint stsadm tool (C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN) in the environment variables type the following in the command prompt. (take care to use an account that is both Administrator of the Server and belongs to the SharePoint Farm Administrators).

Stsadm -o addsolution -filename

Then drag and drop the previously built .wsp file in the command prompt.



then type Enter. The stsadm tool adds your .wsp file to the SharePoint Farm Solution store.



Open the SharePoint Central Administration Console.
Click the Tab Operations
Then in the Global Configuration Section click the link Solutions Management

In the Solution Management page locate the bindablechartwebpartsolution.wsp solution and click on it.
On the Solution Properties page click Deploy solution
In the Deploy Solution page, choose the Web Application where you want to use the web part, then click OK.



Open your web application web.config file, and notice that the deployment using a wsp allows adding automatically an entry in the web.config file of a web application. In our case:

      <SafeControl Assembly="BindableChartWebParts" Namespace="BindableChartWebParts" TypeName="*" Safe="True" />

As specified previously in this post, I have decided not to compile the web part .dll with a strong name on purpose. It is to show that a dll deployed in the bin directory of a web application does not need a strong name.

2.5 Web Part testing

Because there is an entry for our web part in the safecontrols section of the web.config of a SharePoint Web Application, the site collections of this web application will be allowed to populate their web part galleries with the web part.
Choose a site collection of the web application where you deployed the solution, open its site settings page, in the Galleries section locate the Web parts and click the link.
The web part gallery is opening.





Click New.
In the Web Part Gallery: New Web Parts page locate the BindableChartWebParts.MsChartingWebPart and check its checkbox, then click the populate Gallery button



Then go to a web part page of a site within the site collection and add the web part to the page.







Then, don't panic, you have a security exception, and it is perfectly normal.
Your web part was deployed to the bin directory of a web application and the web.config file of this web application has its trust level set to WSS_Minimal so the web part code has the minimal privileges to run.
This exception is a common ASP .Net exception that prevents an Asp .Net application from calling an Url outside its domain. We had this exception thrown because of the call to the web service.
Of course to prevent this exception I could have put the Sinusoid web service with the other SharePoint web services in the SharePoint _vti_bin (as I did in that post Integrate ASP.NET Web Service based AJAX with MOSS 2007 or Windows SharePoint Services 3.0 ), but I did not do it on purpose to illustrate the Code Access Security exception fixing with WspBuilder.

2.6 Modify the Code Access Security Policy with WspBuilder

To fix this issue we are going to redeploy the web part and before redeploying, place in the manifest .xml of the .wsp a new instruction for adding security permissions.
WspBuilder allows us to do it in a very friendly way.

In the wspbuilder folder, create a new .txt file and name it "WspBuilder_CAS.txt".
Inside this file write the following:

<IPermission class="System.Net.WebPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" >
</IPermission>

That will authorize the requests to outside locations for the web application. (there is a way to authorize only one or several locations by typing Url's, but to stay simple for this tutorial, I will authorize all the locations).

Then reopen the genWsp.bat and add the following instruction:

-CustomCAS WspBuilder_CAS.txt

so as the entire content of the .bat be the following:

wspbuilder.exe -WSPname BindableChartWebParts.wsp -CustomCAS WspBuilder_CAS.txt
pause


Double click the modified .bat file to regenerate a new .wsp solution file with the new Code Access Security instructions within its manifest.xml file.

Then we just have to upgrade the solution by typing this instruction in a command prompt:

stsadm -o upgradesolution -name BindableChartWebparts.wsp  -filename C:\Dev\BindableChartWebPart\WSPBuilder\BindableChartWebParts.wsp -immediate -allowcasPolicies



The solution upgrade triggers a recycling of the web application pool that leads to the usual time to wait the page refreshing, and when it's done the web part is displaying the sinusoid trend.



Exit edit mode.
Refresh the page and notice that the time value has changed and the web part is calling the web service each time we refresh the page.





It would be nice to refresh only the web part wouldn't be? That is we will do in the next part of this post by placing the Chart Control and a refresh button inside an update panel control...

It is what I have done in a previous post (Create a SharePoint AJAX-refreshable Web Part which wraps an ASP .NET Chart Control), so if you check it you can perform the second part of this tutorial before I have finished to write it...

2009 June 10th.
...Back to write the end of the post.
We are going to make the Web Part to be refreshable without showing a visible Post Back of the Web Part Page, by embedding the Web Part Children Controls within an Update Panel.
Finally, we are going to use an Ajax Timer for automating the refresh of the web Part.

2.7 Adding Ajax feature to the Web Part

- Prerequisites:

First, we have to add a reference to the System.Web.Extensions in the Web Part project to be able to take benefits of Microsoft Ajax Features.




Then we have to modify the Web Part code doing the following operations:

  • Declare and instantiate the UpdatePanel without forgetting to give it an ID.
  • Set the UpdateMode of the Update panel to conditional because we are going to refresh the Update panel by calling its Update method and the call to this method requires the conditional mode.
  • Declare, instantiate and configure a Link Button to refresh the Web part, add an Event Handler to the Link Button click.
  • Make the chart Control and the Link Button to be children controls of the Update Panel ContentTemplateContainer.
  • In the method referred by the Link Button Event Handler, place the Update Panel Update() method.

Here is the Web Part code after having performed these different code modifications.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Drawing;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.Web.UI.DataVisualization.Charting;
using System.Data;
using System.Diagnostics;
 
 
namespace BindableChartWebParts
{
    [ToolboxData("<{0}:MsChartingWP runat=server></{0}:MsChartingWP>")]
    public class MsChartingWebPart : WebPart
    {
        System.Web.UI.DataVisualization.Charting.Chart Chart1 = new System.Web.UI.DataVisualization.Charting.Chart();
 
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
        }
 
        //UpdatePanel declaration
        UpdatePanel updatepanel1;
        protected override void CreateChildControls()
        {
            //UpdatePanel instantiation, and identification
            updatepanel1 = new UpdatePanel();
            updatepanel1.ID = "updplAjaxRefreshableChartControlWebPart";
            updatepanel1.UpdateMode = UpdatePanelUpdateMode.Conditional;
 
            //LinkButton declaration, instantiation, and configuration
            LinkButton lbtnRefresh = new LinkButton();
            lbtnRefresh.ID = "lbtnWebPartRefresh";
            lbtnRefresh.Text = "Refresh";
            lbtnRefresh.Click += new EventHandler(lbtnRefresh_Click);
 
            Chart1.ChartAreas.Add("datedLabel");
            Chart1.Series.Add("Series 1");
 
            Chart1.Series["Series 1"].ChartType = SeriesChartType.Spline;
            //to change the style of the line
            //Chart1.Series["Series 1"].ChartType = SeriesChartType.Line;
            //Chart1.Series["Series 1"].MarkerStyle = MarkerStyle.Diamond;
            //Chart1.Series["Series 1"].MarkerSize = 7;
            //Chart1.Series["Series 1"].MarkerColor = Color.White;
            //Chart1.Series["Series 1"].MarkerBorderColor = Color.Black;
 
            Chart1.ChartAreas["datedLabel"].AxisX.IsLabelAutoFit = true;
            Chart1.ChartAreas["datedLabel"].AxisX.LabelStyle.Angle = 30;
            Chart1.ChartAreas["datedLabel"].AxisX.LabelStyle.IsEndLabelVisible = true;
 
            string strTimeFormat = "hh:mm:ss";
            Chart1.ChartAreas["datedLabel"].AxisX.LabelStyle.Format = strTimeFormat;
 
 
 
            WebServiceTestCharting201.Service1 myService = new BindableChartWebParts.WebServiceTestCharting201.Service1();
 
            System.Data.DataSet myDs = myService.Sinusoid();
 
            string str30secBefore = DateTime.Now.AddSeconds(-30).ToString();
            string expression = "Time > '" + str30secBefore + "'";
 
            DataView myFilteredView = new DataView(myDs.Tables[0], expression, "", DataViewRowState.CurrentRows);
 
            Chart1.Series["Series 1"].Points.DataBindXY(myFilteredView, "Time", myFilteredView, "Value");
 
            Chart1.Width = 412;
            Chart1.Height = 296;
 
            updatepanel1.ContentTemplateContainer.Controls.Add(Chart1);
            updatepanel1.ContentTemplateContainer.Controls.Add(lbtnRefresh);
 
            this.Controls.Add(updatepanel1);
        }
 
        void lbtnRefresh_Click(object sender, EventArgs e)
        {
            updatepanel1.Update();
        }
    }
}
 

Then we have to build and deploy the new version of the web part as we did before by using a .wsp, but before being allowed to use this new version of the Web Part we have to add a ScriptManager to the Web Part Page that will welcome the Web Part.
In a previous post (Create a SharePoint AJAX-refreshable Web Part which wraps an ASP .NET Chart Control), I have added the ScriptManager to the Web Part Page, but for this one, I will add a ScriptManager to the Master Page of the Site Collection, that will allow all the Site Content Pages to manage one or several Update Panels without thinking each time not to forget to add a ScriptManager to the Page.
Regarding the option to add a ScriptManager to the Page by placing the instruction within the Web Part code, I have seen a lot of example of this option on SharePoint blogs, but I do not advice to do it that way, since it seems to only work randomly. You can also refer to Mike Ammerlaan's Blog. The best explanation of the random nature of success using this approach is in this post:

Adding a ScriptManager to your Page Programmatically through a Web Part

But there is also people that seem to feel confident with it, so..

Best practices and common errors when adding a ScriptManager programmatically from a WebPart
Integrating ASP.NET Ajax WebPart with SharePoint 3.0

Last, you can also find several other options here:

Add ScriptManager to Page Programmatically?

As I use a Site Collection based on a native SharePoint Site Definition the Site Collection Master Page is the default.master and is located in the Global folder under the 12 hive.



I will add the ScriptManager to this Master Page only for this post, but if I had to do it in a real SharePoint project, I would have used a custom Master Page deployed with a SharePoint Feature instead.

So, open the default.master with Visual Studio, then drag and drop a ScriptManager control just under the WebPartManager of the Master Page.



Refresh the page.
The LinkButton Refresh appears, and if you click it, the web part will be refreshed and you will see the sinusoid curve changes.





In the next step, we are going to use an Ajax Timer for automating the refresh of the web Part.

2.8 Adding Ajax Timer to the Web Part

So we have to modify the Web Part code again and perform the following operations:

  • Adding an Ajax timer to the Web part.(You will find it in the AJAX Extension Section of the Visual Studio Toolbox - You can check the previous screenshot where I did the drag and drop of the ScriptManager)
  • Adding an EventHandler to the timer Tick.
  • Making the Ajax timer to be child controls of the Update Panel ContentTemplateContainer.
  • In the method referred by the Event Handler added to the timer Tick, placing the Update Panel Update() method.

We will use the previous refresh button to start the timer.

  • Renaming all the references to "refresh" for the Link Button to "Start Timer"
  • In the method referred by the Link Button Event Handler, place the instruction to set the Timer interval to 1 second so as to start the Timer when the Link Button is clicked.

Here is the Web Part code after having performed these different code modifications.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Drawing;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.Web.UI.DataVisualization.Charting;
using System.Data;
using System.Diagnostics;
 
 
namespace BindableChartWebParts
{
    [ToolboxData("<{0}:MsChartingWP runat=server></{0}:MsChartingWP>")]
    public class MsChartingWebPart : WebPart
    {
        System.Web.UI.DataVisualization.Charting.Chart Chart1 = new System.Web.UI.DataVisualization.Charting.Chart();
 
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
        }
 
        //UpdatePanel declaration
        UpdatePanel updatepanel1;
        Timer timRefresh;
        protected override void CreateChildControls()
        {
            //UpdatePanel instantiation, and identification
            updatepanel1 = new UpdatePanel();
            updatepanel1.ID = "updplAjaxRefreshableChartControlWebPart";
            updatepanel1.UpdateMode = UpdatePanelUpdateMode.Conditional;
 
            //LinkButton declaration, instantiation, and configuration
            LinkButton lbtnStartTimer = new LinkButton();
            lbtnStartTimer.ID = "lbtnWebPartStartTimer";
            lbtnStartTimer.Text = "Start Timer";
            lbtnStartTimer.Click += new EventHandler(lbtnStartTimer_Click);
 
            //Ajax Timer instantiation, and identification
            timRefresh = new Timer();
            timRefresh.ID = "timWebPartRefresh";
            timRefresh.Tick += new EventHandler<EventArgs>(timRefresh_Tick);
 
 
            Chart1.ChartAreas.Add("datedLabel");
            Chart1.Series.Add("Series 1");
 
            Chart1.Series["Series 1"].ChartType = SeriesChartType.Spline;
            //to change the style of the line
            //Chart1.Series["Series 1"].ChartType = SeriesChartType.Line;
            //Chart1.Series["Series 1"].MarkerStyle = MarkerStyle.Diamond;
            //Chart1.Series["Series 1"].MarkerSize = 7;
            //Chart1.Series["Series 1"].MarkerColor = Color.White;
            //Chart1.Series["Series 1"].MarkerBorderColor = Color.Black;
 
            Chart1.ChartAreas["datedLabel"].AxisX.IsLabelAutoFit = true;
            Chart1.ChartAreas["datedLabel"].AxisX.LabelStyle.Angle = 30;
            Chart1.ChartAreas["datedLabel"].AxisX.LabelStyle.IsEndLabelVisible = true;
 
            string strTimeFormat = "hh:mm:ss";
            Chart1.ChartAreas["datedLabel"].AxisX.LabelStyle.Format = strTimeFormat;
 
 
 
            WebServiceTestCharting201.Service1 myService = new BindableChartWebParts.WebServiceTestCharting201.Service1();
 
            System.Data.DataSet myDs = myService.Sinusoid();
 
            string str30secBefore = DateTime.Now.AddSeconds(-30).ToString();
            string expression = "Time > '" + str30secBefore + "'";
 
            DataView myFilteredView = new DataView(myDs.Tables[0], expression, "", DataViewRowState.CurrentRows);
 
            Chart1.Series["Series 1"].Points.DataBindXY(myFilteredView, "Time", myFilteredView, "Value");
 
            Chart1.Width = 412;
            Chart1.Height = 296;
 
            updatepanel1.ContentTemplateContainer.Controls.Add(Chart1);
            updatepanel1.ContentTemplateContainer.Controls.Add(lbtnStartTimer);
            updatepanel1.ContentTemplateContainer.Controls.Add(timRefresh);
 
            this.Controls.Add(updatepanel1);
        }
 
        void timRefresh_Tick(object sender, EventArgs e)
        {
            updatepanel1.Update();
        }
 
        void lbtnStartTimer_Click(object sender, EventArgs e)
        {
            timRefresh.Interval = 1000;
        }
    }
}
 

So, now, when we click the Start Timer Link Button, the Web Part is refreshing automatically each second.