So, there’s been somewhat of a commotion about this thing recently so I chose to give it a try. Let me mention several things first – I’m still wondering whether the sandbox solutions will be that standard and widely used to start with and whether the ability to make user controls for web parts is that vital and effort-saving (well, it’s been a practice for me to use user controls with web parts but that’s not so for most of my colleagues), but despite this temperate pessimism of mine I chose to make a small POC that demonstrates how this can be implemented.
So let me start with several words about why the TemplateControl.LoadControl method is not working in a sandbox solution. The reason is reasonably simple – your code in a sandbox solution really executes in a console attention – the SPUCWorkerProcess.exe. So basically what you have is that a console attention has made an HttpContext and a Page instance, in which your web part class is also instantiated – it is really the only control (in some cases you can have a couple more) on that page. And in this mock-like asp.net environment you don’t have some crucial asp.net pieces as the HostingEnvironment and the VirtualPathProvider – without these two the LoadControl method austerely won’t work (I may clarify the sandbox and SharePoint user code intrinsic workings in another posting). And it is not that you don’t have access to the file system, even if you had, the LoadControl method still wouldn’t work because there wouldn’t be a VirtualPathProvider to provide the file to the asp.net compiler. The terrible news is that the same holds for the TemplateControl.ParseControl method too.
And to the thought behind the implementation: I first saw a codeplex machinate – SharePoint Developer Tools for Visual Studio 2010 – it really had a custom VS 2010 machinate template for a visual sandbox web part … but it didn’t work – it didn’t compile due to one error in this line:
Controls.Add(new ASP.SandboxedVisualWebPart1_ascx());
I immediately understood what the thought behind this was: a class name like this one – ASP.somecontrol_ascx – gives away a class generated by the asp.net runtime or by the aspnet_compiler.exe tool from an ascx file. So, aspx and ascx files get eventually compiled to real code Page and Control classes in temporary assemblies that the asp.net runtime makes if not existing and loads when you navigate the aspx page or use the ascx control. These assemblies can be made also by the aspnet_compiler.exe utility that comes with the .NET framework, which is used primarily to precompile your web sites when you install them. But you can also use this tool to compile any ascx (and aspx) file that you have – in our case the tool can be used to compile the user controls of the sandbox web parts. So, the tool will spit out one or several assemblies that contain the compiled classes of the ascx files but there are two issues with circular references:
- you cannot add a reference to this assembly in your web part assembly because the former itself has a reference to your assembly
- the second circular reference is one of class treatment – you first need to have your assembly compiled before the ascx assemblies can be made (since they need the code behind classes from your assembly), but you wouldn’t be able to compile the web part assembly if it uses the ascx compiled classes (which may possibly be made only after your assembly is compiled) – what a paradox.
And now, here’re the steps that I used to solve the above mentioned issues – note that all these are executed as a post build step of the web part machinate (the actual implementation is with a PowerShell speech file):
- first step is to copy all ascx files that you have in the machinate to a temporary folder and use the aspnet_compiler.exe tool to make assembly (assemblies) containing the compiled ascx classes
- second step (this solves the first circular reference issue) is to use the ILMerge tool (it’s a free Microsoft tool that can be downloaded from here – note that it doesn’t come with the .NET installation) to merge the compiled ascx assembly (assemblies) with the web part assembly – this is what the ILMerge tool does – merging assemblies (fantastic thing). And now you will have the ascx compiled classes right into your web part assembly.
- third step comes to the second circular reference issue – as I mentioned these steps are executed as a post build step which means that you have the web part assembly already compiled – but how did that happen if you need to reference the compiled ascx class. The answer is simple – you don’t reference it at all or at least not as a class – here is how this is possible: with a standard visual web part you use the user control via a member variable whose type is really the code behind class of the user control and the only “reference” to the user control is the LoadControl call in the CreateChildControls method of the web part where the control is made and its instance gets cast to the code behind class member variable. And we have the same here, the only difference is the control instantiation in the CreateChildControls method and this is the key line of code for that:
_userCtrl = (UserControl1)Activator.CreateInstance(Type.GetType("ASP.usercontrol1_ascx"));
As you see – a small bit of proposition (will this pass the security checks in the sandbox – yes) and the ascx compiled class instance is made providing only its class name as a string (which is easily deducible from the name of the ascx file).
You can download the sample machinate which demonstrates this technique (or rather work-around) from here. And I want to make a huge NOTE here that this is only a POC, the implementation is a bit sloppy and probably won’t work in all cases and/or in more complex scenarios. Also in the PowerShell speech that implements the post-build step there’re several hard-coded values for file locations and names which may break the whole thing. So, having said that let me outline shortly the steps that you can use to make a simple sandbox solution that uses user controls in web parts:
- Open Visual Studio 2010 as administrator
- Make an Empty SharePoint Machinate (selecting the “Install as sandbox solution” option) – e.g. SandboxWebPart
- Add a new Web Part item to the machinate (e.g. WebPart1)
- Add a new User Control item to the machinate (e.g. UserControl1)
- Drag the newly make ascx item (UserControl1.ascx) from not more than the ControlTemplates/SandboxWebPart folder and drop it not more than the web part’s node – WebPart1
- Delete the ControlTemplates mapped folder (you won’t be able to build the package with it)
- This is discretionary – open the UserControl1.ascx.cs and UserControl1.ascx.designer.cs and exchange the namespace to be the namespace that you have in the web part’s code file. If you exchange the namespace in these two files you will have to exchange the Inherits attribute in the Control directive in the UserControl1.ascx file so that it reflects the new full name of the code-behind class.
- This is vital – in the UserControl1.ascx in the Control directive at the top exchange the AutoEventWireup to fake – otherwise you will receive security errors at runtime (sorry, you will need to hook your events explicitly).
- From the properties pane of the UserControl1.ascx – set the Deployment Type property to NoDeployment (remember you cannot install ascx files in a sandbox solution)
- Add some code to your web part so that it can use the user control – first make a member variable with the user control’s code-behind class type:
protected UserControl1 _userCtrl;
- Add this code to the web part’s CreateChildControls override method:
_userCtrl = (UserControl1)Activator.CreateInstance(Type.GetType("ASP.usercontrol1_ascx"));
this.Controls.Add(_userCtrl);
- Add the postbuild.ps1 file from the sample machinate into the machinate root folder
- Open the machinate properties page and in the Build Events section place this in the “Post-build event command line” text box:
PowerShell -command "set-executionpolicy -ExecutionPolicy bypass"
PowerShell -command "$(ProjectDir)postbuild.ps1" ‘$(SolutionDir)’ ‘$(ProjectDir)’ ‘$(TargetDir)’ ‘$(TargetFileName)’ ‘$(ConfigurationName)’
- Huge NOTE – here – remember that you’re running Visual Studio as administrator and you’re first changing the execution policy setting of PowerShell and then you will run a PowerShell speech which may be a huge security threat – make sure that you check carefully the code in the postbuild.ps1, so that you know what it does and how it does it. Another note – instead of by the speech as a post-build step you can run it standalone, after you make a normal build of the machinate – in this case you will have to provide all command line arguments that it expects.
- Make sure that you have installed the ILMerge tool (see above) to this location – C:\Program Files (x86)\Microsoft\ILMerge (it is hard-coded in the ps speech)
- Build the solution – in the productivity window you should see something like this:
—— Rebuild All started: Machinate: SandboxWebPart, Configuration: Debug Any CPU ——
SandboxWebPart -> c:\Projects\SandboxWebPart\SandboxWebPart\bin\Debug\SandboxWebPart.dll
asxc compilation started…
Compiling ascx files:
C:\Projects\SandboxWebPart\SandboxWebPart\ascxtmp\UserControl1.ascx
Utility to precompile an ASP.NET attention
Copyright (C) Microsoft Corporation. All rights reserved.
Merging assemblies:
C:\aa618f13-0fa9-4dc8-b6ee-714f24d847f2\bin\App_Web_wagenclm.dll
C:\aa618f13-0fa9-4dc8-b6ee-714f24d847f2\bin\SandboxWebPart.dll
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
- You can now run install and check your web part with a user control in it (hope this works for you).
Check it out:Stefan Stanev’s SharePoint blog









![Panda Antivirus Pro 2011 3-User [Download]](http://ecx.images-amazon.com/images/I/51lzlWx48ZL._SL160_.jpg)

Answers Rating