Todd Snyder

XDG – Developer Team Lead: Samples, Patterns, & Principals
Getting SharePoint and ASP.NET AJAX to Work Together

While, working on Pomegranate I did a lot of research to figure out the best options for using the ASP.NET AJAX library under SharePoint. Unfortunately, I came across a lot of samples that did not work or only worked in some cases.  I am hoping in a future SharePoint service pack Microsoft includes a base AJAX web part that properly sets up the JavaScript to get AJAX to work.

For Pomegranate we followed the approach outlined in the following KB Article. The approach suggests injecting JavaScript that runs during the start up of a page that update the HTML document form’s initial action to be the same as the form’s action (See Code Listing #3). This is needed because by default SharePoint prevents multi post backs from occurring. One caveat with using this approach is that sometimes the AJAX call causes a full post back instead of doing a partial page rendering. To Work around this you must included one of the SharePoint list (Tasks or Announcements) web parts. Note: If you prefer you can hide the list web part and the AJAX call will still work.  I plan on doing some additional research and will let you know if I find a better way to get AJAX to work with SharePoint.

Ok, enough with the war story about getting AJAX to work with SharePoint, let’s move on to an example of building a custom web part that uses AJAX. The example focuses on using a Standard ASP.NET Button control to dynamically load the contents of the Infragistics WebGrid. Once the grid is loaded the example uses the built-in AJAX capabilities of the WebGrid control to filter data.

Image #1: WebGrid displayed in a custom web part

Web Grid AJAX Sample

Before we look at the code for the custom web part we need to take care of a few prerequisites to get AJAX to work under SharePoint. First make sure you are using Windows SharePoint 3.0 SP1 or Microsoft Office SharePoint Server 2007 SP1. These are the only versions of SharePoint that support AJAX. Once you have installed the SharePoint service pack you need to make sure your SharePoint Applications web.config contain all the necessary entries for enabling AJAX to work and create a custom master page that contains an AJAX Script Manager control. See Setting up AJAX to run in SharePoint for more details.

Now that you have AJAX setup to run under SharePoint let’s move onto our example. The first thing you need to do is create a new ASP.NET Server control library (or us an existing one if you prefer) and a new server control to the project. Open the code for the new server control and update it to inherit from System.Web.UI.WebControls.WebParts.WebPart and override the create child control event. When I create a web part I always start simple and just add a label that says “Hello World”. Once the code compiles I sign the assembly for the control, set it up to support Allow Partial Trusted Caller, and deploy it to the BIN folder of my SharePoint application. I then update the SafeControl section of the applications web.config and install the Web Part in SharePoint. I then test to make sure the web part works in SharePoint by adding the web part to web part page in SharePoint.

Code Listing #1: Web.config Safe Control Entry

<SafeControl Assembly="Sample.GridAJAX.Controls,Version=1.0.0.0, Culture=neutral, PublicKeyToken=4e50f862043ae8c9" Namespace="Sample.GridAJAX.Controls" TypeName="*" Safe="True" />

Code Listing #2: Update the Web Part’s assemblyInfo class to include the Allow Partially Trusted Caller Attribute.

using System.Security;

[assembly: AllowPartiallyTrustedCallers()]

Now that my basic web part is working, let’s update the Web Part to support AJAX by adding the necessary code to fix the AJAX Update Panel.

Code Listing #3: Code used for getting an AJAX Update Panel to work properly under SharePoint:

public const string AJAX_HOSTPANEL_NAME = "HostPanel_";

public const string SHAREPOINT_AJAX_POSTBACK_SCRIPTNAME = "UpdatePanelFixup";

ublic const string SHAREPOINT_AJAX_POSTBACK_SCRIPT =

@"_spBodyOnLoadFunctionNames.push(""_initFormActionAjax"");

 

function _initFormActionAjax()

      {

           if (_spEscapedFormAction == document.forms[0].action)

           {

document.forms[0]._initialAction =

document.forms[0].action;

           }

      }

 

      var RestoreToOriginalFormActionCore = RestoreToOriginalFormAction;

                                                             RestoreToOriginalFormAction = function()

      {

            if (_spOriginalFormAction != null)

            {

RestoreToOriginalFormActionCore();

document.forms[0]._initialAction =

document.forms[0].action;

            }

      }";

private ScriptManager _scriptManager;

private UpdatePanel _hostPanel;

 

 

/// <summary>

/// Create Script Manager control.

/// </summary>

private void CreateScriptManager()

{

this._scriptManager = new ScriptManager();

this._scriptManager.EnablePartialRendering = true;            this._scriptManager.EnableScriptLocalization = true;

      this.Controls.AddAt(0, this._scriptManager);

}

 

/// <summary>

/// Setup Sharepoint's JS postback code to handle AJAX calls.

/// </summary>

private void SetupSharePointAjax()

{

      this._hostPanel = new UpdatePanel();

      this._hostPanel.ID = AJAXCommon.AJAX_HOSTPANEL_NAME + this.ClientID;

this._hostPanel.UpdateMode = UpdatePanelUpdateMode.Conditional;

this._hostPanel.ChildrenAsTriggers = true;

this.Controls.Add(_hostPanel);

 

if (this.Page.Form != null)

{

ScriptManager.RegisterStartupScript(this, typeof(GridAJAX),

                    AJAXCommon.SHAREPOINT_AJAX_POSTBACK_SCRIPTNAME,

                    AJAXCommon.SHAREPOINT_AJAX_POSTBACK_SCRIPT, true);

       }

}

 

/// <summary>

/// On Init Control Event.

/// </summary>

protected override void OnInit(EventArgs e)

{

base.OnInit(e);

 

      this._scriptManager = ScriptManager.GetCurrent(this.Page);

      if (_scriptManager == null) // Add a script manager

      {

            this.CreateScriptManager();

      }

 

      this.SetupSharePointAjax();

      this.EnsureChildControls(); // Make sure create child control is called

}

 

I then update the web part to contain a button and setup a click event that changes the text of the label to Hello World AJAX. Once the assembly compiles I copy it to the SharePoint applications BIN folder and test out the updated web part. At this point, if AJAX is configured properly you should be able to click on the button and have the label updated without causing a post back. If a full page post back happens make sure your master page contains a Script Manager Control, your web.conig contains the necessary AJAX configuration entries, and your web part page contains at least one of the Standard SharePoint List (Tasks, Announcements) web parts. If all this is true then AJAX should work without causing a full page post back.

Now that the AJAX is working we can move on to adding the Infragistics WebGrid to the custom Web Part. To use the WebGrid you need to make sure you have Net Advantage for ASP.NET installed and a reference to the following assemblies:

  • Infragistics2.WebUI.Misc.v8.2
  • Infragistics2.WebUI.Shared.v8.2
  • Infragistics2.WebUI.UltraWebGrid.v8.2.

Make sure you use the Allow Partial Trusted Caller (APTC) version of these assemblies. SharePoint only works with assemblies that allow partial trusted callers.

Now that you have references setup to use the Infragistics WebGrid lets update the web part’s Create Child Controls method to setup the WebGrid (See Code Listing #4).  Inside of the create child control method we create an instance of the WebGrid. Then define the columns to display in the grid and set filtering. We finished out the method by adding a button to load the grid. When the button‘s click events fires we will make an AJAX call and bind the grid to a collection of customers.

A few important things to remember about the code listed below. First make sure you setup the grid’s initializeDataSourceEventHandler this is needed for the grid to properly handled data binding. Second make sure that you add all child controls (Grid and Button) to the update panel’s ContentTemplateContainer control collection.

Code Listing #4: Code to setup a WebGrid to display and filter a list of customers

/// <summary>

/// Layout the web part and its children controls

/// </summary>

protected override void CreateChildControls()

{

base.CreateChildControls();

      this._grid = new UltraWebGrid();

           

this._grid.InitializeDataSource +=

new InitializeDataSourceEventHandler(_grid_InitializeDataSource);

 

      this._grid.DisplayLayout.AutoGenerateColumns = false;

      this._grid.DisplayLayout.CellPaddingDefault = 3;

this._grid.DisplayLayout.FilterOptionsDefault.AllowRowFiltering = RowFiltering.OnClient;

this._grid.DisplayLayout.FilterOptionsDefault.AllString = "(All)";

this._grid.DisplayLayout.FilterOptionsDefault.EmptyString = "(Empty)";

this._grid.DisplayLayout.FilterOptionsDefault.AllowRowFiltering = RowFiltering.OnClient;

 

UltraGridBand dataBand =

this.CreateGridBand("Customers", "Customers", "Id");

this._grid.Bands.Add(dataBand);

      dataBand.Columns.Add(this.CreateGridColumn("Name", "Name"));

dataBand.Columns.Add(this.CreateGridColumn("Activation Date", "FormatedCustomerSince"));

dataBand.Columns.Add(this.CreateGridColumn("Balance", "AccountBalance"));

 

this._hostPanel.ContentTemplateContainer.Controls.Add(_grid);

 

this._hostPanel.ContentTemplateContainer.Controls.Add(new LiteralControl("<BR />"));

 

      Button testAJAX = new Button();

      this._hostPanel.ContentTemplateContainer.Controls.Add(testAJAX);

      testAJAX.Text = "Load Grid";

      testAJAX.Click += new EventHandler(testAJAX_Click);

}

 

void _grid_InitializeDataSource(object sender, UltraGridEventArgs e)

{

}

/// <summary>

/// Button Event to load grid data.

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

void testAJAX_Click(object sender, EventArgs e)

{

      this._grid.Rows.ColumnFilters.Clear();

      this._grid.DataSource = new SampleDataSource().GetCustomers();

this._grid.DataBind();

}

 

/// <summary>

/// Create grid band

/// </summary>

/// <param name="baseTable">Table Name</param>

/// <param name="key">Data Source Key</param>

/// <param name="dataKey">Data Key</param>

/// <returns></returns>

private UltraGridBand CreateGridBand(string baseTable, string key,   

string dataKey)

{

UltraGridBand gridBand = new UltraGridBand();

      gridBand.BaseTableName = baseTable;

      gridBand.Key = key;

      gridBand.DataKeyField = dataKey;

      return gridBand;

}

 

/// <summary>

/// Create grid column

/// </summary>

/// <param name="caption">Column Caption</param>

/// <param name="dataKey">Column Data Source Key</param>

/// <returns>Grid Column</returns>

private UltraGridColumn CreateGridColumn(string caption, string   

dataKey)

{

UltraGridColumn gridColumn = new UltraGridColumn();

      gridColumn.BaseColumnName = dataKey;

      gridColumn.Header.Caption = caption;

      gridColumn.IsBound = true;

      return gridColumn;

}

 

After you have setup the grid control and the updated the button to load data into the grid. Compile and deploy the updated web part to the BIN folder of my SharePoint application. Make sure to copy the three Net Advantage assemblies you reference to the BIN folder too.

In this example we examined the challenges of getting AJAX to work with SharePoint. We built a custom web part that uses a Microsoft AJAX update panel and includes the necessary code for an update panel to work under SharePoint. The custom web part displays a list of customers in an Infragistics WebGrid and uses the AJAX cabbalists of the grid to filter data. If you like to see a fully functional Line of Business application running under SharePoint check out Pomegranate.

Sample Code: SampleAJAXWebGrid.zip.

 

Pomegranate (SharePoint) Exemplar Has Been Launched

I am excited to announce the launch of Pomegranate. Pomegranate is a SharePoint 2007/ASP.NET 2.0 exemplar (reference) application. The main component of the application is a Business Intelligence (BI) Dashboard that an insurance agent would use to track customer based Key Performance Indicators (KPI).

 

Fiquare 1: http://sharepoint.infragistics.com (Dashboard)

The dashbaord screen includes custom ASP.NET 2.0 web parts that are hosted in SharePoint (Windows SharePoint Services 3.0).   Each web part is used to display customer KPI(s) and is built using one or more of the following Net Advantage for ASP.NET controls.

Pomegranate Customer Details 

Fiquare2: WebDialogControl used to display customer details for a pending quote.

 Pomegranate WebPart

Fiquare3: Web Slider doing some AJAX magic to filter a WebChart

Over the next few weeks will be releasing additional information about Pomegranate including technical documentation about how we built it and the source code for the exemplar. If you get a chance give it a test drive and provide feedback in our forums for Exemplars.

 

 

Slides & Code Examples for IASA Talk (April 15)

I had a great time speaking at the NYC Chapter of IASA on April 15 about UI Frameworks and Patterns. If you did not get a chance to attend I am giving a similar talk at the next Philly.Net Code Camp on May 17. Check out the Philly.Net Code Camp site for more details.

Here are the Slide and Code from the UI Framework and Patterns presentation.

Speaking at the next IASA Meeting in NYC

 

I will be speaking next Tuesday (April 15) at the NYC chapter of IASA on UI Frameworks and Patterns. If you are in the area stop by as we dive into different patterns used for building enterprise applications.

Here are the details about meeting

Topic:

UI Frameworks and Patterns: MVC, MVP, or MVPOO? Are you confused yet? This session dives into the common UI patterns and concepts used for building enterprise applications and explores how they are implemented in the new ASP.Net MVC Framework.

Location:

The meeting will be held at Microsoft, 1290 Avenue of the Americas on the 6th floor. Due to heightened building security procedures you must RSVP to wzack@microsoft.com by close of business on Monday April 14, 2008 in order to be admitted

Todd Snyder

Slides from Devscovery NYC

I had a great time speaking last week in NYC at Devscovery. It was nice meeting a number of Infragistics customers and talking to them about our great products along with design best practices (Patterns, TDD, UX, etc…) and SharePoint development. I want to also thank my co-speakers: Ambrose Little, Devin Rader, and Andres Aguiar these guys are awesome and a lot of fun to work with on a daily bases. If you did not get a chance to attend I highly encourage you to check out Devscovery Redmond in August.

Slides\Demos

References to Learn More

Todd Snyder

The Birth of the Web vNext

I have seen the future and it’s in the clouds. The day I have been waiting for more than a decade has finally arrived. Yesterday at Mix 08 conference Microsoft rolled out its vision for the next web revolution. In a nutshell the vision centers on using the web as a communication hub where all kinds of rich devices (PC, Media Centers, Phones, Games Consoles, etc…) interact with each other using services hosted in the clouds.

Some would argue that this is not a revolution at all and just Microsoft’s marketing engine capitalizing on the Web 2.0 trend.  But, in reality the technologies we are using today (Web Browsers, HTML, JavaScript, HTTP, Etc…) are out dated and have been Macgyverized (w/ scotch tape and bubble gum) together into a platform that barely scratches the surface on what is needed to power the next revolution.  Don’t get wrong these technologies have served us well and most likely be with us for the foreseeable future. But the time has come to start thinking out of the box and to stop allowing the limitation of these technologies to hinder our innovations.

In my opinion there are three things at the heart of this new revolution: Great User Experience, Empowering Devices, and Ubiquitous Services.  Let’s examine each of these:

Great User Experience – This is much more than just how fancy the UI looks. It’s about the user’s overall experience using an application. This includes how easy the application is to use, how it performs, how reliable it is, and how effectively it solves a business problem/need.

Empowering Devices – Today the web is everywhere. I can view a web page from my desktop, PDA, Phone etc… This is great but unfortunately today’s technologies are pretty limited and force us to use a common denominator approach. What is really needed is a solution that allows to harness the power of each device and its unique capabilities to offer the best possible user experience.

Ubiquitous Services – The boundaries between customers, partners, and business are getting grayer every day. The application we will be building tomorrow will need to rely heavily on pluggable, versatile, and reliable architectures that allow multi parties to collaborate inside and outside of an enterprise.

In order to make all of this possible we need a new generation of software/technologies and a new set of design patterns to effectively meet the needs of customers today and tomorrow. During the MIX keynote Ray Ozzie, Scott Guthrie & company discussed several key technologies including:  Microsoft Software + Service initiative, Silverlight 2.0, ASP.Net 3.5 Extensions, and SQL Server Data Services. Couple these new technologies with what we already have available today:  .Net 3.5 (WPF, WCF, and WF), BizTalk, and SharePoint 2007 and we a rich platform that will help us power the next Web generation. Welcome to the Web vNext are you ready?

Here are some references to learn more about Microsoft vision for next generation web.

·         Microsoft SaaS Services

·         Microsoft Software-plus-Services Blueprints

·         Silverlight Blueprint for SharePoint

·         BizTalk in the Clouds

·         SQL Server Data Services - SDSS - New version of LitwareHR

·          Infragistics UX

MVC or MVP Pattern – Whats the difference?

Over the years I have mentored many developers on using design patterns and best practices. One question that keeps coming up over and over again is: What are the differences between the Model View Controller (MVC) and Model View Presenter (MVP) patterns? Surprisingly the answer is more complex than what you would suspect. Part of reasons I think many developers shy away from using either pattern is the confusion over the differences.

Before we dig into the differences let’s examine how the patterns work and the key benefits to using either one. Both (MVC & MVP) patterns have been use for several years and address a key OO principal namely separation of concerns between the UI and the business layers. There are a number of frameworks is use today that based on these patterns including: JAVA Struts, ROR, Microsoft Smart Client Software Factory (CAB), Microsoft Web Client Software Factory, and the recently announced ASP.Net MVC framework.

Model View Controller (MVC) Pattern

The MVC pattern is a UI presentation pattern that focuses on separating the UI (View) from its business layer (Model). The pattern separates responsibilities across three components: the view is responsible for rending UI elements, the controller is responsible for responding to UI actions, and the model is responsible for business behaviors and state management. In most implementation all three components can directly interact with each other and in some implementations the controller is responsible for determining which view to display (Front Controller Pattern),

Model View Presenter (MVP) Pattern

 

The MVP pattern is a UI presentation pattern based on the concepts of the MVC pattern. The pattern separates responsibilities across four components: the view is responsible for rending UI elements, the view interface is used to loosely couple the presenter from its view, the presenter is responsible for interacting between the view/model, and the model is responsible for business behaviors and state management. In some implementations the presenter interacts with a service (controller) layer to retrieve/persist the model. The view interface and service layer are commonly used to make writing unit tests for the presenter and the model easier.

Key Benefits

Before using any pattern a developers needs to consider the pros and cons of using it. There are a number of key benefits to using either the MVC or MVP pattern (See list below). But, there also a few draw backs to consider. The biggest drawbacks are additional complexity and learning curve. While the patterns may not be appropriate for simple solutions; advance solutions can greatly benefit from using the pattern. I’m my experience a have seen a few solutions eliminate a large amount of complexity but being re-factored to use either pattern.

 

·         Loose coupling – The presenter/controller are an intermediary between the UI code and the model. This allows the view and the model to evolve independently of each other.

·         Clear separation of concerns/responsibility

o    UI (Form or Page) – Responsible for rending UI elements

o    Presenter/controller – Responsible for reacting to UI events and interacts with the model

o    Model – Responsible for business behaviors and state management

·         Test Driven – By isolating each major component (UI, Presenter/controller, and model) it is easier to write unit tests. This is especially true when using the MVP pattern which only interacts with the view using an interface.

·         Code Reuse – By using a separation of concerns/responsible design approach you will increase code reuse. This is especially true when using a full blown domain model and keeping all the business/state management logic where it belongs.

·         Hide Data Access – Using these patterns forces you to put the data access code where it belongs in a data access layer. There a number of other patterns that typical works with the MVP/MVC pattern for data access. Two of the most common ones are repository and unit of work. (See Martin Fowler – Patterns of Enterprise Application Architecture for more details)

·         Flexibility/Adaptable – By isolating most of your code into the presenter/controller and model components your code base is more adaptable to change. For example consider how much UI and data access technologies have changed over the years and the number of choices we have available today. A properly design solution using MVC or MVP can support multi UI and data access technologies at the same time.

Key Differences

So what really are the differences between the MVC and MVP pattern. Actually there are not a whole lot of differences between them. Both patterns focus on separating responsibility across multi components and promote loosely coupling the UI (View) from the business layer (Model).  The major differences are how the pattern is implemented and in some advanced scenarios you need both presenters and controllers.

 

Here are the key differences between the patterns:

 

·         MVP Pattern

o    View is more loosely coupled to the model. The presenter is responsible for binding the model to the view.

o    Easier to unit test because interaction with the view is through an interface

o    Usually view to presenter map one to one. Complex views may have multi presenters.

 

·         MVC Pattern

o    Controller are based on behaviors and can be shared across views

o    Can be responsible for determining which view to display (Front Controller Pattern)

 

Hopefully you found this post interesting and it helped clarify the differences between the MVC and MVP pattern. If not, do not be discouraged patterns are powerful tools that can be hard to use sometimes. One thing to remember is that a pattern is a blue print and not an out of the box solutions. Developers should use them as a guide and modify the implementation according to their problem domain.