SharePoint Internals – Hristo Pavlov’s Blog

19 January, 2009

Understanding SharePoint: SPRequest

I am going to put together a series of ‘Understanding SharePoint’ posts and cover various important parts of SharePoint which are not very well understood or for which there is little or no information on the net. The first post will be about possibly the most important class in SharePoint called SPRequest – an internal class from the SharePoint object model.

It may come as a surprise to you (which only shows how little it has been written about this) but most of the ‘important’ things in SharePoint are actually done through unmanaged code and the SharePoint .NET object model provided by the Microsoft.SharePoint.dll is a sort of a wrapper to this unmanaged world. Understanding how your code does what you want it to do can be very helpful when troubleshooting issues, fixing bugs, doing performance tuning and writing solid code in general so I believe that every SharePoint developer should know about SPRequest.

As you are aware the gateway to doing anything in SharePoint is the SPSite object. In order to get to any other objects that reside in a site collection such as SPWeb, SPList, SPListItem, SPFile and others we first need to obtain an SPSite and there is a very good reason for that. Every SPSite instance holds a reference to the unmanaged WSS world in the means of a field member of type SPRequest which is called m_Request. The internal SPRequest class has an unmanaged reference to a COM object called SP.SPRequest and having a ClassID of BDEADEE2-C265-11D0-BCED-00A0C90AB50F which is implemented in and exposed by the OWSSVR.DLL class library.

The SP.SPRequest COM object exposes almost 400 basic operations and almost everything you do with the Microsoft.NET managed SharePoint object model that reads from or writes to the ContentDatabase (including data, fields, content types, list schemas, etc) will actually go via this unmanaged COM object. Even more the OWSSVR.DLL is actually an ISAPI extension registered in IIS and its methods can be called directly via an HTTP request to /_vti_bin/owssvr.dll. Many of the Office applications (Word, Excel, InfoPath, SharePoint Designer etc) are using HTTP calls to OWSSRV directly in order to integrate with a remote SharePoint server. It won’t be too much of an exaggeration to say that OWSSRV.DLL is the soul and body of WSS 3.0. It comes historically from SharePoint ver 1.0 from the days before Microsoft.NET when web applications were developed using technologies like ISAPI and DCOM. For more information on OWSSRV and the WSS architecture have a look at the Overview of the SharePoint Team Services Architecture in MSDN.

Let’s now have a look at the public ISPRequest interface which is implemented by the SP.SPRequest COM object and is available for .NET via the SPRequest class. The list below shows only a fraction of the ~400 actions exposed by this COM object and demonstrates what sort of operations are done through the SPRequest class. As you can see this is pretty much everything in WSS:

[

    ComImport,

    Guid(“BDEADEBE-C265-11D0-BCED-00A0C90AB50F”),

    ComConversionLoss,

    TypeLibType((short)0x100),

    SuppressUnmanagedCodeSecurity,

    InterfaceType((short)1)

]

public interface ISPRequest

{

   

    void GetFieldsSchemaXml();

    void GetViewsSchemaXml();

   

    string CreateList();

   

    void DeleteList();

   

    void QueryUserInfo();       

   

    string AddField();

    void RemoveField();

    void UpdateField();

   

    void GetMetadataForUrl();

    void DeleteView();

    void UpdateView();

    void CreateView();

   

    void AddOrUpdateItem();

    void DeleteItem();

    void GetAttachmentsInfo();

   

    void CrossListQuery();

    void RenderViewAsHtml();

   

    void UpdateUser();       

   

    void BackupSite();

   

    void CreateSite();

    void DeleteSite();

    void OpenSite();

    void SetSiteProps();

    void GetAllWebsOfSite();

   

    void UpdateFileOrFolderProperties();

    void PutFile();

   

    void GetFile();

   

    void CheckOutFile();

    void CheckInFile();

   

    void CreateWeb();

    void SaveWebAsTemplate();

   

    void OpenWeb();

    string ApplyTheme();

   

    int AddRoleDef();

   

    void AddWebPart();

   

    void CreateListViewPart();

   

    void GetTimeZoneInfo();

   

