How To: Enable Unity in a SharePoint Application to make Web Parts more testable

The objective of using a container (like Unity) in an application is allowing it to use Dependency Injection. The Unity container holds different elements of your application. These elements are injected into your classes when necessary. That allows your classes to be highly decoupled, because there are no hard references between them. Therefore you can unit test your application’s functionality in an easy manner.
To improve the testing capabilities of the presentation layer, the MVP (Model View Presenter) pattern is used in this example. There are different implementations of this pattern, but its main goal is to locate all the “complex” logic to update the User Interface in a presenter class, which makes your views easier to test.
This guidance describes how to enable Unity in a SharePoint application and how to test a sample Web Part using the MVP pattern.
You can download it from here.

Contents

Material

This guidance includes an extension that enables Unity to work on a SharePoint application: the Unity.Sharepoint.dll assembly. This assembly is required to implement the proposed solution.
The Unity.Sharepoint assembly contains the following classes:
  • Unity.SharePoint.SPUnityHttpApplication: entry point for the application. This class creates the Unity container and inherits from the SPHttpApplication class.
  • Unity.SharePoint.Web.UI.UserControl: a base class to make user controls support Unity dependency injection in SharePoint applications.
  • Unity.SharePoint.Web.UI.WebPart: a base class to make web parts support Unity dependency injection in SharePoint applications.
You can download the material from here.

Important: To be able to open the UnitySharePoint.sln solution you will need to have the SharePoint templates for Visual Studio 2008 installed.

The layout of the Unity.SharePoint solution is shown below.

Unity-SharePoint.png
Figure 1
Unity SharePoint solution

How To: Enable Unity in a SharePoint application

By default, SharePoint applications do not provide out-of-the-box configuration that allow developers to take advantage of the features provided by the Unity Application Block. However, through a series of steps, developers can enable SharePoint applications to support the features provided by the Unity container, including dependency injection.
The WSS object model provides the SPHttpApplication class that processes requests for SharePoint pages, controls, web services, and other resources associated with a particular SharePoint application on the Internet Information Server (IIS). By extending this class you can enable the Unity container in your application.
This topic describes the steps required to enable the Unity container in SharePoint applications:
  • 1. Open the Unity.SharePoint.sln solution file and build it. This solution contains a custom version of the SPHttpApplication class adapted to enable Unity.
  • 2. Open the Bin folder of your SharePoint application. This folder is usually located at: C:\Inetpub\wwwroot\wss\VirtualDirectories\%sharepoint application%\Bin.
  • 3. Copy the following assemblies to the Bin folder:
    • Unity.SharePoint.dll (located in the Debug folder of the Unity.SharePoint solution)
    • Microsoft.Practices.Unity.dll
    • Microsoft.Practices.ObjectBuilder2.dll
  • 4. Open your SharePoint application’s Global.asax file typically located in the folder C:\Inetpub\wwwroot\wss\VirtualDirectories\%sharepoint application%, and replace its content with the following code:
<%@ Application Language="C#" Inherits="Unity.SharePoint.SPUnityHttpApplication" %>
* 5. Save the file and close it.
  • 6. Open the Web.Config file located in the root folder of your SharePoint application and set the trust level to WSS_Medium (this is required by the Unity assemblies to work). Find the trust element under system.web.
<trust level="WSS_Medium" originUrl="" />
* 7. Save the file and close it.
  • 8. Reset the Internet Information Services by running the iisreset command.
Note: The Web Parts and User Controls you build to be used with Unity dependency injection need to inherit from the Unity.SharePoint.Web.UI.WebPart and Unity.SharePoint.Web.UI.UserControl base classes respectively.

How To: Create a Web Part that uses dependency injection

In this task, you will create a Web Part that implements the Model-View-Presenter pattern to make it more testable (Unity Application Block allows you to implement this pattern in a loosely coupled fashion by using Dependency Injection). You will also create a service and consume it from the presenter.

Create a service

