When describing execution models, the term hybrid approaches refers to applications that run in the sandbox yet can call out to full-trust code through various mechanisms. In other words, hybrid approaches combine components that execute in the sandbox environment with components that run with full trust and are deployed with multiple solutions. Essentially, you can think of a hybrid approach as two (or more) distinct, loosely coupled components. The sandboxed component is deployed in a SharePoint solution package (WSP) to a site collection solutions gallery, and the full trust component is deployed in a WSP to the server farm. These components are typically developed in isolation, often at different times, and a single full-trust component can be consumed by multiple sandboxed applications. In many environments, the full-trust components are built or validated by the central IT team in order to make them available to multiple sandboxed solutions.
Because a hybrid approach involves creating a sandboxed solution and a full trust solution, it is important to fully understand the sandbox execution model and the full-trust execution model before you start to work with hybrid approaches. To recap, there are three different types of full trust components that you can consume from within a sandboxed solution:
- Full trust proxies. You can implement your full-trust functionality in classes that derive from the SPProxyOperation abstract class and deploy the assembly to the global assembly cache. These classes expose a full-trust proxy that you can call from within the sandbox environment.
- External content types. You can use an external content type to retrieve data from line-of-business (LOB) applications and other external sources through Business Connectivity Services (BCS). External content types must be deployed as full-trust solutions. However, you can create external lists from within the sandbox environment that use these external content types to retrieve data.
- Custom workflow activities. You can create custom, code-based workflow activities and deploy these activities as full-trust assemblies to the global assembly cache. You can then consume these activities in declarative workflows from within the sandbox environment.
This topic explains the technical details behind each of these hybrid execution models. It explains in detail how you can use each model, and it identifies some of the key execution issues that you should consider when you work with hybrid solutions.
How Do Hybrid Execution Models Work?
When you use a hybrid approach to solution deployment, the execution process varies, according to the type of full-trust component you use.
Hybrid Execution with a Full Trust Proxy
When you use a full trust proxy from the sandbox environment, requests follow the normal execution path of sandboxed solutions. The code access security policy for the sandbox environment allows sandboxed code to make calls to full-trust proxy assemblies, providing that the proxy assembly is registered with the server farm. You can programmatically register a proxy assembly from a feature receiver or by using Windows PowerShell.
Your sandboxed code must use the SPProxyOperationsArgs class to structure the arguments that you want to pass to the full-trust proxy. When you call the SPUtility.ExecuteRegisteredProxyOperation method, the sandbox worker process invokes the full-trust proxy and passes in your arguments. The proxy code executes with full trust in a proxy process. The full-trust proxy then passes any return arguments back to the sandboxed solution, and normal execution within the sandbox environment resumes.
The SharePoint context (SPContext) is not available within the proxy operation class. If you require contextual information in the proxy operation class, you will need to pass the information required to recreate the context to the proxy. For example, if you need to access a site within the proxy, you would pass the site ID as a property on the proxy arguments passed into the proxy operation. The proxy would then recreate the site using the site ID. You can then access the SPUser in the sandbox through site.RootWeb.CurrentUser.
The following illustration shows the key components of hybrid execution with a full trust proxy.
Hybrid execution with a full-trust proxy
The following describes the three key code components behind full-trust proxies:
- SPProxyOperation. This class provides an abstract base class for full-trust proxies. The class includes a method named Execute, within which you can define your full trust functionality. Your full-trust proxy classes must be deployed to the global assembly cache and registered with the SharePoint server farm, either programmatically or by using Windows PowerShell.
- SPProxyOperationArgs. This class provides an abstract base class for the parameter that you pass to the full-trust proxy. To pass arguments to the full-trust proxy, you must create a serializable class that derives from SPProxyOperationArgs. Add properties within this class to get and set your arguments.
- SPUtility.ExecuteRegisteredProxyOperation. This static method enables you to invoke the full-trust proxy from your sandboxed code. This method requires a string assembly name, a string type name, and an SPProxyOperationArgs object. The method returns an argument of type Object to the caller.
Any types you include in the proxy arguments class must be marked as serializable. Similarly, the type returned by the proxy operation must be marked as serializable. This is because arguments and return values are serialized when they are passed between processes. Both the proxy operation class and the proxy argument class must be deployed to the global assembly cache. You cannot pass any types defined in the sandboxed code into the proxy, because the proxy will not have access to load the sandboxed assembly; therefore, it will not be able to load the passed-in type.
Hybrid Execution with External Content Types
When you want to use external content types with sandboxed solutions, deployment constraints alone mean you must use a hybrid approach. External content types must be defined in a farm-scoped feature; therefore, they cannot be deployed as part of a sandboxed solution. You do not need to deploy any fully trusted code to the server. Instead, you can create external content types from the External Content Type Designer in SharePoint Designer 2010 or from the Business Connectivity Services Model Designer in Visual Studio 2010. After the external content types are in place, you can define an external list from within your sandboxed solution to access the external data. For an example of this scenario, see the external list reference implementation.
Hybrid Execution with external content types
The only means to access external data from custom code in a sandbox solution is through an external list, by using the SPList object model. You cannot use the BCS runtime APIs directly in sandboxed code.
There are special considerations for securing services for access in the sandbox. When your access external data from the sandbox, it is important to understand how credentials must be configured and used. When code in the sandbox requests access to external data through the external list, the external list implementation calls the BCS runtime. Because this code is part of the internal SharePoint implementation, it will execute within the user code proxy service. For security reasons SharePoint removes the authentication tokens for the user from the context when it enters the sandbox worker process. As a result, the Windows identity associated with the user is not available in either the sandbox worker process or the sandbox proxy process. Because a Windows identity is not available, the managed account for the sandbox proxy process must be used as the basis for securing calls to an external service or a database through the BCS. All users will authenticate to the service based upon the managed account that runs the user code proxy service. This is an example of the trusted subsystem model.
When the BDC runtime receives a request for external data, it determines if the Secure Store Service (SSS) is used to manage credentials to access the service. If the SSS is being used, then the identity of the user associated with the request is typically provided to the SSS, which maps the user (or a group or role to which the user belongs) to a credential that can be used to access the service. Because the user authentication token is not available in this case, the BDC uses impersonation mode, which results in the identity of the managed account that runs the user code proxy service being passed to the SSS rather than the identity of the user. In the SSS, the credentials of the managed account are mapped to the credentials that you want to use to access the external system. The SSS returns the mapped credentials to the BDC runtime, which then uses the credentials to authenticate to the external system. Because the BDC runtime does not receive the credentials of individual users, you cannot constrain access to the external system to specific user accounts when the request originates from the sandbox environment. The following illustration shows this process, using the example of an external vendor management system from the external list reference implementation.
Identity flow and external service access
The following describes the numbered steps in the preceding illustration:
- Custom user code, executing in the sandbox environment, uses the SPList object model (OM) to request data from an external list. The user authentication tokens for the user submitting the request have been removed from the context.
- The SPList OM call is delegated to the user code proxy service. The user code proxy service passes the request to the BDC runtime, which also runs within the user code proxy service process.
- The BDC runtime calls the Secure Store Service (SSS). The identity associated with the request is that of the managed account that runs the user code proxy service. The SSS returns the vendor management system credentials that are mapped to the identity of the user code proxy service.
- The BDC runtime retrieves the external content type metadata from the BDC metadata cache. If the metadata is not already in the cache, the BDC runtime retrieves the external content type metadata from the BDC service. The external content type metadata provides the information the BDC runtime needs to be able to interact with the external vendor management system.
- The BDC runtime uses the vendor management logon credentials retrieved from the SSS to authenticate to the service and access data from the external vendor management system.
The SharePoint user (SPUser) context is available within the sandbox environment. As such, the credentials of the user are used to control access to SharePoint resources within the sandbox.
For more information about creating external content types, see How to: Create External Content Types on MSDN.
Hybrid Execution with Custom Workflow Activities
Workflow logic is not executed synchronously in response to a user request. Instead, it is executed asynchronously by the workflow engine. This results in a significantly different execution model.
Within the sandbox environment, you can deploy a declarative workflow that defines connections between individual workflow activities. Many commonly used workflow activities are provided out-of-the-box by SharePoint 2010. The IT team can make additional workflow activities available to your declarative workflow by deploying custom, code-based workflow activities to the global assembly cache as full-trust solutions.
In order to make a full-trust workflow activity available to declarative workflows, the IT team must add an authorizedType entry to the Web.config file for the content Web application. This gives your custom activity the same status as the built-in workflow activities that come with SharePoint 2010. The following code example shows the format of an authorizedType entry.
<configuration> <System.Workflow.ComponentModel.WorkflowCompiler> <authorizedType Assembly="…" Namespace="…" TypeName="*" Authorized="True" /> </System.Workflow.ComponentModel.WorkflowCompiler> </system.web>
When you add an authorized type, set the Assembly attribute to the strong name of your assembly and set the Namespace attribute to the fully qualified namespace of your activity class. For an example of how to use a feature receiver class to add an authorized type entry for a custom workflow activity, see the Workflow Activities Reference Implementation.
As described earlier, you can also create and deploy custom sandboxed workflow actions. These actions run within the constraints of the sandbox environment. If you need to take advantage of capabilities outside the sandbox, you must deploy your custom workflow activities as full-trust solutions.
The workflow engine itself always runs in full trust, regardless of whether you deploy your workflow as a sandboxed solution or a full-trust solution. When you deploy a declarative workflow to the sandbox environment, it simply specifies the rules that determine how execution will proceed through the full-trust activities in the workflow.
This following illustration shows the key components involved in workflow execution. The declarative workflow is loaded from a sandbox solution, whereas custom full-trust workflow activities are loaded from the global assembly cache. However, the workflow is executed entirely in a full-trust environment.
Hybrid execution with a custom workflow activity
The declarative workflow is defined as part of the sandbox solution, but it always executes in a full-trust process such as Owstimer.exe, W3wp.exe, or in the user code proxy process. Generally, the process in which the workflow is determined by where the workflow is initiated or where an action is taken that causes the workflow to be "rehydrated" from the database. There are some performance mechanisms that can push execution into the timer process under high load conditions. A full-trust custom activity included in the declarative workflow also runs in a full-trust process.
Declarative workflows cannot be moved between SharePoint Foundation and SharePoint Server. In general, you can create equivalent workflows for each environment, although there are, of course, more activities available for SharePoint Server. Declarative workflows are managed slightly differently on each platform, and the workflow is packaged and deployed with the expectation that the server version is the same. You must develop the workflows on the same SharePoint version that you expect them to run on in production.
What Can I Do with Hybrid Solutions?
Hybrid approaches enable you to bypass the code access security policies and the limited permission set of the sandbox environment. When you create a full-trust proxy or a custom workflow activity, your code runs with full trust and there are no restrictions on what it can do. Any resources consumed by the full-trust code are not counted against the sandbox resource limits of the site collection. However, by definition, hybrid approaches require that your full-trust code is invoked from the sandbox environment. Because sandboxed logic can only run in the context of pages, event receivers, or workflows, hybrid approaches are inherently inappropriate for other application types such as timer jobs or service applications. In these cases, you must look to a full-trust solution.
How Do I Manage Hybrid Solutions?
When you design a SharePoint application to use a hybrid execution model, you will use two or more solution packages to deploy the components to the SharePoint environment. Components that target the sandbox are deployed as sandboxed solutions to a site collection solution gallery, and components that run with full trust are deployed as farm solutions to the server environment.
For example, suppose your solution includes a Web Part that uses an external list to query a LOB application. Behind the scenes, the external list relies on an external content type to provide an interaction with the LOB data source. The following illustration shows an example where the Web Part is deployed in a sandboxed solution, while the external content type is deployed as a farm solution.
Hybrid approach with a Web Part and an external content type
Alternatively, suppose your Web Part uses a full trust proxy to access parts of the object model that are inaccessible to sandboxed code. The following illustration shows an example where the Web Part is deployed in a sandboxed solution, while the full trust proxy is deployed as a farm solution.
Hybrid approach with a Web Part and a full trust proxy
From an administrative perspective, these types of deployment are managed as two separate solutions. The sandboxed solution is subject to the monitoring, resource throttling, and permission limitations of the sandbox environment, while the farm solution is subject to any organizational constraints on the deployment of full trust code.
What Are the Core Issues for Hybrid Solutions
When you design your applications to use a hybrid execution model, you will deploy components in both sandboxed solutions and full-trust solutions. As such, you need to consider the issues that relate to each individual solution type in addition to those issues that apply specifically to hybrid approaches. When you develop a hybrid solution, you should pay particular attention to the areas described in the following sections.
Hybrid solutions expose a smaller surface area of full-trust code compared to farm solutions. This can reduce the amount of security review time that you require before deploying your solution. Because some of your solution code runs in full trust, you can impersonate the application pool (in other words, elevate permissions) if necessary. However, the boundaries of the sandbox environment were carefully designed when SharePoint 2010 was developed. You should consider the impact of any full-trust functionality that you expose to the sandbox, because this code runs without the security restrictions that apply to the sandbox environment.
If you want to use a hybrid approach, your organization must permit you to deploy farm solutions to your SharePoint environment. If you do not have permission to deploy assemblies and other resources to the server environment, you cannot deploy a hybrid solution. Organizations may be more permissive to external content types, as you can create an external content type from SharePoint Designer without deploying any managed code.
It is important to understand which components of your solutions can run within the sandbox environment and which components require a full-trust proxy. The full-trust proxy should only include those elements that need to execute with full trust—the other elements should remain within the sandboxed solution. This helps to minimize the surface area of code that you expose to performance or security vulnerabilities. It can also help to reduce the time required for code review, as described in the preceding paragraphs.
Logging and Configuration
Full-trust proxies can provide a useful way to expose logging and configuration functionality to sandboxed applications. For example, the SharePoint Logger component includes a full-trust proxy that enables sandboxed applications to write events to the Windows Event log and the Unified Logging Service (ULS) trace log.
Similarly, a full-trust proxy can provide a sandboxed application with access to configuration settings that would otherwise be unavailable. Full-trust proxies can read and write to any data within the Web application and can read data stored in the SPFarm object. However, if you create a full-trust proxy to expose additional configuration functionality to sandboxed solutions, take care to include safeguards against improper use of that functionality. For example, developers risk corrupting the content or configuration database if they attempt to persist a non-serializable object to a property bag. In this case, it would be wise to include functionality within the full-trust proxy to verify that the object can be serialized before you proceed with the operation.
Because full-trust proxies are deployed to the global assembly cache, they are not subject to the resource throttling and monitoring constraints that are applied to sandboxed solutions. It is important to verify that the code in your full-trust proxy performs to a high standard. For example, ensure that your code does not cause excessive memory use or process timeouts, just as you would for code in a farm solution. This can help to ensure that your full-trust proxy does not jeopardize the stability of the farm as a whole.
Like with sandboxed solutions, there is a marginal reduction in performance when you use a hybrid solution instead of a farm solution. This is because of the marshaling of data across application domains.