Wednesday 11 December 2013

SharePoint 2010 Sandbox solution 3 – Sandbox Proxy


As now we are aware of architecture and execution model of Sandboxed solutions, this blog should be dedicated to a sample sandbox solution. Do you think it is required? I don’t think so because it’s a very straight forward task which doesn’t motivates me to dedicate a full blog J. Instead we’ll take another topic – Sandbox Proxy or Full Trust Proxy.

If you want to execute full trust code in a sandbox solution then the only way of doing so is to write a Sandbox Proxy.



A sandbox proxy must be registered to User Code Host Service so that it can be called from a sandbox solution. Below are the steps to create and register a proxy

Step 1: Create SP Project


1.      Create an Empty  SharePoint Project

2.      Update the AssemblyInfo class and add following attribute to the class

 

using Microsoft.SharePoint.UserCode;

 

Step 2: Create Argument Class


1.      Add a new class “TestProxyArgs” with public access modifier

2.      Add following

using Microsoft.SharePoint.UserCode

 

3.      Make the class serializable and inherit from SPProxyOperationArgs class as following

[serializable]
public class TestProxyArgs : SPProxyOperationArgs { }

 

4.      Add properties that you want to pass from the proxy. Only serializable types can be used as properties here

public string TestArg { get; set; }
 

5.      Add read-only properties for the type name and assembly name of the proxy operations class (which we will create in the next step). This is required in registering the proxy operation and when invoking the operation from sandboxed code. By adding these properties to the proxy arguments class, we ensure that they are available from all locations when required.

6.      Add read-only properties for the type name and assembly name of the proxy operations class. The type name should be fully qualified and the assembly name should be the four-part strong name of the assembly

public static string ProxyOperationTypeName
{
  get
  {
    return "TestProxy.TestProxyOps";
  }
}
 
public static string ProxyAssemblyName
{
  get
  {
    return "TestProxy, Version=1.0.0.0, Culture=neutral,   
            PublicKeyToken=2dfe43bced7458f6";
  }
}

Step 3: Create Proxy Operations Class


1.      Add a new class named TestProxyOps to the project with a Execute method as following
public class TestProxyOps : SPProxyOperation {
public override object Execute (SPProxyOperationArgs args)
{
}
        }
 

2.      In the Execute method, cast the SPProxyOperationsArgs parameter to your proxy operations argument type, which in this case is TestProxyArgs.

   var proxyArgs = args as TestProxyArgs;

 

3.      Retrieve the arguments from the proxy arguments class and perform any full-trust logic

// Retrieve arguments from the proxy arguments class.
string testArg = proxyArgs.TestArg;
 
// Perform full-trust logic; for example, call a WCF service.
FullTrustMethod(testArg);
 
 

 

Step 4: Register Proxy Operation


  1. Add a new feature named TestProxyFeature to the project
  2. Make the scope of the feature to Farm
  3. Add an event receiver to the TestProxyFeature
  4. Add the following using statements to the TestProxyFeature.EventReceiver class

using Microsoft.SharePoint.Administration;

using Microsoft.SharePoint.UserCode;

 

  1. Uncomment the FeatureActivated method.
  2. In the FeatureActivated method, add the following code to retrieve the local user code service

SPUserCodeService userCodeService = SPUserCodeService.Local;

 

  1. Add the following code to create a new proxy operation type, based on your proxy operation class

var TestOperation = new SPProxyOperationType(

                            TestProxyArgs.ProxyAssemblyName,

                            TestProxyArgs.ProxyOperationTypeName);

 

  1. Add the following code to register your proxy operation type with the local user code service.

userCodeService.ProxyOperationTypes.Add(TestOperation);

userCodeService.Update();

 

  1. Deploy your sandbox proxy to the test environment.

Step 5: Use the proxy from Sandbox solution


  1. In the sandboxed solution, add a reference to the sandbox proxy assembly
  2. Create an instance o­f the proxy arguments class and set any property values

var proxyArgs = new TestProxyArgs();

proxyArgs. TestArg = "Test Arg";

 

  1. Call the SPUtility.ExecuteRegisteredProxyOperation method, passing in the assembly name of the proxy operation, the type name of the proxy operations class, and the proxy arguments instance. In this case, the assembly name and the type name are provided by static properties of the proxy arguments class, as described in step 2.

var result = SPUtility.ExecuteRegisteredProxyOperation(

 TestProxyArgs.ProxyAssemblyName,

 TestProxyArgs.ProxyOperationTypeName,

 proxyArgs);

 

That’s it. Hope this would help you guys J
Please note that I posted this blog orignally on http://aspe-it.com/blog/2013/sharepoint-2010-sandbox-solution-3-sandbox-proxy/

SharePoint 2010 Sandbox solution 4 – Solution Validation


 

The scope of a sandboxed solution is site collection and site collection administrator can activate / deactivate it. There may be some cases where the farm administrator needs to have a check before activating the solution. For such purpose Sandbox Solution Validator is used. In this episode of Sandbox solution, we will look at HOW TO IMPLEMENT SANDBOX SOLUTION VALIDATOR. Although it’s a feature which is not used often, I am still taking it up as I know how handy it can be proved when you really need to implement a rule for solution activation.

To create a solution validator you need to follow below steps

1.      Create an empty SharePoint Farm solution in VS

2.      Add a class SolutionValidator  in class file SolutionValidator.cs

3.      Inherit it from SPSolutionValidator and give a GUID to the class

 

    [Guid("DAC77CB7-7511-4E7E-8427-B6A57C5F49F7")]

    public class SolutionValidator : SPSolutionValidator

    {

    }

 

