Share via


Programmatically Block Sandboxed Solutions in SharePoint 2010

You can verify and block sandboxed solutions by using the Microsoft SharePoint 2010 API. In this article, you learn how to implement this functionality in a real-world scenario by using farm Features.

Applies to: Business Connectivity Services | Open XML | SharePoint Designer 2010 | SharePoint Foundation 2010 | SharePoint Online | SharePoint Server 2010 | Visual Studio

Provided by:  Yogesh Joshi, Microsoft Corporation

Warning

The Sandbox Solution framework provides a mechanism for executing user-provided code outside of the IIS worker process. The Sandbox Solution framework should not be used as a mechanism for enforcing security boundaries when executing user code. Sandbox Solutions are not supported as a security boundary with user code, especially code of unknown origin. We advise against executing Sandbox Solutions of unknown origins.

Click to get code  Download the code sample

Introduction to SharePoint 2010 Sandboxed Solutions

A sandboxed solution is a new concept in SharePoint Foundation 2010 that enables site collection users to upload their own custom code solutions. All sandboxed solutions are stored in a solution gallery. Facilities are provided to help server farm administrators monitor and validate solutions that have been uploaded to these galleries. You can monitor performance by measuring CPU execution time, memory consumption, and database query time. You can also monitor other aspects of operations, including abnormal termination, critical exceptions, unhandled exceptions, and data marshaling size.

This article assumes that you have a basic knowledge of sandboxed solution development and usage. For detailed information about developing sandboxed solutions, see Sandboxed Solutions Resource Center

Programmatically Blocking Sandboxed Solutions

SharePoint 2010 provides an API to extend the sandboxed solution validation process. This enables farm administrators to have more granular control over solutions that are being uploaded and activated over the site collection. You can automatically validate solutions by writing custom solution validators and deploying them over the farm. Deployment can be done by using farm-level Features. Each solution validator that is deployed over the farm is called when a solution is activated.

Solutions are validated each time they are activated. Solution validators can analyze the entire WSP file contents and determine whether the solution is valid or not. For example, while activating solutions, you might want to check whether the solution’s assemblies are signed by using a specific certificate or by your own licensing mechanism. You may also want to block solutions that contain specific types of files, such as ECMAScript (JavaScript, JScript) files.

Creating Custom Sandboxed Solution Validators

In this section, you create a sandboxed solution validator. The procedures in this section assume that you have a development environment where SharePoint 2010 is installed and configured, Microsoft Visual Studio 2010 is installed, and the currently logged-on user has administrative rights on the SharePoint 2010 environment for deployment.

Note

To download the Contoso.SharePoint.Administration solution that is used in this example, see Programmatically Block Sandboxed Solutions in SharePoint 2010.

All custom solution validators are derived from the SPSolutionValidator class. In this example, you create a derived class named SolutionValidator and use the following methods of the SPSolutionValidator base class:

The SPSolutionValidationProperties object is passed to the ValidateSolution method. This object contains information about the activated solution. The following properties are used in the custom validator:

  • Files property: Property of the SPSolutionValidationProperties object that contains the collection of SPSolutionFile objects.

  • Valid property: A flag to indicate whether the current solution is valid.

  • ValidationErrorMessage property: String property to specify a custom error message to be displayed on a SharePoint 2010 error page.

  • ValidationErrorUrl property: URL of the custom error page that is displayed for a solution validation failure.

After the validator development is complete, the validator must be registered with SPUserCodeService. You do this by adding the solution validator object to the SPUserCodeService.SolutionValidators collection. In the example, on Feature activation, the custom validator is registered in the FeatureActivated method and removed in the FeatureDeactivating method of the EventReceiver object.

The following steps create a custom solution validator in Microsoft Visual Studio 2010.

Note

You can inherit from the SPSolutionValidator class to write your own logic for validating sandboxed solutions when they are activated. However, administrators can block certain solutions from Central Administration by using the Manage User Solutions option of the System Settings item. This article discusses blocking sandboxed solutions while they are being activated on a site collection. The code provided here does not add these solutions under the Blocked Solutions List in SharePoint Central Administration.