    void AddMeeting();

   

    void GetSiteQuota();       

   

    void RegisterEventReceiver();

   

    void InvokeTimerJob();

   

    void GetListContentTypes();

   

    void AddWorkflowToListItem();

   

    void SetGhostedFile();       

   

    int AddNavigationNode();       

   

}

To see the full list of methods exposed by SPRequest you can open up this class in Reflector. In order to do this you first need to get the Microsoft.SharePoint.Library assembly from the GAC. To get a physical copy of this file you can go Start -> Run -> type ‘C:\WINDOWS\ASSEMBLY\GAC_MSIL’  -> press ‘Enter’. This is a little trick that will open up the physical store of the GAC assemblies. And remember you must do this from Start -> Run – it will not work otherwise. So once you have it opened, navigate to Microsoft.SharePoint.Library\12.0.0.0__71e9bce111e9429c and copy the file to a place you can open it with Reflector.

[Updated 23 Jan]

ISPRequest is actually a COM interface and the public SPRequestInternalClass from the Microsoft.SharePoint.Library.dll is a wrapper to it. The ISAPI extension  /_vti_bin/owssvr.dll can be used to do various things as documented in the Windows SharePoint Services URL Protocol.

Even that the SPRequestInternalClass is public it is actually undocumented according to the Microsoft SharePoint Escalation Engineer Stefan Gossner. (See his comment below and the link to his blog Documented / Undocumented API – Why Should I care?).  Stefan also points out that any SharePoint database which is modified using direct access to this undocumented API will become an unsupported state as if you would have modified the database using direct SQL queries. So be warned!

[/Updated 23 Jan]

So now that we know that when we call the SharePoint .NET object model almost everything is done via unmanaged code the next question is what is the implication of this. Well firstly this means there are unmanaged objects being created all the time, and those objects cannot be cleaned up automatically by the .NET garbage collector. This is exactly why it is so important to call Dispose() or Close() on an SPSite when we have finished using it as we need to free those unmanaged resources. If we don’t do this they will cause unmanagedmemory leaks and will severely slow down the server. We need to call Close()/Dispose() with every object that implements the IDisposable interface and from the ‘common’ SharePoint objects this are both the SPSite and SPWeb class instances.

If you try to allocate too many SPRequest objects (create too many SPSites) without releasing them you will start getting medium severity trace messages in the ULS Log similar to the one below:

“Potentially excessive number of SPRequest objects (10) currently unreleased on thread 23. Ensure that this object or its parent (such as an SPWeb or SPSite) is being properly disposed. This object will not be automatically disposed.”

There are two registry keys you can use to control the ULS trace log related to allocating and disposing SPRequest objects. Firstly the warning threshold can be controlled via the LocalSPRequestWarnCount value in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions. You should however always try to have a minimal number of SPSite objects created at the same time and should always dispose them as soon as you’ve finished working with them. Secondly to get the stack trace of the not correctly disposed SPRequests (which is not enabled by default) you can set a value of 1 for SPRequestStackTrace  in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings registry key.  You can monitor the ULS trace messages in real time using the very light-weight SPTraceView utility. For detailed information and best practices on disposing SharePoint objects see the following MSDN article: Best Practices: Using Disposable Windows SharePoint Services Objects

Because creating too many unmanaged objects is a serious concern for a server application, Microsoft have implemented a couple of ways for those SPRequest objects to be cached and reused internally whenever this is possible. However this caching might cause additional problems such as: Reusing a cached version when you don’t really want this or attempting to reuse a cached version of the SPRequest on a thread different from the thread it has been created on. Before looking into those potential issues lets see how the caching of SPRequests works.

For managing the SPRequests SharePoint gets the help of two internal classes – SPRequestManager and SPRequestContext.  All SPRequest objects created in the managed world of Microsoft.NET are tracked and cached per process using an SPRequestManager object which singleton instance is saved in the HttpContext for web applications or in the ThreadContext of the SPFarm for non web applications (such as OWS Timer jobs, command line application such as custom STSADM commands or rich clients). This also means that this caching is per thread. The code below shows how the SPRequestManager is created and associated with the running thread:

private static SPRequestManager Instance

{

    get

    {

        SPRequestManager manager = null;

 

        if (HttpContext.Current == null)

        {

            manager = SPFarm.ThreadContext[typeof(SPRequestManager)] as SPRequestManager;

        }

        else

        {

            manager = HttpContext.Current.Items[typeof(SPRequestManager)] as SPRequestManager;

        }

 

        if (manager == null)

        {

            manager = new SPRequestManager ();

 

            if (HttpContext.Current == null)

            {

                SPFarm.ThreadContext[typeof(SPRequestManager)] = manager;

                return manager;

            }

 

            HttpContext.Current.Items[typeof(SPRequestManager)] = manager;

        }

 

        return manager;

    }

}

 Additionally to this the SharePoint Object Model may be also caching the opened SPSites when running in a web context. This caching is done with the help of the SPRequestContext class which single instance is stored in the HttpContext per server thread that processes the request.

internal static SPRequestContext GetCurrent(HttpContext context)

{

    if (context != null)

    {

        string str = “HttpHandlerSPRequestContext”;

 

        SPRequestContextreqContext = (SPRequestContext)context.Items[str];

 

        if(reqContext== null)

        {

            reqContext= new SPRequestContext(context);

            context.Items[str] = reqContext;

        }

 

        returnreqContext;

    }

 

    return null;

}

The site instances will be cached only if they have not been created with a farm admin account (when SPSite.m_bAdministratorOperationMode is false) . Please note that runing code using SPUtility.RunWithElevatedPrivilegies() method doesn’t mean your code will have farm administrator privileges. Whether a user is a farm administrator or not is determined by the SPFarm.CurrentUserIsAdministrator() method. An account will be a  farm admin if:

– It is the identity of the application pool used by the SharePoint Central Administration web application

– The account has been added to the SharePoint Administrators site group of the Central Administration web application

– The farm is being provisioned and the account is a local administrator or the Local System account

When you are using  SPUtility.RunWithElevatedPrivilegies() this will simply revert the current user identity to the identity of the current application pool, and if this identity is not a farm administrator then your SPSite _will_ be cached in the SPRequestContext. This is done when the SPSite object is created:

private void SPSiteConstructor(

    SPFarm farm, Guid applicationId, Guid contentDatabaseId, Guid siteId,

    SPUrlZone zone, Uri requestUri, string serverRelativeUrl, bool hostHeaderIsSiteName,

    Uri redirectUri, Pairing pairing, SPUserToken userToken)

{

   

 

    if (SPSecurity.ImpersonatingSelf && (userToken == null))

    {

        // We will enter here if the site is created inside SPUtility.RunWithElevatedPrivilegies()

        this.m_bAdministratorOperationMode = SPSecurity.ProcessIdIsGlobalAdmin;

    }

 

   

 

    if (!this.m_bAdministratorOperationMode)

    {

        // The site is cached here and may be reused when activating features

        SPRequestContext.RegisterSite(this);

    }

 

   

}

The following diagram shows at a high level the relationship between the various objects working with SPRequests:

 

As you see one of  the classes I added on the above diagram is the SPFeatreManager class. This class can be actually called from the unmanaged world to activate features when you are provisioning a WSS site and this is when a cached SPSite may get reused. Here is what will happen every time you create a site or a web from a Web-based SharePoint application (web part, aspx page or SharePoint itself) if the WSS site definition you are using has some features to be activated:

– Before you can initiate a site creation first there must be an SPSite object created. This will be either done by the SharePoint UI code behind or by you directly creating the SPSite. If the user identity used to create the site is not a farm administrator then the SPSite will be cached by SiteId and by UserToken in the current SPRequestContext.

– You now initiate a new site creation for example by calling SPWebCollection.Add()

– The SharePoint Object Model calls the corresponding unmanaged function of the SP.SPRequest COM object to create the site. This is ISRequest.CreateWeb()

