Winsmarts.com

Microsoft MVP

MVP Logo

Awarded the Microsoft MVP Award.

Hosted By

blah!bLaH!BLOG!!

SharePoint 2007 as a WCF host - Step #4, Write a Virtual Path Provider

Posted on 5/9/2008 @ 10:46 PM in #Sharepoint | 1 comments | 755 views

Table of Contents for SharePoint as a WCF host


1. Create a WCF Home. This is the virtual directory that will host all your WCF endpoints.

2. Create a WCF Service Library, and throw it in the GAC.

3. Create a relevant .svc file in the WCF home you created in step #1.

4. Write a WCF Virtual Path Provider, and register it in the SharePoint site.


As I just mentioned, the SPVirtualPathProvider blows up when it see's a URL that starts with '~'. Luckily, the problem is easy to fix. You simply author your own Virtual Path Provider.

In order to write your own VirtualPathProvider, you have to author a class that inherits from the System.Web.Hosting.VirtualPathProvider class. Now, you might be thinking that this will be a very difficult job - considering the SPVirtualPathProvider does SO MUCH work in making the content database paths, and physical paths work together. If I had to do all that work, I'd be howling and screaming like a hungry dog that just got kicked. Thankfully, the VirtualPathProviders work in a chained form - so all you've gotta do is, chain yours AFTER the SPVirtualPathProvider. (I'll talk soon about how to register your Virtual Path Provider).

This way, the previous VirtualPathProvider (in our case, the SPVirtualPathProvider), is accessible using the "Previous" property on the VirtualPathProvider class.

Thus, my custom VirtualPathProvider looks like this -

   1:  public class WCFVirtualPathProvider : VirtualPathProvider
   2:  {
   3:      public override string CombineVirtualPaths(string basePath, string relativePath)
   4:      {
   5:          return Previous.CombineVirtualPaths(basePath, relativePath);
   6:      }
   7:   
   8:      // all other methods omited, they simply call Previous... like the above.
   9:   
  10:      public override bool FileExists(string virtualPath)
  11:      {
  12:          string fixedVirtualPath = virtualPath;
  13:          if (
  14:            virtualPath.StartsWith("~") &&
  15:            virtualPath.EndsWith(".svc")
  16:              )
  17:          {
  18:              fixedVirtualPath = virtualPath.Remove(0, 1);
  19:          }
  20:          return Previous.FileExists(fixedVirtualPath);
  21:      }
  22:   
  23:      protected override void Initialize()
  24:      {
  25:          base.Initialize();
  26:      }
  27:  }

So really, my funky logic goes in a single method - the FIleExists method.

Okay, fantastico. The next question is, how the heck do I register this VirtualPathProvider into my SharePoint / Port 80 site? Well the code to do so is quite simple as shown below:

   1:  WCFVirtualPathProvider wcfVPP = new WCFVirtualPathProvider();
   2:  HostingEnvironment.RegisterVirtualPathProvider(wcfVPP);

But, the above must be executed ONLY once. ONLY Once - after each IISRESET :-). Yep, ASP.NET forgets the virtual path providers it was using if you issue an IISReset, or modify the web.config - basically everytime the application recompiles.

So, the mostest bestest place to put such code, is inside an HttpModule, and use a static variable to check and see that you don't register this VirtualPathProvider over and over again. Here's the code for the HttpModule -

   1:  public class WCFVPPRegModule: IHttpModule
   2:  {
   3:      static bool wcfProviderInitialized = false;
   4:      static object locker = new object();
   5:   
   6:      public void Init(HttpApplication context)
   7:      {
   8:          if (!wcfProviderInitialized)
   9:          {
  10:              lock (locker)
  11:              {
  12:                  if (!wcfProviderInitialized)
  13:                  {
  14:                      WCFVirtualPathProvider wcfVPP = new WCFVirtualPathProvider();
  15:                      HostingEnvironment.RegisterVirtualPathProvider(wcfVPP);
  16:                      wcfProviderInitialized = true;
  17:                  }
  18:              }
  19:          }
  20:      }
  21:  }

Ok good job.

Now put both of the above in the GAC (I put them both as 2 classes in a single assembly called WCF Support). Modify the web.config to register the HttpModule - which in turn will register the WCFVirtualPathProvider. This is as shown below:

   1:  <add 
   2:     name="WCFVPPRegModule" 
   3:    type="WCFSupport.WCFVPPRegModule, WCFSupport, Version=1.0.0.0, Culture=neutral,PublicKeyToken=d4f7bd9e55b39661"
   4:  />

NICE.

Now, browse to your WCF service, and you should merrily see the below -

.. Umm .. that's basically it. You can now start using the SharePoint object model in the WCF service, and merrily expose SharePoint functionality on a variety of endpoints. Now THATS cool!


On 5/14/2008 5:58:22 PM Steve Clements said ..

That is indeed cool...great series :)

Please post your comments:


Your feedback will be submitted for moderation, and will appear after it is approved.

Name:  
Email (optional): Your email address will not be posted.
URL (optional):
Comments: HTML will be ignored, URLs will be converted to hyperlinks  
Enter the text you see in the box:
 

Site designed and maintained by Sahil Malik | All Rights Reserved. ©2007 WinSmarts.com.