To create a basic validator solution

  1. In Visual Studio 2010, click New Project. Expand the SharePoint node, click 2010, and then click Empty SharePoint Project. Name the project Contoso.SharePoint.Administration, and click OK.

  2. In the SharePoint Customization Wizard, select the local SharePoint 2010 site that will be used for debugging, and then choose Deploy as a farm solution, as shown in Figure 1. Click Finish.

    Figure 1. Specify the deployment method and SharePoint site

    Specify the deployment method and SharePoint site

  3. In Solution Explorer, under the Contoso.SharePoint.Administration project, right-click the Features node, and then click Add Feature.

  4. After the new Feature is created, add the title and description of the Feature, as shown in Figure 2. In the Scope drop-down list, select Farm.

    Figure 2. Specifying the title, description, and scope of the Feature

    Specify the title description and scope of feature

  5. Rename the Feature folder to SandboxedSolutionValidator, as shown in Figure 3.

    Figure 3. Renaming the Feature folder

    Rename the feature folder

  6. In Solution Explorer, right-click the Contoso.SharePoint.Administration project, point to Add, and then select Class.

  7. In the Add New Item dialog box, select the Class item, specify SolutionValidator.cs as the name, and then click Add.

  8. Next, you need to specify a GUID attribute. This attribute is used for registering and removing the custom solution validator with SPUserCodeService. On the Tools menu, click Create GUID.

  9. In the Create GUID dialog box, select option 5 to create a GUID in the attribute format, click Copy, and then click Exit, as shown in Figure 4.

    Figure 4. Creating a new GUID in attribute format

    Create a new GUID in attribute format

  10. In the code screen, paste the GUID as an attribute in the SolutionValidator class. Also, add a reference to the System.Runtime.InteropServices namespace, as shown in Figure 5.

    Figure 5. Pasting the GUID as an attribute

    Paste the GUID as an attribute

  11. Add the following code to the SolutionValidator class. The Signature property is used by SharePoint 2010 to check whether the validator has changed. In this example, you can use 10000 as the value. However, in a production environment, you should choose a unique number that represents the version/hash or specific information about the validator.

            /// <summary>
            /// Initializes a new instance of the SolutionValidator class. 
            /// </summary>
            public SolutionValidator()
            {
            }
    
            /// <summary>
            /// Initializes a new instance of the SolutionValidator class. 
            /// </summary>
            /// <param name="sandboxService">Sandboxed service instance.</param>
            public SolutionValidator(SPUserCodeService sandboxService) :
                base("ContosoSandboxedSolutionValidator", sandboxService)
            {
                Signature = 10000;
            }
    
            /// <summary>
            /// Checks if the solution has JavaScript files.
            /// </summary>
            /// <param name="properties">Solution validation properties.</param>
            public override void ValidateSolution(SPSolutionValidationProperties properties)
            {
                base.ValidateSolution(properties);
    
                bool isValidSolution = true;
    
                // Check if the solution file contains any JavaScript files.
                foreach (SPSolutionFile file in properties.Files)
                {
                    if (file.Location.EndsWith(".js", StringComparison.OrdinalIgnoreCase))
                    {
                        isValidSolution = false;
                        properties.ValidationErrorMessage = "Contoso IT : Sandboxed solutions should not contain JavaScript files.";
                        break;
                    }
                }
    
                properties.Valid = isValidSolution;
            }
    
  12. Right-click the SandboxedSolutionValidator Feature, and then select Add Event Receiver.

  13. Add the following code to the event receiver class, and then add references to the associated namespaces.

            /// <summary>
            /// Register Contoso Solution Validator.
            /// </summary>        
            public override void FeatureActivated(SPFeatureReceiverProperties properties)
            {
                SPUserCodeService sandboxService = SPUserCodeService.Local;
                SPSolutionValidator contosoSolutionValidator = new SolutionValidator(sandboxService);
                sandboxService.SolutionValidators.Add(contosoSolutionValidator);
            }
    
            /// <summary>
            /// Remove Contoso Solution Validator.
            /// </summary>        
            public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
            {
                SPUserCodeService sandboxService = SPUserCodeService.Local;
                Guid contosoSolutionValidatorId = typeof(SolutionValidator).GUID;
                sandboxService.SolutionValidators.Remove(contosoSolutionValidatorId);
            }
    
  14. In Solution Explorer, right-click the Contoso.SharePoint.Administration project, and then select Deploy. After the custom solution validator is deployed, it is registered with SPUserCodeService.

Testing Sandboxed Solution Validators

In this section, you test a custom validator in Visual Studio 2010, and by using the Activate option in the Site Collection Solutions Gallery. In the first test method, you create a new sandboxed solution with one JavaScript file.

Note

To download the SolutionWithJavaScript solution that is used in this example, see Programmatically Block Sandboxed Solutions in SharePoint 2010.

To test a custom validator by using Visual Studio 2010

  1. In Solution Explorer, right-click the Contoso.SharePoint.Administration solution, point to Add, and then select New Project.

  2. Create an Empty SharePoint 2010 project, and name it SolutionWithJavaScript.

  3. Specify the URL of the target site for debugging, and then choose Deploy as a sandboxed solution, as shown in Figure 6.

    Figure 6. Selecting the site and deployment type

    Select the site and deployment type

  4. In Solution Explorer, right-click the SolutionWithJavaScript project, point to Add, and then click New Item.

  5. In the Add New Item dialog box, select Module. Name it JavaScripts, and then click Add.

  6. In Solution Explorer, right-click the JavaScripts module, point to Add, and then click New Item.

  7. In the Add New Item dialog box, click Web, and then select JScript File. Name the file HelloWorld.js.

  8. Add the code shown in Figure 7 into the JavaScript file, and then save the file.

    Figure 7. Writing some code in the JavaScript file

    Write some code in the JavaScript file

  9. In Solution Explorer, right-click the SolutionWithJavaScript project, and choose Deploy. The solution is deployed to the Site Solutions Gallery. Visual Studio 2010 then tries to activate the solution, unsuccessfully. Observe the output window error list, as shown in Figure 8.

    Figure 8. Error list in Visual Studio

    Observe the error list