– Based on the WSS site definition to be used for the site, there may be features to be activated. The SP.SPRequest COM object makes calls back to .NET using the ISPFeatureManager COM visible interface of the Microsoft.SharePoint.SPFeatureManager managed class in order to activate those features. It possibly calls EnsureTemplateAssociatedWebFeaturesActivated(). This results in any existing SPSitescached in the same HttpRequest for the same user to be reused. The SPFeatureManager.EnsureSite() method will reuse the cached SPSite or create a new one if there is no cached (when not running in HttpContext).

Now if you are using custom site definitions and depending on how complex are they i.e. how many features do you have and what they are doing, in some cases because the cached SPSite will be reused, you may get some very weird errors particularly when trying to provision two sites at the same time. Some of those errors which I have seen at least a couple of times each include:

———————————————————————————————————————————-

System.InvalidOperationException : You cannot invalidate the SPRequest object while it’s in use.
Source: Microsoft.SharePoint; Help Link: 
Stack Trace:    at Microsoft.SharePoint.Library.SPRequest.ReleaseResources()
    at Microsoft.SharePoint.SPRequestManager.Release(SPRequest request)
    at Microsoft.SharePoint.SPWeb.Invalidate()
    at Microsoft.SharePoint.SPWeb.Close()
    at Microsoft.SharePoint.SPSite.Close()
    at Microsoft.SharePoint.SPSite.Dispose()

———————————————————————————————————————————-

System.Runtime.InteropServices.COMException : Attempted to make calls on more than one thread in single threaded mode. (Exception from HRESULT: 0x80010102 (RPC_E_ATTEMPTED_MULTITHREAD))
Stack Trace:    at Microsoft.SharePoint.Library.SPRequestInternalClass.GetListsWithCallback(String bstrUrl, Guid foreignWebId, String bstrListInternalName, Int32 dwBaseType, Int32 dwBaseTypeAlt, Int32 dwServerTemplate, UInt32 dwGetListFlags, UInt32 dwListFilterFlags, Boolean bPrefetchMetaData, Boolean bSecurityTrimmed, Boolean bGetSecurityData, ISP2DSafeArrayWriter p2DWriter, Int32& plRecycleBinCount)
                       at Microsoft.SharePoint.Library.SPRequest.GetListsWithCallback(String bstrUrl, Guid foreignWebId, String bstrListInternalName, Int32 dwBaseType, Int32 dwBaseTypeAlt, Int32 dwServerTemplate, UInt32 dwGetListFlags, UInt32 dwListFilterFlags, Boolean bPrefetchMetaData, Boolean bSecurityTrimmed, Boolean bGetSecurityData, ISP2DSafeArrayWriter p2DWriter, Int32& plRecycleBinCount)

———————————————————————————————————————————-

ExeName: w3wp.exe, Machine: localhost, Severity: Unexpected, Product: ‘Windows SharePoint Services’, Category: ‘General’
ERROR: request not found in the TrackedRequests. We might be creating and closing webs on different threads. ThreadId = 24, Free call stack =    at Microsoft.SharePoint.SPRequestManager.Release(SPRequest request)
    at Microsoft.SharePoint.SPWeb.Invalidate()
    at Microsoft.SharePoint.SPWeb.Close()
    at Microsoft.SharePoint.SPContentType.CloseWebAsNecessary()
    at Microsoft.SharePoint.SPWeb.Close()
    at Microsoft.SharePoint.SPSite.Close()
    at Microsoft.SharePoint.SPSite.Dispose()

———————————————————————————————————————————-

All of the 3 errors suggest that a cached SPSite may have been reused from a different thread, when it actually shouldn’t have been. It is very difficult to say why those errors do occur but I believe it has to do with the SPRequestContext caching some SPSites which are being reused when activating features. One of the facts that supports this theory is that you don’t get those errors when you are creating the sites from a non HttpContext application such as a custom STSADM command for example. In that case there is no HttpRequest and no SPRequestContext class i.e. no SPSites are being cached and reused. One of the times when I was getting those errors and was trying to resolve the problem I found a couple of post in Internet from people having the same problem but there were no resolutions. Almost everyone experiencing those errors was saying that they don’t get the errors when their code was called by a console application (custom STSADM command).  I wasn’t able to resolve the issue and it left as a known issue in the product. If you have experienced the same problem and have managed to nail it down I would love to hear about your findings/resolution. To mitigate the risk of getting those errors I would suggest that you should:

– Avoid using custom WSS site definitions if they include custom feature receivers that contain complex code

– Consider provisioning your sites from a non HttpContext application whenever possible. OWSTimer jobs count as non HttpContext way of provisioning sites

Also remember that you may be getting those errors for a different reason that is completely unrelated to the SPRequestContext cache. For example if you really are trying to reuse SPWeb or SPSite on a different thread or if you are not disposing properly the SPSite/SPWeb.

And finally lets recap the story about the SPRequest. Almost all read/write content/metadata operations that you do using the .NET SharePoint object model use unmanaged class to do the job. This unmanaged class is called SP.SPRequest and is used from .NET via the SPRequest internal class. The class is implemented and exposed by the OWSSRV.DLL library and has almost 400 methods. Because the SPSite and SPWeb objects have a reference to unmanaged objects you must keep the number of SPSite/SPWeb objects that are active at the same time to a minimum and should dispose them as soon as you have finished using them. You can monitor the creation and disposal of SPRequest objects via the ULS log. In order to minimize the number of SPRequests used in a HttpContext application, SharePoint uses internal cache. It is possible your SPSite objects to be reused when you are creating a site or a web from a web application which site/web is based on a custom WSS site definition that contains custom feature receivers. In rare cases you may be getting errors because of this so if you are using custom WSS site definitions then keep the complexity of your custom feature receivers to a minimum. Consider creating your sites from a non HttpContext application such as an STSADM command, Windows Forms application or a OWSTimer job.

I hope you’ve enjoyed this not very short reading. My next post in the “Understanding SharePoint” series, which will not necessarily be my next post, will be about how asynchronous Event Receivers work in SharePoint and what traps people can get into.

