Tuesday, February 15, 2011

Disposing SPSite and SPWeb

Most of the time when we are working with a site or a web we would put a using statement such as these:
using (SPSite siteCollection = new SPSite("http://evan.local"))
{
    // Code here
}
using (web = site.OpenWeb("search"))
{
    // Code here
}
The reason is so that site collection / the web are disposed properly.

However trying to do similar thing in:
using (SPSite site = SPContext.Current.Site)
{
       Code here
}
using (SPWeb web = site.RootWeb)
{
       Code here
}

Will give you the following error in the log:

Unexpected    Detected use of SPRequest for previously closed SPWeb object.  Please close SPWeb objects when you are done with all objects obtained from them, but not before.


The reason is the SPContext (together with the site collection/web property in the object) will be automatically disposed when SharePoint finish with it. By putting them into the “using” statement, we are actually disposing the object when they are still being used.

So the conclusion:
If you are opening a site / a web then use “using” statement;
If you are utilising a site/web object from a property of the SPContext object then please do not use “using” statement.

Have a great day everyone J

Wednesday, February 2, 2011

Using a 3rd party control in SharePoint 2010

In this example I was trying to use Recaptcha in one of my custom SharePoint Page.

In normal ASP .Net registering the following TagPrefix should be enough:
<%@ Register TagPrefix="recaptcha" Namespace="Recaptcha" Assembly="Recaptcha" %>

Then I should be able to use the control just like this:
<recaptcha:RecaptchaControl ID="recaptcha" runat="server" PublicKey="SOME_PUBLIC_KEY" PrivateKey="SOME_PRIVATE_KEY" />

However SharePoint did not like it, instead I was getting the following error:
System.IO.FileNotFoundException: Could not load file or assembly 'Recaptcha' or one of its dependencies. The system cannot find the file specified.    at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)     at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)     at System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)     at System.Reflection.Assembly.Load(String assemblyString)     at System.Web.Configuration.CompilationSection.LoadAssembly(String asse...      a475e341-2fe9-435c-916f-189bee006e81

The solution is to register recaptcha using the fully qualified name including the PublicKeyToken like this:
<%@ Register TagPrefix="recaptcha" Namespace="Recaptcha" Assembly="Recaptcha, Version=1.0.5.0, Culture=Neutral, PublicKeyToken=9afc4d65b28c38c2" %>

Hope this helps.