You can also test the sandboxed solution validator by trying to activate the solution from the SharePoint Site Collection Solution Gallery.

To test the validator by using the Activate option in SharePoint

  1. Log on as the site collection administrator on the SharePoint 2010 site.

  2. Navigate to the Site Settings page. Under the Galleries section, choose the Solutions link.

  3. Choose Upload Solution, and then upload the SolutionWithJavaScript.wsp file, if it’s not already uploaded.

  4. In the solutions list, choose SolutionWithJavaScript.wsp.

  5. Click the solution, and on the ribbon, in the Commands section, choose Activate.

    As you try to activate the solution, the solution validator’s ValidateSolution method is called by the SharePoint 2010 object model. The code sets SPSolutionValidationProperties.IsValid flag to False. If there are any JavaScript files in the WSP, the solution validation fails. The custom error message is set using the ValidationErrorMessage property of SPSolutionValidationProperties class, and it is displayed on the SharePoint 2010 error page, as shown in Figure 9.

    Figure 9. Solution validation error message

    Solution validation error message

Adding a Custom Validation Error Page

In the previous section, you saw that the validation error message is displayed on the out-of-the-box SharePoint 2010 error page. If there is a requirement to display a custom error page, you can use the ValidationErrorUrl property of the SPSolutionValidationProperties class. In the following steps, you add a custom error page to the custom solution validator.

To add a custom error page to the validator

  1. In Solution Explorer, right-click the Contoso.SharePoint.Administration project, point to Add, and then select New Item.

  2. In the Add New Item dialog box, expand the SharePoint node, choose 2010, and then choose Application Page. Name the page ContosoError.aspx, and then click OK.

  3. Add the following markup to the .aspx page.

    <%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
    <%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
    <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
    <%@ Import Namespace="Microsoft.SharePoint" %>
    <%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ContosoError.aspx.cs" Inherits="Contoso.SharePoint.Administration.Layouts.Contoso.SharePoint.Administration.ContosoError" DynamicMasterPageFile="~masterurl/default.master" %>
    
    <asp:Content ID="PageHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
    
    </asp:Content>
    
    <asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
    <h1>Contoso IT Department</h1>
    <br />
    Sandboxed Solutions should not contain JavaScript files.
    <br />
    <br />
    Please visit <a href="https://www.contoso.com/Pages/DevelopingSandboxedSolutions.aspx">Developing Sandboxed Solutions</a> page for more information.
    </asp:Content>
    
    <asp:Content ID="PageTitle" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
    Error
    </asp:Content>
    
    <asp:Content ID="PageTitleInTitleArea" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server" >
    Error
    </asp:Content>
    
  4. Modify the SolutionValidator class code. Inside ValidateSolution method, assign the ValidationErrorUrl property as shown in the following code.

            /// <summary>
            /// Checks if the solution has JavaScript files.
            /// </summary>
            /// <param name="properties">Solution validation properties.</param>
            public override void ValidateSolution(SPSolutionValidationProperties properties)
            {
                base.ValidateSolution(properties);
    
                bool isValidSolution = true;
    
                // Check if the solution file contains any JavaScript files.
                foreach (SPSolutionFile file in properties.Files)
                {
                    if (file.Location.EndsWith(".js", StringComparison.OrdinalIgnoreCase))
                    {
                        isValidSolution = false;
                        properties.ValidationErrorMessage = "Contoso IT : Sandboxed solutions should not contain JavaScript files.";
                        properties.ValidationErrorUrl = "/_layouts/Contoso.SharePoint.Administration/ContosoError.aspx";
                        break;
                    }
                }
    
                properties.Valid = isValidSolution;
            }
    
  5. In Solution Explorer, right-click the Contoso.SharePoint.Administration project, and then select Deploy.

  6. Log on as the site collection administrator.

  7. Navigate to the Site Settings page, and then in the Galleries section, choose the Solutions option.

  8. In the solutions list, choose SolutionWithJavaScript.wsp.

  9. Select the solution, and on the ribbon, choose Activate. The solution fails validation and the custom error page is displayed, as shown in Figure 10.

    Figure 10. Custom validation error page

    Custom validation error page

Conclusion

SharePoint 2010 provides an API to extend the sandboxed solution validation process. This has the benefit of enabling you to have greater control over solutions that are uploaded and activated over the site collection. By using this API, you can write custom validator solutions for your own organization.

Additional Resources