4.      Give name to the validator by defining a property in the validator class

 

private const string validatorName = "Custom Solution Validator";

 

5.      Add constructors

 

public SolutionValidator() { }

    

public SolutionValidator(SPUserCodeService userCodeService) : base(validatorName, userCodeService)

       {

           this.Signature = 1111;

      }

 

6.      Override ValidateSolution method and set the properties.Valid as true or false based on your logic. If properties.Valid is false then SCA wouldn’t be able to activate the solution

 

public override void ValidateSolution(SPSolutionValidationProperties properties)

       {

           base.ValidateSolution(properties);

   

           // Write some validation logic here an

           //properties.Valid = true;

}

 

7.      Override ValidateAssembly method and set the properties.Valid as true or false based on your logic. If properties.Valid is false then SCA wouldn’t be able to activate the solution

 

public override void ValidateAssembly(SPSolutionValidationProperties properties, SPSolutionFile assembly)

       {

                // Write some validation logic here an

           //properties.Valid = true; 

       }

 

Is it done? The answer is yes and no. The validator is ready but it is not registered yet. To register the validator to SPUC service, add following code in FeatureActivated method of the feature in which this class is added

 

SPUserCodeService sandboxService = SPUserCodeService.Local;

            SPSolutionValidator solutionValidator =

                    new SolutionValidator(sandboxService);

            sandboxService.SolutionValidators.Add(solutionValidator);

 

To unregister the validator add following code in FeatureDeactivating method

 

SPUserCodeService sandboxService = SPUserCodeService.Local;

Guid solutionValidatorId = sandboxService.SolutionValidators["Custom Solution Validator"].Id;

sandboxService.SolutionValidators.Remove(solutionValidatorId);

 

Now deploy the solution and try to activate any sandbox solution in solution gallery. You should be able to see the rules/ logic,  you wrote in validator, governing the solution activation. Enjoy J

Please Note that I posted this blog orignally on http://aspe-it.com/blog/2013/sharepoint-2010-sandbox-solution-4-solution-validation/
 

 

 

SharePoint 2010 Sandbox solution 2 – Architecture and Execution Model



In my previous blog, I took up overview of Sand boxed solutions. Now the time is to take a lift and peek into the architecture and execution model
Architecture

Sandbox solution is often called as user solution. The primary API for sandbox solution is Microsoft.SharePoint.UsserCode and the service that takes care of it is SharePoint 2010 User Code Host.

Now the first question arises is where the assemblies are deployed – The assembly is packaged in wsp file and the wsp is uploaded in the solution gallery. When, for the first time, the assembly is required – e.g. a page is accessed which contains a webpart of the sandboxed solution, then the assembly is extracted from the gallery and copied to the file system (C:\ProgramData\Microsoft\SharePoint\UCCache) of the server that is handling the request (this may not be web front end server as it is handled by User Code Host Service).

But who copies the assembly to the file system as SPUCWorkerProcess.exe can’t write to file system. The answer is SharePoint 2010 User Code Host service

Once the user session, which accessed the assembly, ends, the assembly stays in the cache for a short time. If the same assembly is required by some other session it can be accessed from the cache, if present. Otherwise again it needs to be extracted from the solution. Following is the detailed execution process


This chronicles the process of using a custom  Web Part and solution in a particular site.

  1. The SPSite admin uploads a new solution package (*.wsp) into the Solution Gallery of the SPSite.
  2. The SPSite admin "activates" the solution.  This activates the features within the solution.  Web Part files are copied into the Web Part gallery.

       As part of the activation, solution is validated using the validation framework. Custom validator can be added for example to check that only solutions signed with certain key can be activated. Customers and partners can develop their own validators based on their needs.

  1. Sometime later, a user decides to add a Web Part to their home page.  They go into Web Part edit mode, and click "Add a Web Part".  They notice the additional Web Part options, and click Add.
  2. SharePoint now checks to see if the custom webpart.dll file, which backs this Web Part, is installed into the assembly cache.  It is not.
  3. The assembly is faulted into the assembly cache; it is extracted and copied from the solution file to temporary folder in disk and loaded to memory (disk is cleaned immediately). Now the Web Part is about to be used. 
  4. It is loaded into Sandbox Code service host.
  5. Processes deliver the Web Part to be executed to the service.

 

Execution Model


We’ll see the same execution from the perspective of execution model

 


  1. An incoming request comes in for a page with a Web Part from a partial trust assembly.   This is delegated to a Web Part proxy.  The Web Part proxy then in turn calls the worker process manager, and tells it to execute the Web Part
  2. The worker process manager queries the configuration database to figure out which machine and process it should send the request to
  3. The worker process then sends the request to the user code manager on that machine
  4. The user code manager needs to ensure that the assembly backing the Web Part is locally deployed.  To do this, it reaches back into the Web Part solution package, extracts the assembly, and places it into the assembly cache
  5. Now, the SPUserCodeManager (SPUserCodeHostService.exe) delegates the request to execute the code to SPUserCodeWorkerProcess.exe. The full trust Web Part wrapper works with the instantiated process to simulate the Web Part lifecycle
  6. The Web Part itself calls into the SharePoint OM to retrieve some set of data
  7. The resulting HTML and viewstate changes are bubbled back to the hosting process, which has been synchronously waiting for this infrastructure to complete
  8. The resulting page is sent back to the user
  9. Rendered results sent back to the requester

 

So, that’s it. Hope this blog served the purpose. I’ll be back with the next part of this series soon J