This section describes how to create a service and register it into your container so it can be used by the entire application.
  • 1. Open Visual Studio 2008 and create a new solution named UnitySharePoint with a class library project named CustomWebParts.
Note: The CustomWebParts project will contain the Web Part that you will create in the next section.
  • 2. Add a new solution folder named Custom Services.
  • 3. Create a project named Services and an interface project for it named Services.Interface inside the Custom Services solution folder.
  • 4. Create a new folder named Services inside both of the previously created projects.
  • 5. Create an interface named ISampleService in the Services.Interface project inside the Services folder.
namespace Services.Interface.Services
{
    public interface ISampleService
    {
        string GetMessage();
    }
}
* 6. Add a reference to the Services.Interface project in the Services project.
  • 7. Create the SampleService class in the Services project inside the Services folder that implements the ISampleService interface.
using Services.Interface.Services;

namespace Services.Services
{
    public class SampleService : ISampleService
    {
        private int number = 0;

        public string GetMessage()
        {
            number++;
            return "I am a {0} with Unity enabled that injects a service. Called " + number.ToString() + " times.";
        }
    }
}
* 8. Sign your projects with a strong name key file (this is really important).
  • 9. Add the following attribute to the AssemblyInfo.cs file of both projects:
[assembly: System.Security.AllowPartiallyTrustedCallers]
* 10. Compile the UnitySharePoint solution.
  • 11. Copy the Services.dll and Services.Interface.dll assemblies located in the UnitySharePoint solution’s Debug folder.
  • 12. Paste them inside the Bin folder of your SharePoint application. This folder is usually located at: C:\Inetpub\wwwroot\wss\VirtualDirectories\%sharepoint application%\Bin.
  • 13. Override the AddRequiredServices method in the Global.asax file of your SharePoint application with the following code:
<%@ Application Language="C#" Inherits="Unity.SharePoint.SPUnityHttpApplication" %>
<%@ Import Namespace="Services.Services" %>
<%@ Import Namespace="Services.Interface.Services" %>
<%@ Import Namespace="Microsoft.Practices.Unity" %>

<script runat="server" language="C#">
    protected override void AddRequiredServices()
    {
        base.AddRequiredServices();

        this.Container.RegisterType<ISampleService, SampleService>(new ContainerControlledLifetimeManager()); 
    }
</script>
Now the SampleService service is registered in the Unity container and could be accessed through the ISampleService interface.

Create a Web Part

The following process explains how to create a Web Part and inject dependencies on it (presenter and service) to make it more testable.
  • 1. Add references to the following assemblies in the CustomWebParts project:
    • Microsoft.Practices.Unity.dll
    • Unity.Sharepoint.dll
    • System.Web.dll
    • Services.Interface.dll
  • 2. Add the following items to the CustomWebParts project:
    • An interface named ISimpleWebPart.
    • A presenter class called SimpleWebPartPresenter.
    • A new folder named SimpleWebPart for your Web Part.
  • 3. Replace the code in the ISimpleWebPart interface for the following one:
namespace CustomWebParts
{
    public interface ISimpleWebPart
    {
        string Message { get; set; }
        string Name { get; set; }
    }
}
* 4. Replace the code in the SimpleWebPartPresenter class for the following one:
using Services.Interface.Services;

namespace CustomWebParts
{
    public class SimpleWebPartPresenter
    {
        public ISimpleWebPart View
        { get; set; }

        public SimpleWebPartPresenter(ISampleService service)
        {
            Service = service;
        }

        public ISampleService Service
        { get; set; }

        public void OnSayHello()
        {
            View.Message = GetGreetingsMessage();
        }

        private string GetGreetingsMessage()
        {
            return string.Format("Hello, {0}",
                              string.Format(Service.GetMessage(), View.Name));
        }
    }
}
* 5. Create a class named SimpleWebPart inside the SimpleWebPart folder.
Note: You can also use the SharePoint templates to create your Web Parts if you have them installed.
  • 6. The following is the code to place in the SimpleWebPart class inside the SimpleWebPart folder.
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Runtime.InteropServices;
using Microsoft.Practices.Unity;

