Errors creating WebPart subclass in another assembly - sharepoint

I am trying to create a subclass of WebPart that will act as a parent to any WebParts we create. If I create an empty class in the same project, I am able to inherit from it as one would expect. However, if I try to place it in another assembly -- one that I've been able to reference and use classes from -- I get the following error:
Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
Other information that may be pertinent (I am not normally a SharePoint developer): I compile the dlls, reference them from the dev project, and copy them into the /bin directory of the SharePoint instance. The assemblies are all signed. I'm am attempting to deploy using VS2008's 'deploy' feature.
Unfortunately, this does not appear to be a SharePoint specific error, and I'm not sure how to solve the problem. Has anyone experienced this and do you have any suggestions?

OK, I found the problem. The packaging task uses reflection for some reason or another. When it finds that your class inherits from a class in another domain, it tries to load it using reflection. However, reflection doesn't do binding policy, so that domain isn't loaded.
The authors of the packaging program could solve this by adding the following code:
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(CurrentDomain_ReflectionOnlyAssemblyResolve);
Assembly a = System.Reflection.Assembly.ReflectionOnlyLoadFrom(filename);
static Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args)
{
return System.Reflection.Assembly.ReflectionOnlyLoad(args.Name);
}
However, if you need a solution for your project, just add the assemblies to the GAC and it will be able to resolve them.

Related

.NET MEF DirectoryCatalog issue