23 Comments »

  1. Awesome, I read every word of it! Great article Hristo!

    Comment by Radi A. — 19 January, 2009 @ 10:08 am

  2. Great article.
    I also recently started a series of blog articles to explain what is going on the database layer when interacting with the SharePoint Managed API. Check out http://blog.dynatrace.com/category/net/sharepoint-net/

    Cheers
    Andi

    Comment by Andreas Grabner — 19 January, 2009 @ 3:33 pm

  3. Nice article,

    I just want to ask you if you KNOW that it is “supported” to use the COM object directly?

    The reason I ask is that I think that “the fact that ISPRequest is actually a _public_ COM interface implemented by the _public_ SPRequestInternalClass” does NOT indicate that the class or interface is intended to be public, it’s just because of how COMInterop works.

    I know you can’t just instantiate the SPRequest COM object and use it, you need to do some “advanced” initialization before you can call it’s methods and that init part is actually obfuscated by MS.
    (As you describe it we can get to an initialized SPRequest instance by using private reflection but that’s another story)

    This leads me to believe that MS never intended us to use the interface 😉

    Thanks for an interesting post.
    /Jonas

    Comment by Jonas — 19 January, 2009 @ 6:04 pm

  4. Hi Jonas,

    I think someone from Microsoft should answer your question, not me.

    What I have to say is that, yes all COM interfaces are public but the .NET class that is a wrapper of the ISPRequest interface is also public. This class as mentioned in my article is SPRequestInternalClass from the Microsoft.SharePoint.Library.dll. You can instanciate this public .NET class and call any method of the ISPRequest interface. This is what I meant by the interface being public.

    The reason I suggest using SPRequest to call the ISPRequest interface rather than creating an instance of SPRequestInternalClass is only because it is easier to get to it from your SPSite and because it catches some COM exceptions and rethrows SPExceptions. As you mentioned some part of SPRequest are indeed obfuscated. The reason for that is hiding security sensitive code because the SPRequest is cached per user. Probably security considerations is also why farm admin SPRequests are not cached at all.

    And speaking about whether something is supported or not I think the right question is whether a certain operation is supported not whether a method or class is supported. For example if you have formated your harddrive you can’t ask Microsoft to restore your data or pay for your lost data only because you have used the public method FormatHardDrive() from a supported API. Similarly if you have used public SharePoint .NET methods to run code with elevated privilegies and as a result have left a security whole and your server got hacked – again you cant ask Microsoft to support you, it’s your bad coding not their problem. Again if you use the ISPRequest to do something silly don’t expect to be supported.

    What developers need to learn is to write quality and solid code. And one thing that helps writing quality code is understanding more about how the SharePoint platform works and this is what I try to focus on in my blog. Having a list of “supported” classes certified by Microsoft doesn’t make your code solid, it doesn’t fix your bugs and doesn’t save you from Microsoft bugs.

    Finally if someone wants to say that supported classes are tested more and better I defenitely think that the COM class has been tested more and better in this case and not the .NET object model of SharePoint. So this means it is more likely to find bugs in the managed object model rather than in the unmanaged COM class. The reason for this is that the unmanaged COM class has been around for a lot longer, it has small number of methods and is much easier to test completely, it is used via ISAPI from Microsoft Office desktop applications so there has been extra testing done compared to the .NET object model and by testing the .NET object model you actually test the COM class as well because this is what the object model is calling.

    So to recap my opinion: Developers need to learn to write solid code, they need to learn more about how things are working and not about which APIs are “supported”. If you don’t know what you are doing – don’t do it and learn more how it works before you do it. No matter if you are using the managed .NET classes or ISPRequest or assembly language. It’s all the same principles for good quality. And I only hope that it is actually the “good quality” that is your top priority as a developer.

    Comment by hristopavlov — 19 January, 2009 @ 10:56 pm

  5. Hristo,

    Thanks for your reply, and I do agree I should ask MS not you 🙂

    But you obviously have done some deep diving into the inner workings of the platform and you are making this info “available” and you “uncover” a lot of details that can “cause some problems” in the wrong hands 😉

    Let me give you an example of what I mean:
    As you explained in your post the ISPRequest “interface” has 400+ methods. It’s obviously much more like a dll with 400 exports than an “interface” which should have a well defined set of operations.

    And as you know quite a few of these methods take callback interfaces, how should these behave? Who owns the memory? (The COM part of SharePoint is notorious for not using BSTR’s but char/wchar and so on. Because of this basic COM allocation rules does not always apply in SP land. What are the required calling sequences (I assume some of these 400 methods are not atomic but have call dependencies because of the sheer number of methods)?

    And finally like you said “most” SharePoint devs are completely unaware that the “gut” of WSS is implemented in unmanaged code, most people tend to think that it’s a “classic” (ASP).NET application, I’ll go as far as to say they don’t even know what COM is.. or that it’s dead 😉

    Interesting information non the less, waiting for more.

    Thanks again!
    /Jonas

    Comment by Jonas — 19 January, 2009 @ 11:45 pm

  6. Jonas,

    Thanks for your follow up. It is good to see that there are people that know what COM is. I don’t think it’s dead because it’s everywhere in Windows including the .NET runtime 🙂

    > you are making this info “available” and you “uncover” a lot of details
    > that can “cause some problems” in the wrong hands

    Yes I agree. But I don’t see anything wrong in promoting for example the RunWithElevatedPrivilegies() method and saying that it can do very nice and powerful things. It may become a problem if used with bad code or if used by someone that doesn’t understand how it works. In a similar way I don’t see anything wrong in promoting the ISPRequest interface and saying that it can do very nice and powerful things. Again used with bad code it could cause a trouble.

    > SharePoint is notorious for not using BSTR’s but char/wchar and so on.
    > Because of this basic COM allocation rules does not always apply in SP land.

    The SPRequestInternalClass managed class defines all the marshalling of types that needs to be done by COMInterop so the calls to the SP.SPRequest COM object from .NET will work okay. So I don’t think this is an issue.

    > And as you know quite a few of these methods take callback interfaces,
    > how should these behave? Who owns the memory?

    Well again it is COM Interop related issue and this may be a tough one. But it is no different than using say Excel automation from .NET. You need to know which objects to release and most .NET developers don’t have a clue and as a result have those hanging instances of Excel.exe running on the server and I’ve even seen people using Process.Kill() to kill those:) Again the problem is not that someone has used the Excel Interop object model it is the lack of understanding how things work. This is why again I am blogging. What I will be trying to do with the “Understaning SharePoint” series is sharing my findings about the SharePoint internals because knowing more about how SharePoint works can only help you write better code.

    Comment by hristopavlov — 20 January, 2009 @ 2:38 am

  7. […] to the SPList and SPView. The following illustration shows usage and performance metrics based on SPRequest method invocations: Analyzing Performance and Usage through SharePoint Object […]

    Pingback by Performance, Scalabilty and Architecture - Java and .NET Application Performance Management (dynaTrace Blog) » SharePoint: Monitoring individual List usage and performance — 22 January, 2009 @ 2:02 pm

  8. […] Understanding SharePoint: SPRequest – very impressive […]

    Pingback by Links (1/22/2009) « Steve Pietrek - Everything SharePoint — 23 January, 2009 @ 12:57 am

  9. I will not comment on the fact that this blog shows reverse engineered source code of SharePoint.
    Someone else can decide if this is a violation of rights hold by Microsoft.

    But I will comment on the statement that it is save to use SP.SPRequest in a custom application:
    This is NOT a public API! This class is undocumented and it’s use is unsupported!

    Any application based on this is unsupported.
    In addition: any SharePoint database which is modified using direct access to this undocumented API will become an unsupported state as if you would have modified the database using direct SQL queries.

    See here for details on this:
    http://blogs.technet.com/stefan_gossner/archive/2005/07/27/undocumented-API-Part1.aspx

    Comment by stefangossner — 23 January, 2009 @ 7:36 am

  10. Hi Stefan,

    Thanks for clearing the important question of what is supported by Microsoft and what not. This is really appreciated.

    Please note that the information in this blog is retrieved using the widely used .NET Reflector. Microsoft actually supports numerous open source add-ins for Reflector on CodePlex and also people blog on msdn.microsoft.com about how useful Reflector is for example to “See SharePoint’s Source Code”: http://blogs.msdn.com/markarend/archive/2008/02/28/using-reflector-to-see-sharepoint-s-source-code.aspx. This is possible because Microsoft has intentionally left the vast majority of the source code of SharePoint unobfuscated which clearly indicates their understanding that showing implementation details to the developers and the community could only help this community write better code.

    My intention with the “Understanding SharePoint” blogs is to present in a systematic way parts of this freely available information and I do this for the sole purpose of helping developers write better code.

    Comment by hristopavlov — 23 January, 2009 @ 10:47 am

  11. […] of SharePoint however is mostly implemented in native code which is wrapped by certain classes. Hristo Pavlov wrote a great article that explains the special wrapper class SPRequest which plays a very central […]

    Pingback by Performance, Scalabilty and Architecture - Java and .NET Application Performance Management (dynaTrace Blog) » SharePoint: Identifying memory problems introduced by custom code — 12 February, 2009 @ 3:01 am

  12. […] receivers in SharePoint with the exception of the ListItemFileConverted receiver are run from the SPRequest unmanaged class. There are two types of event receivers – synchronous (such as ItemAdding and […]

    Pingback by Understanding SharePoint: Event Receivers « SharePoint Internals - Hristo Pavlov’s Blog — 24 February, 2009 @ 10:22 am

  13. I think Mark may have copped a bit of the internal Microsoft stick since your post – the article you reference has recently had a “Disclaimer” added to it –

    Important Note: Customers are advised to review the end user license agreement (EULA) for the relevant Microsoft products before using this tool. This blog entry does not authorize or endorse any use of Microsoft products that is not addressed specifically by the product’s EULA.

    Doesn’t appear in the “Snap” screenshot when you mouse over the link though… 🙂

    Comment by Brad Saide — 7 March, 2009 @ 11:52 am

  14. Although I understand Stefan’s comment about reverse engineering SharePoint code, but I think this article helps to understand what’s happening under the covers so developers can understand why these obstacles exist.

    Comment by Suman Chakrabarti — 6 April, 2009 @ 6:24 pm

  15. […] end up with a call to the SPRequest class. Hristo Pavlov has a great post about the internals of SPRequest. This transition to unmanaged code is the reason we have to call Dispose on our SPSite and SPWeb […]

    Pingback by Running Windows SharePoint Services on Linux - The Bamboo Team Blog - Bamboo Nation — 1 July, 2009 @ 2:37 am

  16. Hello there

    To my dismay, I’ve just run into:
    RPC_E_ATTEMPTED_MULTITHREAD

    I have a non SP ASP.NET web application, which uses SharePoint as a datastore. I have ashx files which load images and files stored in SP. Now I was trying to have a single static SPWeb object to service multiple file loads.. and of course hit this problem – when loading multiple images on one page, SP just doesn’t let you do that.. so I’m forced to try an alternative solution =(..

    Thanks for the info anyhow.

    Comment by =8)-DX — 28 July, 2009 @ 3:03 pm

  17. […] calls from list item update to SPRequest methods (find out more by reading brilliant code posting Understanding SharePoint: SPRequest by Hristo Pavlov) that Reflector wasn’t able to disassemble. As soon as I saw request I got the […]

    Pingback by SharePoint problem: moderation comment is not saved - Gunnar Peipman's ASP.NET blog — 10 August, 2009 @ 10:23 am

  18. Awesome! Very useful information Hristo!
    Hristo,Do yOu have any information about FPUGA(File print user grp administration) in WSS2003?

    Comment by Audey — 25 January, 2010 @ 2:40 pm

  19. Very detailed post ..
    Nice !!

    Comment by Sharepoint Italia — 16 February, 2010 @ 10:52 am

  20. […] object model.  There is a method called AddGhosted in the internal SPRequest class, but using SPRequest to bypass the public API leaves your installation in an unsupported state, which is a Bad […]

    Pingback by Changing the disk location of uncustomized (ghosted) pages « The SI SharePoint Blog — 2 March, 2010 @ 1:13 pm

  21. […] call him Doctor SharePoint. By benkaboo This article explains just how much of the SharePoint API is accountable to unmanaged code. This also gives a […]

    Pingback by You call him Doctor SharePoint. « Sense the balance shift — 18 April, 2010 @ 5:18 am

  22. So I have an issue – I think given your obvious expertise in this area you may be able to assist. I’ve spent 2 weeks on this trawled the web can’t find satisfactory answer. This relates to the SPS internals.
    Issue : I run a web application under the context of a farm admin (via app pool), make a call to .UpgradeFormTemplate(string) on the OM – and get an “access denied” every time. It’s intermittent – and what’s worse – looking at the internals, the .IsCurrentUserFarmAdmin() – “caches” the previous results in a static collection. (Meaning new calls to that method return the same value even if permissions change, until the appool is recycled). I’ve managed to trace this down the check for farm admin permissions to the point where a call is made out to SPRequest.GetCurrentUserPermissionOnGroup(string bstrUrl, int lGroupID, out bool pbCanViewMembership, out bool pbCanEditMembership, out bool pbCanManageGroup, out bool pbIsCurrentUserInMembership, out bool pbIsCurrentUserInDirectMembership).
    I cannot see what this method does (its wrapping managed code), but looking at the parameters it must connect to the db. So theoretically this should fail every time unless my ‘app pool’ account has DBO permissions (which it does not), but the results are intermittent. Any Idea?

    Comment by PM — 26 May, 2010 @ 5:30 am

  23. Hi Hristo

    Wow – thanks for sharing your insights.

    In summary – looks like
    – managed code – handles ASP.NET page display processing and other stuff but
    – unmanaged code – handles all interactions with the back-end databases

    If you know, could you say a few words about if/how the unmanaged code uses the Tabular Data Stream (TDS)protocol?

    Best regards
    James

    Comment by James McGinley — 23 November, 2010 @ 11:52 pm


RSS feed for comments on this post. TrackBack URI

Leave a comment

Create a free website or blog at WordPress.com.