namespace CustomWebParts.SimpleWebPart
{
    [Guid("a270e25d-d15f-4a22-adfa-a1dbe0b02982")]
    public class SimpleWebPart : Unity.SharePoint.Web.UI.WebPart, ISimpleWebPart
    {
        Button btnSayHello;
        Label lblMessage;

        public string Message
        {
            get { return lblMessage.Text; }
            set { lblMessage.Text = value; }
        }

        public string Name { get; set; }

        public SimpleWebPart()
        {
            this.ExportMode = WebPartExportMode.All;
        }

        private SimpleWebPartPresenter _presenter;
        
        [Dependency]
        public SimpleWebPartPresenter Presenter 
        {
            get { return _presenter; }
            set
            { 
                _presenter = value;
                _presenter.View = this;
            } 
        }

        protected override void Render(HtmlTextWriter writer)
        {
            btnSayHello.RenderControl(writer);
            
            writer.WriteLine("<br/><strong>");
            lblMessage.RenderControl(writer);
            writer.Write("</strong>");
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
           
            btnSayHello = new Button();
            btnSayHello.ID = "btnSayHello";
            btnSayHello.Text = "Say Hello";
            btnSayHello.Click += new EventHandler(btnSayHello_Click);
            lblMessage = new Label();
            lblMessage.ID = "lblMessage";
            lblMessage.Text = "";

            this.Controls.Add(btnSayHello);
            this.Controls.Add(lblMessage);
        }

        public void btnSayHello_Click(object sender, EventArgs e)
        {
            this.Name = "Web Part";
            Presenter.OnSayHello();
        }
    }
}
|Note: The class must inherit from Unity.SharePoint.Web.UI.WebPart, so it can get dependencies injected; also note how the presenter is injected into the view).|
  • 7. Sign the CustomWebParts project with a strong name key file (this is really important).
  • 8. Add the following attribute to the AssemblyInfo.cs file in the CustomWebParts project:
[assembly: System.Security.AllowPartiallyTrustedCallers]
Having performed the previous steps your Solution Explorer should look like the one in Figure 2:
SampleImplementation.png
Figure 2
Solution explorer after the View and the Presenter are created.

How To: Unit Test the Web Part

The following procedure will help you create a test project to test the created presenter. This can be easily achieved given that, as explained in the introduction of this document, your web parts and services can be mocked, allowing you to concentrate only in the presenter’s logic. The mocks will be obtained by implementing the interfaces you’ve previously created, both for the Web Part and the Service.
  • 1. In the Solution Explorer, right click the UnitySharePoint solution, point to Add and click New Project.
  • 2. Select C# language and pick Test type. Figure 3 shows the Add New Project dialog.
TestProject.png
Figure 3
Create a new test project form
  • 3. Change the project’s name to CustomWebParts.Tests.
  • 4. Add a reference to the Services.Interface and CustomWebParts projects.
  • 5. Add a folder named Mocks inside the test project.
  • 6. Add a new class named MockSampleService to the Mocks folder. It will be used when testing the presenter to replace the service implementation.
  • 7. Replace the code in the MockSampleService class with the following:
using Services.Interface.Services;

namespace CustomWebParts.Tests.Mocks
{
    public class MockSampleService : ISampleService
    {
        public bool MessageCalled = false;

        public string GetMessage()
        {
            MessageCalled = true;
            return "I am a Mock Service";
        }
    }
}
* 8. Create a class named MockSimpleWebPart inside the Mocks folder. It will be used when testing the presenter to replace the web part implementation.
  • 9. Place the following code in the MockSimpleWebPart class:
using CustomWebParts;

namespace CustomWebParts.Tests.Mocks
{
    public class MockSimpleWebPart : ISimpleWebPart
    {
        public bool MessageCalled = false;
        public bool NameCalled = false;
        
        public string Message
        {
            get
            {
                MessageCalled = true;
                return "Hello";
            }
            set { MessageCalled = true; }
        }

