Thursday, January 21, 2010

using using

In C++ we have what is called ‘deterministic finalization’ which means that the lifetime of an object is predictable. In .NET however we don’t; the garbage collector takes care of deleting objects and when this happens is not defined.

This makes all kinds of nice patterns we were able to use in C++ impossible. Fortunately, there is a solution in .NET by using the IDisposable interface. In .NET all classes that manage some expensive resource implement this interface and it is up to you, the developer, to make sure the Dispose() method is called appropriately. This is actually not so nice, for example think of exceptions that may occur before you’re able to call Dispose() ( and when you happen to be a SharePoint dev you must really ensure proper use of Dispose() or you may quickly exhaust your server)

Fortunately the C# compiler helps here by providing the using() statement that ensures a call to Dispose() on your object, no matter what.

Having said this I come to my point, which is that we can also use IDisposable nicely for other purposes then freeing up resources.

For example, in good old MFC we had a class called CWaitCursor which one could put at the entry of a lengthy UI method. When the CWaitCursor object was constructed the cursor would show a wait cursor, when the method finished, the object would go out of scope and the cursor would be reset, nice. In .NET we don’t have it, but we can use IDisposable and using() to achieve the same behavior.

So what we want is to write:

using (WaitCursor w = new WaitCursor())
{
    // lengthy operation:
    Thread.Sleep(2000);
}


In order to achieve this, we make a simple class as follows:



class WaitCursor : IDisposable
{
    private Cursor _prev = Cursors.Default;
    public WaitCursor()
    {
        _prev = Cursor.Current;
        Cursor.Current = Cursors.WaitCursor;
    }
    
    ~WaitCursor()
    {
        Cursor.Current = _prev;
    }
    #region IDisposable Members
    public void Dispose()
    {
        Cursor.Current = _prev;
        GC.SuppressFinalize(this);
    }
    #endregion
}


Of course this is a very simple example but it shows an alternate use of using() and IDisposable and can be applied to many more scenarios. It sure beats writing try{} catch{} finally{} to set/unset all sorts of state.

Wednesday, January 20, 2010

SharePoint Connections 2010, Amsterdam

Last 2 days I was at the SharePoint Connections 2010 conference in Amsterdam. All about the upcoming release of SharePoint. Some things I took home from the conference (as I walked the dev track, most of it is dev related):

Good news for developers! Our lives will definitely be more easy with SP2010.

  • Client side object model, no longer a need to manually craft Xml messages. The model comes in three flavors: 
            for JavaScript
            for Silverlight
            for normal .NET apps
        I guess each of them will have different limitations
        Btw, a company named HubKey has a flavor of this already available for 2007 see http://www.hubkey.com/sharepointapi.aspx
        The 2010 client OM will obviously be a subset of the full SP OM.
  • Ajax supported out of the box, no longer a need to adjust web.config
  • WCF Ajax enabled webservices work out of the box, no longer a need to build/register your own Vvirtual Path Provider
  • Visual WebParts, user control support ala SmartPart out of the box
  • Silverlight support out of the box. There is a standard Silverlight webpart that you can point to a .xap and have it rendered on a page
  • Full integration in VS2010; 'F5' debugging experience, all kinds of SP project templates, a BDC designer etc.
  • SandBoxed solutions, although it has some limitations (e.g. no Visual WebParts) this gives devs better deployment options (site level iso farm level)

