Wednesday, March 14, 2012

SPContext and SharePoint Factory

ASP.NET developers depend on the intrinsic  objects exposed as properties Request, Response, Session, and a few others in the code classes inherited from System.Web.UI.Page and System.Web.UI.UserControl.  Everything there is to know about the current web request and mechanism to produce an adequate response is encapsulated in these objects.

Microsoft SharePoint application developers similarly depend on the class Microsoft.SharePoint.SPContext also known as SharePoint Context.

ASP.NET developers may tap in the application foundational infrastructure  via System.Web.HttpContext class when programming web request processing logic outside of the boundaries of pages and user controls. For example, Code On Time applications are extended with business rules, which are not based on the pages. The application framework creates business rules classes in response to AJAX requests to process custom aspects of the application business logic.

For example, the following business rule written in Visual Basic will keep assigning an ever increasing generic label “New Product N” by replacing “N” with the counter whenever a new product is created in the Northwind sample.

Imports MyCompany.Data
Imports System

Namespace MyCompany.Rules

    Partial Public Class ProductsBusinessRules
        Inherits MyCompany.Rules.SharedBusinessRules

        <RowBuilder("Products", RowKind.New)> _
        Public Sub PrepareNewProductRow()
            Dim count As Nullable(Of Integer) = HttpContext.Current.Session("ProductCount")
            If Not count.HasValue Then
                count = 1
            Else
                count = count + 1
            End If
            HttpContext.Current.Session("ProductCount") = count
            UpdateFieldValue("ProductName", "New Product " + count.ToString())
        End Sub

    End Class
End Namespace

The method interacts with the user session object via Current static property of HttpContext class.

HttpContext.Current.Session("ProductCount")

SharePoint developers use exactly the same technique. The entire universe of Microsoft SharePoint server infrastructure is available via Current static property of SPContext class.

Business rule developers can take advantage of the shortcut property named Current to make interaction with ASP.NET runtime a little shorter.

Context.Session("ProductCount")

There is no shortcut that would allow access the SharePoint Context in the same fashion. As a matter of fact the application class library in a SharePoint Factory project does not even reference Microsoft SharePoint assemblies.

We have deliberately constructed the SharePoint Factory application generation project to be a solution composed of three Visual Studio projects. Only the project named WebParts is directly dependent on the SharePoint .

SharPoint Factory project in Solution Explorer

The class library of the project incorporates the entire application source code and resources including JavaScript, images, and CSS style sheets. Project named WebApp is used by the application generator to preview the application at design time.

Injection of SharePoint dependencies in either the class library or WebApp will make it impossible to preview the result of project customization. SharePoint is a 64-bit environment. Code On Time relies on IIS Express, the 32-bit application, for preview of generated web sites. These two are simply not compatible.

If you are building line-of-business web applications then having a direct SharePoint dependency can become obsolete with SharePoint Factory. In a matter of minutes your can generate an app straight from your database, customize it without having any idea about the actual intricacies of development with the rather complex SharePoint environment. Publish your application and the WebParts project will make the miracle of turning your app in a native citizen of the SharePoint Server a reality.

If you do need to take full advantage of vast capabilities of Microsoft SharePoint then with a little bit of effort you will outperform your peers and deliver amazing native SharePoint apps – SharePoint Factory will not let you down.

Right-click the WebParts project of your solution and select Set as StartUp Project option in the context menu.

Expand the class library node of the solution, right-click References. Select option Add Reference. Note that if you are developing a Visual Basic application then right-click the class library project name instead.

Adding a reference to Microsoft SharePoint to the class library project of a SharePoint Factory project

Find the SharePoint namespace on the .NET tab of Add Reference dialog and click OK.

SharePoint assembly in 'Add Reference' window

Choose File | Save All option in the Visual Studio menu.

Start the web application generator, click on the name of your project and choose Settings. Select Business Logic Layer and proceed to enable shared business rules.

Enabling shared business rules in a Code On Time web application

Click Finish button. You will end up on the Summary page. Click Cancel  to return to the start page of the generator.

Select the project name on the start page of the application generator one more time and choose Settings. Activate Web Server Configuration settings

Uncheck “Run application upon completion of code generation” option and click Finish.

Disabling automatic launching of the application upon completion of code generation in Code On Time web application generator

This time generate your project.

Select the project name on the start page and choose Develop to launch the Visual Studio development environment. You will be prompted to authorize the elevated permissions required for SharePoint development.

Double-click the shared business rules class of the class library project to open it in the text editor.

Shared Business Rules class in a Code On Time web application

Enter the following code in the class definition. The class implements a method that allows verifying if a the current SharePoint application user belong to a certain SharePoint user group.

C#

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using MyCompany.SPDemo.Data;
using Microsoft.SharePoint;

namespace MyCompany.SPDemo.Rules
{
    public partial class SharedBusinessRules : MyCompany.SPDemo.Data.BusinessRules
    {

        public bool BelongsToGroup(string name)
        {
            foreach (SPGroup group in SPContext.Current.Web.CurrentUser.Groups)
                if (group.Name.Equals(name))
                    return true;
            return false;
        }
    }
}

Visual Basic:

Imports MyCompany.SPDemoVB.Data
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Linq
Imports Microsoft.SharePoint

Namespace Rules

    Partial Public Class SharedBusinessRules
        Inherits MyCompany.SPDemoVB.Data.BusinessRules

        Public Function BelongsToGroup(ByVal name As String) As Boolean
            For Each group As SPGroup In SPContext.Current.Web.CurrentUser.Groups
                If (group.Name.Equals(name)) Then
                    Return True
                End If
            Next
            Return False
        End Function

    End Class
End Namespace

Microsoft SharePoint takes advantage of Windows Active Directory and also contributes a proprietary method of organizing users. This method empowers SharePoint administrators to create application-specific user groups that do not necessarily match the corporate domain organization.

Our method will scan the groups assigned to the current user and will return true if the match is found.

The base class BusinessRules implements the method UserIsInRole. The method allows verifying if the current user is a member of an Active Directory user group. Our new addition effortlessly enhances the framework with the ability to analyze membership in the SharePoint user groups.

Let’s take advantage of this method.

Click on the project name on the start page of the code generator and select Design. Activate the Controllers tab in Project Explorer and double-click any data controller. Our sample has been built from the Adventure Works 2008 R2 database. We will customize the HumanResources_Shift data controller. Enter the name of the custom business rule class that will handle the life-cycle of your data controller.

We have entered “ShiftBusinessRules” in the Handler property. Make sure to click OK button to save the changes.

'Handler' property of the business rules class in SharePoint Factory web application created from 'Adventure Works' database

Exit the designer and click Generate.

Return to Visual Studio – you will be prompted to reload the project.

The new file will show in the project solution under the Rules folder of the application class library.

'ShiftBusinessRules' class in SharePoint Factory project

Double-click the file name and enter the following code.

C#:

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using MyCompany.SPDemo.Data;
using System.Xml;
using System.Xml.XPath;

namespace MyCompany.SPDemo.Rules
{
    public partial class ShiftBusinessRules : MyCompany.SPDemo.Rules.SharedBusinessRules
    {
        public override bool SupportsVirtualization(string controllerName)
        {
            return true;
        }

        public override void VirtualizeController(string controllerName,
            XPathNavigator navigator, XmlNamespaceManager resolver)
        {
            if (BelongsToGroup("Team Site Owners"))
            {
                XPathNavigator grid1 = navigator.SelectSingleNode(
                    "//c:view[@id='grid1']/c:headerText", resolver);
                if (grid1 != null)
                    grid1.SetValue(
                        "Welcome, <b>Site Owner</b>. These are the shifts that you can see.");
            }
        }

        [AccessControl("", "ShiftID", "[Name]='Night'")]
        public void ShowTheNightShiftOnlyToTeamSiteOwners()
        {
            if (BelongsToGroup("Team Site Owners"))
                RestrictAccess();
        }
    }
}

Visual Basic:

Imports MyCompany.SPDemoVB.Data
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Linq
Imports System.Xml
Imports System.Xml.XPath

Namespace Rules
    
    Partial Public Class ShiftBusinessRules
        Inherits MyCompany.SPDemoVB.Rules.SharedBusinessRules

        Public Overrides Function SupportsVirtualization(controllerName As String) As Boolean
            Return True
        End Function

        Public Overrides Sub VirtualizeController(controllerName As String,
                navigator As XPathNavigator, resolver As XmlNamespaceManager)
            If (BelongsToGroup("Team Site Owners")) Then
                Dim grid1 As XPathNavigator = navigator.SelectSingleNode(
                    "//c:view[@id='grid1']/c:headerText", resolver)
                If (Not grid1 Is Nothing) Then
                    grid1.SetValue(
                        "Welcome, <b>Site Owner</b>. These are the shifts that you can see.")
                End If
            End If
        End Sub

        <AccessControl("", "ShiftID", "[Name]='Night'")> _
        Public Sub ShowTheNightShiftOnlyToTeamSiteOwners()
            If (BelongsToGroup("Team Site Owners")) Then
                RestrictAccess()
            End If
        End Sub
    End Class
End Namespace

The code will virtualize the Shift controller by changing the header text of the grid view to a custom text if the current user belongs to Team Site Owners group.

It also restricts the list of shifts to the “Night” shift only. The actual database contains “Day” and “Evening” shifts as well but there is nothing the user from the group “Team Site Owners” can do to see the data.

The default instance of Microsoft SharePoint Foundation is configured to execute in Minimal trust mode. Open “C:\inetpub\wwwroot\wss\VirtualDirectories\80\web.config” file in a text editor and make sure to that the trust is set to at least “Medium” or “High” level.

<trust level="WSS_Medium" originUrl="" />

Run the solution. Visual Studio will deploy the solution to your local SharePoint instance. Place the application web part on any site page and activate the logical page named “Human Resources | Shift”.

Activating logical page 'Human Resources | Shift' in the webpart created with SharePoint Factory and Code On Time

Save changes in the part editor and exit the page edit mode.

If you are the site owner then this is what you will see.

Only the “Night” shift is visible.  Also a custom message will be displayed at top of the Shift grid view.

User from 'Team Site Owners' group is effected by access control rules and virtualization. Only the 'Night' shift is visible.  Also a custom message will be displayed at top of the 'Shift' grid view.

The applications users that do not belong to the Team Site Owners group will not be affected by virtualization and access control rule.

No comments:

You can find more about Code OnTime Generator, Data Aquarium Framework, and other great products here.


© 2010 Code OnTime LLC. Intelligent code generation software for ASP.NET. Visit us at http://codeontime.com