        public string Name
        {
            get
            {
                NameCalled = true;
                return "John Doe";
            }
            set { NameCalled = true; }
        }
    }
}
* 10. Create a new UnitTest class named SimpleWebPartPresenterTestFixture in the CustomWebParts.Tests project. To do this, select the Unit Test template at the Add New Item dialog.
  • 11. Replace the code in your presenter’s test fixture with the following one:
using CustomWebParts;
using CustomWebParts.Tests.Mocks;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace CustomWebParts.Tests
{
    [TestClass()]
    public class SimpleWebPartPresenterTestFixture
    {
        private MockSimpleWebPart _view;
        private MockSampleService _service;

        //This test method checks if a message was called when
        //the OnSayHello method is executed.

        [TestMethod()]
        public void OnSayHelloTest()
        {
            SimpleWebPartPresenter presenter = GetSimpleWebPartPresenter();

            presenter.OnSayHello();

            Assert.IsTrue(_view.MessageCalled);
            Assert.IsTrue(_view.NameCalled);
            Assert.IsTrue(_service.MessageCalled);
        }

        private SimpleWebPartPresenter GetSimpleWebPartPresenter()
        {
            _view = new MockSimpleWebPart();
            _service = new MockSampleService();

            SimpleWebPartPresenter presenter = new SimpleWebPartPresenter(_service);
            presenter.View = _view;

            return presenter;
        }
	}
}
* 12. Run the Unit Test, it should pass.

How To: Deploy the Web Part

The following procedure describes how to deploy the SimpleWebPart and SampleService you created in your SharePoint application. As a result, you will be able to consume the service and the web part along the entire application.
Before performing the next steps you will need to Enable Unity in your SharePoint application.
  • 1. Open the Web.config file of your SharePoint application typically located at the root folder of your SharePoint application.
  • 2. Find out the PublicKeyToken of your CustomWebPart project. You can use the command sn.exe -T CustomWebParts.dll from the Visual Studio 2008 Command Prompt to get it.
  • 3. Add the following line under the configuration/SharePoint/SafeControl element, setting the right PublicKeyToken and Namespace attributes:
<SafeControl Assembly="CustomWebParts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=MyPublicKeyToken" 
Namespace="MyNamespace" TypeName="*" Safe="True" AllowRemoteDesigner="True" />
* 4. Build the UnitySharePoint solution.
  • 5. Open the Bin folder of your SharePoint application. This folder is usually located at: C:\Inetpub\wwwroot\wss\VirtualDirectories\%sharepoint application%\Bin.
  • 6. Copy the following assemblies to the Bin folder of your SharePoint application:
    • CustomWebParts.dll
    • Services.dll
    • Services.Interface.dll
  • 7. Open the SharePoint web site in a browser to set up the Web Part.
  • 8. Go to the Site Actions menu and select Site Settings.
  • 9. Open the Web Parts links in the Gallery section.
  • 10. Click the New button and check in the list the previously created web part (CustomWebParts.SimpleWebPart.SimpleWebPart). Then click the Populate Gallery button.
  • 11. Go back to your home site and go to the Site Actions menu again, but this time select Edit Page.
  • 12. Click in the Add a Web Part button in the panel where you want to place the web part. The Add Web Parts dialog will be shown.
  • 13. In the Miscellaneous section check the SimpleWebPart and add it.
  • 14. Open the edited web site in a browser. The resulting page will be like the one shown in Figure 4.
website1.png
Figure 4
The created SharePoint Web Part that uses Unity dependency injection.
  • 15. Press the Say Hello button. You should see a display like the one shown in Figure 5.
website2.png
Figure 5
The created SharePoint Web Part using a service.

Outcome

After performing all tasks in this document you have:
  • Enabled the Unity container in your SharePoint application.
  • Implemented the MVP pattern in a Web Part.
  • Registered and used a service that was injected in your presenter class.
  • Created a unit test for your presenter class.

Last edited Sep 8, 2008 at 7:06 PM by mconverti, version 4

Comments

No comments yet.