With the inclusion of new tools and features in Visual Studio 2010 which directly support SharePoint development, programmers now have a much wider set of options for creating custom solutions. As with the introduction of any new approach, there are various factors which need to be considered in order to ensure that the final outcome meets the specified requirements and that all of the available functions are fully understood before embarking on a new project. The following article discusses the process of designing solutions in Visual Studio 2010 for SharePoint development, highlights several new features and techniques, and provides an overview of the various options developers should consider during project planning.
SharePoint Solutions, Projects, and Project Items
Visual Studio 2010 introduced the first native correlation between the IDE and the SharePoint framework. Included out of the box are a number of SharePoint-specific project and item types, along with capabilities for automated packaging and deployment of SharePoint solutions. At the most basic level, a SharePoint solution is no different than any other Visual Studio solution – it is simply a container for one or more projects; however, SharePoint projects are a bit more specialized. Each SharePoint project contains, at a minimum, those artifacts necessary to package and deploy the project – primarily a package which defines and creates the WSP that will be deployed to the server.
Each project may contain one or more SharePoint Project Items (SPI's), which are distinct components such as a web parts, event receivers, workflows or other SharePoint-specific artifacts. A SPI may also be somewhat generic, as in a Module which deploys a document to a library or a mapped folder which deploys files to the file system. A project may contain multiple SPI's; however, depending upon the type of SPI's employed, each one may have different packaging and deployment requirements. Some may have different implementation scopes (Site vs. Web, Web vs. Farm, etc.) and others may be incompatible based on target deployment type (Sandbox vs. Farm). When creating a solution design, it is important to determine in advance how SPI's will be grouped together and deployed.
A logical boundary for solution design is the deployment scope of the requisite Features. By default, Visual Studio will group all SPI's with the same scope into a single Feature; however, this behavior may not reflect the manner in which the developer desires the project to be deployed. For example, consider a solution which calls for the deployment of site columns, content types and custom web parts. Since these artifacts are all deployed at the same scope (Site), they could logically be grouped together into a single Feature; however, in some cases this may not be desirable. From a maintenance perspective, it doesn't make much sense to upgrade site columns and content types when adding functionality to web part assemblies or files. From an administrative point of view, columns and content types are often considered Publishing elements while web parts are more likely to be confined to collaboration/team scenarios.
Figure 1 – Grouping Artifacts by Scope
An alternate approach is to group artifacts and Features which serve a particular purpose into a single project. Publishing projects, for example, often include artifacts which span several scopes. For implementation purposes, these collectively operate as an integrated unit and often contain inherent or explicit dependencies (content types depend upon site columns, layout pages depend upon content types, etc.). The same holds true for Site Definitions, which contain artifacts which span all available scopes. Such solutions are typically upgraded and maintained as a cohesive unit.
Figure 2 – Grouping Artifacts by Purpose
NOTE: Aside from Content Types, Visual Studio 2010 does not include any Publishing artifacts by default (such as Layout Pages, Master Pages or Site Columns). These must be created manually using a Module element.
A package is comprised of all the components required for deployment of a solution (.wsp file) into SharePoint – features, assemblies, images, XML files, ASPX pages, style sheets, user controls, and so on. Once a manual process which involved editing manifest.xml and .ddf files, Visual Studio 2010 now automatically locates elements within a solution and adds them to the package. Using a visual design surface, developers can add or remove solution elements from the package to create a deployable solution that meets their requirements.
Figure 3 - The Visual Studio 2010 Package Explorer
There are also advanced packaging options which allow for the inclusion of additional assemblies, specification of safe control entries, and control over the deployment target (global assembly cache or web application). Behind the scenes, Visual Studio still generates a manifest xml file, to which additional entries can be added or, should more direct control be required, the visual designer can be circumvented and the manifest edited directly (note, however, that once this has been done the visual designer is no longer available for that project).
Figure 4 – Package Manifest Editor
NOTE: When pressing F5 to initiate the build, packaging and deployment routines, only the project set as startup will be packaged; however, multiple projects may be marked as startup in a solution.
Visual Studio makes certain assumptions about how packages should be organized, such as putting everything in the current project into a single package, which may not fit individual design objectives. While each package may be adjusted as necessary, there can only be one package per project, which limits flexibility within a single project scope. While it may be desirable to have one package for web parts and another for list definitions, if these artifacts exist within the same project (perhaps because the same developer works on both or because the web parts depend upon the lists) then by default they will be placed into the same project.
In order to overcome this default behavior, it is not uncommon to see solutions which contain a separate project for each type of artifact, i.e. Contoso.WebParts and Contoso.Lists. While this is certainly a viable design methodology, it can often lead to project proliferation and create clutter in the farm solution store. One potential solution to this problem is to group artifacts by purpose or scope and create separate projects for packaging. For example, consider a project which contains mostly collaborative artifacts (web parts, list definitions, even receivers, etc.) and supporting utility assemblies. These may be grouped together into a single project for development, but packaged separately into, say, Contoso.Collaboration and Contoso.Utilities. In this fashion, the package containing supporting assemblies, such as data access or object classes, could be updated independently of the actual SharePoint artifacts.
Figure 5 – Base Project
In this simple scenario, the base project contains all the elements that will eventually be deployed; however, no features or packages are defined within the project itself. Instead, packaging is handled by two additional projects – one for collaborative elements and one for utilities.
Figure 6 – Collaboration Project
Within the collaboration project, new features are created for the SharePoint elements in the base project. Visual Studio keeps track of the available elements within the solution and makes them available for inclusion within feature packages even though the features and elements exist in two separate projects.
Figure 7 – Collaboration Features
By default, Visual Studio organizes features based on scope. When creating the Lists feature, only the list definition and list instance are available for inclusion as the scope for these artifacts is Web; however, the WebParts feature displays both the web part and list elements when the scope is changed to Site. Although these can be deployed together in a site-scoped feature, list definitions and instances are actually activated at the web level. It is important to understand the role scoping plays when artifacts are deployed – a site administrator will not have the option to activate a specific feature at the web level if it is scoped at the site level – the feature will only appear in Site Collection Features. If granular feature activation is required (and it often is) then the features should be designed accordingly.
The collaboration project will contain a package for deployment of the required features. The packaging explorer will automatically identify the features in the project and include them in the project package; if necessary, the package manifest can be edited manually to include any additional elements.
Figure 8 – Collaboration Package
It is worth noting that in this example the dependent classes (DataAccess.cs and ListItem.cs) will be included by extension in the package as they exist within the base Contoso.SP2010 project when it is built and compiled (a safe control entry will also be included automatically). The purpose of the Utilities project, which would normally contain all non-SPI artifacts, is simply to allow for solution modifications and upgrades to the base assembly without the need to update the Collaboration package. Admittedly, this is a contrived example, but it serves to illustrate how various components can be extracted into separate packaging projects while all actual development work is performed in the base project. Note also that no features are required in this package as its only purpose is to deploy the base assembly.
Figure 9 – Utilities Project and Package
In this scenario, it will be necessary to package both the Collaboration and Utility projects prior to deployment. Visual Studio allows for multiple projects to be set as startup by modifying the project properties of the solution. First, select the base solution then select Projects > Properties from the VS menu. This will open the Property Pages dialog where the additional packaging projects can be set to startup. This will allow both projects to be packaged when F5 is pressed to initiation the build, package and deployment processes.
Figure 10 – Setting Multiple Startup Projects
There are many ways to package and deploy solutions which contain numerous artifacts. It is common to have a single solution in which multiple projects and packages exist which all serve a related purpose. By way of an additional example that reflects a real-world scenario, consider a solution for a public-facing publishing site. Following the "grouping by purpose" methodology, this solution has two main areas – the artifacts necessary for the publishing infrastructure (master pages, layout pages, content types, site columns, images, styles, and so on) and programmatic elements which provide specific pieces of functionality (in this case, web parts). The solution therefore contains two projects – one for publishing and one for web parts. They are packaged and deployed separately, allowing for ongoing maintenance and updates in one area which do not affect elements in the other area.
Figure 11 – Publishing Site Solution with Multiple Projects
This solution could be further broken down with additional projects for core elements – such as a Pages project for master and layout pages, a ContentTypes project for the content types and site columns, and so forth. These projects could be collectively packaged in a separate project created just for that purpose. This is often the case in situations where developers on a team have specific task assignments (one creates the pages, one creates the content types, etc.).
Visual Studio 2010 provides SharePoint developers with a rich set of tools for designing, packaging and deploying solution artifacts. Although the tools do a good job of automatically grouping elements together and creating the requisite deployment packages, the default organizational schema does not always reflect the desires of the developer or ongoing maintenance requirements. Team leads should give careful consideration to which methodology they will use and how the underlying collection of projects supports their decisions. There is no best practice or prescriptive guidance which determines how this will be done – each situation is different; the tools provide the capabilities to create solution structures which reflect the individual working environment and needs of the organization.