I am developing Excel add-in and use MEF to provide extensibility. DirectoryCatalog works fine on my local drive, however when I deploy solution to the network drive composition silently fails.
In regular .exe application this problem can be resolved by adding "loadFromExternalSources=true" to "runtime" section of application configuration file, however for Excel add-in this file does not exist (and I can't add Excel.exe.config to the folder, containing Excel executable since this folder is read-only). Is there any way to programmatically enable loadFromExternalSources behavior?
Is there any way to programmatically enable loadFromExternalSources behavior?
If you create a seperate AppDomain with AppDomain.CreateDomain, then you can pass a AppDomainSetup which has a ConfigurationFile property.
However, I suppose that comvisible objects are normally created in the default appdomain so making the new AppDomain talk to Excel will probably be difficult. I guess it would involve shim classes in the default appdomain which pass calls through to the other appdomain.

Unable to deploy my custom DLL to Sharepoint site

I created my custom assembly that has a simple HttpModule in it that I'd like to use in my Sharepojnt 2010 site.
I added my module to sharepoint site's web.config/system.webServer/modules section.
I then also copied my DLL directly to bin folder since that's how suual asp.net applications work. I got an exception about failed AspNetHostingPermission.
I copied the same DLL to _app_bin folder and it worked. My module did get initialized and was running.
I then added two permissions to my module class:
[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
and also added these two to assembly
[assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution = true)]
[assembly: AllowPartiallyTrustedCallers]
and strongly signed my assembly with a key I created.
Then I copied the DLL back to bin but it still didn't work. Copying it to _app_bin worked.
What do I have to do, to deploy my DLL directly to bin folder?
The problem you're running into is that SharePoint is using Code Access Security (CAS) to make it possible for really well educated Admins to make sure that they don't put their environment to unnecisary risk when adding functionallity to it.
The problem is then that even though CAS has been in .Net since the beginning nearly nobody has used it before SharePoint, so most developers don't know how to deal with it.
Everything in _app_bin is running with full trust, which explains why your dll works there.
Everything in bin is running with a lot less trust depending on the trust level specified in web.config (in fact this is also the one that specifies _app_bin has full trust, but thats common in all of the out of box trust levels).
In order to get your dll to work from bin (without changing trust level to full which is bad) you need to modify the policy file which the trust level is pointing to with the right xml for the right your dll need.
Adding the attributes don't help you directly, initially they in fact just makes the problem worse, because now your dll demands the rights even though it might not call anything which requires them.
Where the attributes help you is if you use WSPBuilder to build your WSP package for deploying to SharePoint (You're using a WSP right), then it'll look for security attributes and make the corresponding entries in manifest.xml which then get SharePoint to add the corresponding entries to the policy file on deployment.
In order for you attributes to work with WSPBuilder I think they have to be changed to SecurityAction.Demand though.

Using SubSonic Active Record in a seperate assembly from the Web

I'm following the tutorial here.
I created a new Web Application. I then added two Class Library projects, Common and Domain. The common project contains the SubSonic library while the Domain project contains the SubSonic .tt and .ttinclude files.
After modifying the settings in Settings.ttinclude, I try to 'Run custom tool' on the tt files and I get this error:
Running transformation: System.ArgumentNullException: Value cannot be null.
Parameter name: The project does not contain App.config or Web.config file.
I can provide the rest of the stack trace, but it appears that it can't find my Web.config which was the connection string. Adding an app.config to the Domain project just causes the generation step to complain about not finding expected sections.
Is there a way to have these files in a separate assembly but still use the web.config for settings?
You need to place an App.config in the project you want to generate from. Yes, it's redundant but there's no other way to handle this with T4

How to add a referenced assembly to the deployment of a VSTO project?

I have written a few Excel 2003/2007 add-ins using VSTO, and I usually end up referencing .NET dll's in the VSTO project (usually code I reuse across projects).
I ran into the following issue. While the calls to the dll work perfectly in debug mode or on the development machine, when I deploy the add-in through a msi installer, the dll is added to the folder of the add-in, but the add-in doesn't seem to be able to call the dll.
After some struggles, I figured out a way around this: on top of the Custom Action in the installer granting security to the add-in, I add another Custom Action granting security to each individual dll referenced by the add-in, following the steps described in
http://msdn.microsoft.com/en-us/library/bb332052.aspx
My issue is that while it works, I am not convinced I am doing it right. It is super-tedious, and I also get a warning when I build, which from what I can make is actually pointing at the fact that the security is granted twice in the same location.
Anyone here can tell me whether I am doing it right or not, and what the better way is, if there is one?
In my case, I have a suite of add-ins under MyCompany.Office.
I have a shared library of core functionality called MyCompany.Office.dll, which is referenced by MyCompany.Office.Word.dll and MyCompany.Office.Excel.dll, which are both add-ins (you could easily have multiple add-ins for Excel rather than one for Word and one for Excel, or whatever you want).
What I did was create a strong name keyfile for the solution and linked it in all three projects. I then signed all three libraries with the same strong name keyfile.
I then created an Installer Action that adds a CAS entry using the public key as evidence, rather than the file location. so, my custom action ultimately invokes caspol.exe -m -q -ag "My_Computer_Zone" -strong -hex <my public key> -noname -noversion FullTrust -n "MyCompany_Office" -d "Code group for MyCompany.Office add-ins.". This gives FullTrust to all libraries with that public key.
You can view the public key by opening a command prompt, navigating to the keyfile location and typing sn -Tp mykeyfile.snk. If you want to get the public key pro grammatically (like extending SetSecurity), you could use code like this:
private static String GetPublicKeyHexString(String assemblyPath)
{
AssemblyName assmName = Assembly.LoadFile(assemblyPath).GetName();
StringBuilder output = new StringBuilder();
Byte[] publicKey = assmName.GetPublicKey();
foreach(Byte byte in publicKey)
{
output.Append(byte.ToString("x").PadLeft(2, '0'));
}
return output.ToString();
}

Deploying a Custom Field Types to the bin directory

As stated here custom field types (and any dlls they have a reference to?) must be deployed to the global assembly cache. Why, and what problems may arise by deploying to the bin directory? I’m trying to secure my code by writing CAS-policies and since my field controls uses a lot of help methods shared by my other code this seems like a show stopper.
So far the only problem I’ve found with a bin deployment is that when the feature is deactivated and then reactivated with STSADM I get an error message stating that my field type is not installed properly. Using the –force switch or activating through the GUI seems to be working just fine.
custom fields are installed farm wide, if you deploy the dll to the bin directory, you must ensure that they are in all web application's bin directories.
I forgot to put one of the interfaces my field type implemented in the GAC, which caused the problem I described above.
Conclusion:
Custom field types can reference dll:s in the bin directory, as long as they are not required to create the object.

Resources