Very interesting was the presentation given by Peli de Halleux, a MS researcher who works on tools and frameworks (http://research.microsoft.com/en-us/projects/pex/) to automate unit testing. He basically developed a way to ‘mole’ (stub) the SharePoint API so you can unittest your SharePoint code without……..SharePoint, yeah. I wonder how far they can take this for more complex code…

Friday, January 8, 2010

Opening editable Office documents located in a WebDAV folder from a browser

When you want to store Office documents on your webserver and allow users to edit these documents, WebDAV is a very nice way to do so. However, opening this docs in edit mode from an ASP page is not possible without some client side scripting and an ActiveX component. As part of the Office SharePoint integration comes a handy ActiveX component that happens to work for WebDAV as well. The following script shows you how to do so.

<script type="text/javascript">
    var v_stsOpenDoc = null;
    var v_strStsOpenDoc = null;
    function StsOpenEnsureEx(szProgId) {
        if (v_stsOpenDoc == null) {
            v_stsOpenDoc = new ActiveXObject(szProgId);
            v_strStsOpenDoc = szProgId;
        }
        return v_stsOpenDoc;
    }
    function Open(url) {
        // call webservice
        var pid = StsOpenEnsureEx("SharePoint.OpenDocuments.3");
        pid.EditDocument3(window, url, false);
    }
    function Button2_onclick() {
        Open("http://localhost:1966/docs/doc1.docx");
    }
</script>


Once the doc is opened in Word, whenever the user saves the document, it will be saved on the webserver.



For Office 2003, use SharePoint.OpenDocuments.2 for the progid

Tuesday, December 1, 2009

Production server stops with: Retrieving the COM class factory for component with CLSID {BDEADEE2-C265-11D0-BCED-00A0C90AB50F} failed due to the following error:800703fa.

SharePoint server stops working with: Retrieving
the COM class factory for component with CLSID
{BDEADEE2-C265-11D0-BCED-00A0C90AB50F} failed due to the following error:
800703fa

If you have this error run IISRESET and everything works again. This must be some temporarely corruption.




Server
Error in '/' Application.







Retrieving
the COM class factory for component with CLSID
{BDEADEE2-C265-11D0-BCED-00A0C90AB50F} failed due to the following error:
800703fa.


Description: An unhandled exception occurred
during the execution of the current web request. Please review the stack trace
for more information about the error and where it originated in the code.
Exception Details: System.Runtime.InteropServices.COMException:
Retrieving the COM class factory for component with CLSID
{BDEADEE2-C265-11D0-BCED-00A0C90AB50F} failed due to the following error:
800703fa.



Source Error:



An unhandled exception was generated during the execution of the
current web request. Information regarding the origin and location of the
exception can be identified using the exception stack trace below.




Stack Trace:



 

[COMException (0x800703fa): Retrieving the COM class factory for
component with CLSID {BDEADEE2-C265-11D0-BCED-00A0C90AB50F} failed due to the
following error: 800703fa.]

   Microsoft.SharePoint.Library.SPRequest..ctor() +104

   Microsoft.SharePoint.SPGlobal.CreateSPRequestAndSetIdentity(Boolean
bNotGlobalAdminCode, String strUrl, Boolean bNotAddToContext, Byte[]
UserToken, String userName, Boolean bIgnoreTokenTimeout, Boolean
bAsAnonymous) +238

   Microsoft.SharePoint.SPWeb.InitializeSPRequest() +455

   Microsoft.SharePoint.SPWeb.EnsureSPRequest() +75

   Microsoft.SharePoint.SPWeb.get_Request() +74

  
Microsoft.SharePoint.WebControls.SPControl.SPWebEnsureSPControl(HttpContext
context) +613

   Microsoft.SharePoint.WebControls.SPControl.GetContextWeb(HttpContext
context) +41

  
Microsoft.SharePoint.ApplicationRuntime.SPRequestModule.PostResolveRequestCacheHandler(Object
oSender, EventArgs ea) +595

  
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
+80

   System.Web.HttpApplication.ExecuteStep(IExecutionStep step,
Boolean& completedSynchronously) +171


 


Saturday, October 17, 2009

QuizXpress site is live!

After lots of hard work we’re done with our new release of the QuizXpress product suit and website. Details can be found at http://www.quizxpress.com.

Friday, September 18, 2009

SharePoint error of the day

Today one of our servers in the farm start failing on some sites with the error below. Appearantly we're the only one, Googling on PreInitServer and '[COMException (0x80004005): Cannot complete this action. ' yields nothing. We're hoping a reboot tonight will resolve something here as we recently installed report server in the farm.

Server Error in '/' Application.
--------------------------------------------------------------------------------

Cannot complete this action.

Please try again.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Runtime.InteropServices.COMException: Cannot complete this action.

Please try again.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:


[COMException (0x80004005): Cannot complete this action.

Please try again.]
Microsoft.SharePoint.Library.SPRequestInternalClass.PreInitServer(String bstrAbsoluteRequestUrl, String bstrServerRelativeUrl, Int32 lZone, Guid gApplicationId, Guid gSiteId, Guid gDatabaseId, String bstrDatabaseServer, String bstrDatabaseName, String bstrDatabaseUsername, String bstrDatabasePassword, Boolean fHostHeaderIsSiteName) +0
Microsoft.SharePoint.Library.SPRequest.PreInitServer(String bstrAbsoluteRequestUrl, String bstrServerRelativeUrl, Int32 lZone, Guid gApplicationId, Guid gSiteId, Guid gDatabaseId, String bstrDatabaseServer, String bstrDatabaseName, String bstrDatabaseUsername, String bstrDatabasePassword, Boolean fHostHeaderIsSiteName) +359

[SPException: Cannot complete this action.

Please try again.]
Microsoft.SharePoint.Library.SPRequest.PreInitServer(String bstrAbsoluteRequestUrl, String bstrServerRelativeUrl, Int32 lZone, Guid gApplicationId, Guid gSiteId, Guid gDatabaseId, String bstrDatabaseServer, String bstrDatabaseName, String bstrDatabaseUsername, String bstrDatabasePassword, Boolean fHostHeaderIsSiteName) +479
Microsoft.SharePoint.SPSite.PreinitializeServer(SPRequest request) +666
Microsoft.SharePoint.SPWeb.InitializeSPRequest() +548
Microsoft.SharePoint.SPWeb.EnsureSPRequest() +75
Microsoft.SharePoint.SPWeb.get_Request() +74
Microsoft.SharePoint.WebControls.SPControl.SPWebEnsureSPControl(HttpContext context) +613
Microsoft.SharePoint.WebControls.SPControl.GetContextWeb(HttpContext context) +41
Microsoft.SharePoint.ApplicationRuntime.SPRequestModule.PostResolveRequestCacheHandler(Object oSender, EventArgs ea) +595
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +80
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +171