How to: Create a Full-Trust Proxy Operation
This topic describes how to create a full-trust proxy operation, deploy it, and call it from a sandboxed solution in Microsoft SharePoint 2010.
Applies to: SharePoint Foundation 2010
For details about the steps in the procedures in this topic, together with an example, see Walkthrough: Creating and Calling a Full-Trust Proxy Operation.
Creating a Full-Trust Proxy Operation in SharePoint 2010
The major steps to creating and using a full trust proxy operation are as follows.
In a farm solution project, create a class that is derived from SPProxyOperation and override its Execute method.
In the same project, create a class that is derived from SPProxyOperationArgs. An object of this class will be passed by the sandboxed solutions to the Execute method of the custom operation.
Create code that registers the proxy operation with the SharePoint Foundation Sandboxed Code Service. This is typically done in the FeatureActivated handler of a Feature Receiver deployed to Farm scope.
Deploy the farm solution.
In a sandboxed solution project, create a component that will call the proxy operation and consume what it returns.
Deploy the sandboxed solution.
To create the SPProxyOperation class
In Microsoft Visual Studio, start an Empty SharePoint Project. Make it a farm solution, not a sandboxed solution.
In Solution Explorer, right-click the project name, and select Properties to open a project settings dialog box. On the Application tab, specify a namespace that complies with the guidance in Names of Namespaces and an assembly name.
Each time that you redeploy the assembly that contains the proxy operation class, you must restart the Microsoft SharePoint Foundation Sandboxed Code service. (This is called the SharePoint 2010 User Code Host service in the Windows Services user interface.) To automate this task, follow these steps:
In the property settings dialog box, click the SharePoint tab.
In the Post-deployment Command Line text box, add the following two lines.
net stop SPUsercodeV4 net start SPUsercodeV4
On the toolbar, click the Save all files button.
Add references to the project as needed. What you have to reference depends on which assemblies you call in your override of the Execute method in a later step.
Add a C# or Microsoft Visual Basic class code file to the project. The class will automatically be declared in the namespace that you chose in an earlier step.
In the file, add a using (Imports in Microsoft Visual Basic) statement for the Microsoft.SharePoint.UserCode namespace.
Add more using statements as needed. What namespaces must be used depends on what classes you call in your override of the Execute method in a later step. You almost always need using statements for Microsoft.SharePoint and very often for Microsoft.SharePoint.Administration.
Modify the class declaration so that the class inherits from SPProxyOperation.
Add a demand for the SharePoint object model permission to the declaration of the class. We recommend this because the assembly will receive the AllowPartiallyTrustedCallersAttribute in a later step, and you do not want all partially trusted callers to obtain access to the SharePoint object model via the proxy operation class. (For more information, see Best Practices with SharePoint Foundation.) The following is an example.
[Microsoft.SharePoint.Security.SharePointPermission(System.Security.Permissions.SecurityAction.LinkDemand, ObjectModel=true)] public class MyProxyOperation : SPProxyOperation { }
Override the Execute method. Use it to implement the functionality that you want the operation to perform for the sandboxed solutions that call it. Note that the method returns Object. Therefore, you can return any serializable type that you want. It must be serializable so that it can be passed across processes. All common system types, in addition to system collection and generic collection types, are serializable. Calling code must convert the returned object to the more specific type. For information about how to return a custom type, see "To create a custom serialized type for the return value of the operation" later in this topic.
If the operation returns no data to the caller, your override should return null.
Typically, you begin an override of this method by verifying that the parameter that is passed to it is not null, and then casting that parameter to the derived class that you create in the next procedure. The following is an example.
public override object Execute(SPProxyOperationArgs args) { if (args != null) { MyProxyOperationArgs myArgs = args as MyProxyOperationArgs; // TODO: Implement the functionality of the proxy operation. // Return null or an object of any serializable type. } return null; }
Of course, if your proxy operation does not need any data passed to it from the caller, the args parameter can be null, and you can skip the next procedure.
To create an SPProxyOperationArgs class
Declare a class that inherits from SPProxyOperationArgs, and decorate it with the SerializableAttribute attribute so that it can be passed across processes.
Add a demand for the SharePoint object model permission to the declaration of the class.
Declare public properties or fields to contain the data that is passed to the proxy operation.
Declare a constructor, and implement it to initialize the properties and fields. The following is an example.
[Serializable] [Microsoft.SharePoint.Security.SharePointPermission(System.Security.Permissions.SecurityAction.LinkDemand, ObjectModel=true)] public class MyProxyOperationArgs : SPProxyOperationArgs { public MyProxyOperationArgs (string title) { Title = title; } public string Title {get; set; } }
To create a custom serialized type for the return value of the operation
If your override of the Execute method returns a custom type (boxed as an Object), declare and implement the custom class (or struct) in the same code file as the proxy operation and proxy arguments classes.
The class or struct must be serializable so that the object box can be passed across processes. Therefore, add the [SerializableAttribute] to the declaration. If the declaration is not decorated in this manner, your override of the Execute method will throw an exception. For an example of this technique, see Walkthrough: Creating and Calling a Full-Trust Proxy Operation.
To register the proxy operation with the sandboxed code service
Add a Feature to the Visual Studio project, and set its scope to Farm.
Right-click the Feature, and select Add Event Receiver.
In the code file that is created by the previous step, override the FeatureActivated handler. The implementation code is almost always identical to the following, where MyProxyOperation is the class that you created in the previous procedure.
public override void FeatureActivated(SPFeatureReceiverProperties properties) { Type type = typeof(MyProxyOperation); SPProxyOperationType proxyOperationType = new SPProxyOperationType(type.Assembly.FullName, type.FullName) SPUserCodeService userCodeService = SPUserCodeService.Local; userCodeService.ProxyOperationTypes.Add(proxyOperationType); userCodeService.Update(); }
The use of Type in this example is only one of many ways of getting a reference to an assembly name and type name in Microsoft .NET Framework. The most important point is that you must call the IList.Add(Object) method of the SPUserCodeService.ProxyOperationTypes property to register the proxy operation with the sandboxed code service.
Tip
Visual Studio tokens, such as "$SharePoint.Project.AssemblyFullName$", cannot be used in compilable files.
It is a good practice to always override the FeatureDeactivating handler to reverse what your code does in the FeatureActivated handler. The implementation code is almost always identical to the following.
public override void FeatureDeactivating(SPFeatureReceiverProperties properties) { Type type = typeof(MyProxyOperation); SPProxyOperationType proxyOperationType = new SPProxyOperationType(type.Assembly.FullName, type.FullName) SPUserCodeService userCodeService = SPUserCodeService.Local; userCodeService.ProxyOperationTypes.Remove(proxyOperationType); userCodeService.Update(); }
To build and deploy the assembly
Because the assembly is going to be called from sandboxed solutions, it must have the AllowPartiallyTrustedCallersAttribute. Open the AssemblyInfo.cs (or AssemblyInfo.vb) file, and add the following line at the end.
[assembly: AllowPartiallyTrustedCallers]
By default, Visual Studio will configure the package manifest to deploy the assembly to the global assembly cache. Leave this at the default. Proxy operation assemblies must be deployed to the global assembly cache.
Build the project, package it, add the solution to the farm Solution Gallery, deploy the solution, and activate the feature in it. If you are using Visual Studio, selecting Deploy on the Build menu does all of this. If you added the Post-deployment Command Line as instructed in an earlier step, the sandboxed code host service is also restarted automatically.
Note
When you distribute your completed solution package, inform farm administrators that they must restart the Microsoft SharePoint Foundation Sandboxed Code service after the package is deployed.
Calling a Proxy Operation from a Sandboxed Solution
Any component in a sandboxed solution that includes imperative code can call the proxy operation. Typically, it is called from the CreateChildControls method of a Web Part. There are four things the developer of the sandboxed solution must know about the proxy operation before creating the sandboxed solution.
The fully qualified name of the proxy operation class.
The full four-part name of the assembly that contains the proxy operation class.
The type of the class, if any, derived from SPProxyOperationArgs and its members, and what its constructor does.
The specific type of object, if any, returned by the Execute method of the proxy operation class.
To call the proxy from a sandboxed solution
Begin a new Visual Studio project of any type that can be deployed as a sandboxed solution.
Add a reference to the assembly that contains the proxy operation class by using these steps:
In Solution Explorer, right-click the References folder, and then select Add reference.
In the Add Reference dialog box, open the Browse tab.
Browse to C:\Windows\assembly\GAC_MSIL\assembly name\version folder\, select the assembly, and then click OK.
Add a using (Imports in Visual Basic) statement for the namespace of the class you derived from SPProxyOperationArgs in an earlier procedure.
Determine where in the code the proxy operation should be called. This depends on the kind of components in the solution. For example, the proxy operation might be called in the CreateChildControls method of a Web Part. Or it might be called in the FeatureUpgrading handler of a Feature Receiver.
If the proxy operation requires a parameter derived from SPProxyOperationArgs, call the constructor of the derived class. The following is an example, where MyProxyOperationArgs is the derived class, and it has a property named Title that is initialized by its constructor.
MyProxyOperationArgs args = new MyProxyOperationArgs("Admiral");
Call the static method SPUtility.ExecuteRegisteredProxyOperation, and pass the following to it as parameters:
The full four-part name of the assembly that contains the proxy operation class. (Separate the four parts with commas, but do not put the values of the Version, Culture, and PublicKeyToken attributes of the name in either single or double quotation marks. For an example, see Walkthrough: Creating and Calling a Full-Trust Proxy Operation.)
The fully qualified name of the proxy operation class.
The object constructed in the previous step (or null).
The ExecuteRegisteredProxyOperation method is a wrapper around the overridden Execute(SPProxyOperationArgs) method of the derived proxy operation class. The SPUtility object uses the first two parameters to verify that an assembly and class with exactly those names is registered with the sandboxed code service. If they are, the SPUtility object calls the override of the Execute(SPProxyOperationArgs) method and passes the third parameter to it. The object returned by the Execute method is then returned by the ExecuteRegisteredProxyOperation method to the sandboxed solution that called it.
Cast or convert the Object object that is returned by the ExecuteRegisteredProxyOperation method to its specific type.
The following is an example of the last two steps.
string proxyOperationAssembly = "four-part assembly name"; string proxyOperationType = "fully qualified proxy operation class name"; Object object = SPUtility.ExecuteRegisteredProxyOperation(proxyOperationAssembly, proxyOperationType, args); String returnedString = (String)object;
Complete the sandboxed solution, and then build and package it.
The sandboxed solution is now ready to be deployed to any site collection in the same farm to which the proxy operation was deployed and registered.
See Also
Tasks
Walkthrough: Creating and Calling a Full-Trust Proxy Operation
Concepts
Sandboxed Solutions in Partnership with Full-Trust Proxies in SharePoint 2010
Other Resources
Sandboxed Solutions in SharePoint 2010
Sandboxed Solutions Resource Center | SharePoint 2010