Skip to main content

Wouter

Go Search
Home
Contact Me
  

 ‭(Hidden)‬ Admin Links

About the CKSDEV and Microsoft PowerTools Sandboxed Web Part

Early last year I thought it was fun to rise to the challenge of creating a visual (designable) Web Part that could be deployed into the SharePoint 2010 Solution Sandbox. Mostly as a fun programming exercise and also because I wasn't sure how it could be achieved. In the end I got a pretty decent working solution that is now part of CKSDEV.

A while ago Microsoft also released a set of productivity extensions for the SharePoint sandbox. The PowerTools contain two new features; sandboxed compilation and… a Visual Web Part. Both features are also present in CKSDEV> A duplication which is best avoided. The CKSDEV team quickly decided to drop our versions in favor of Microsofts. Being the author of both features I want to go over the differences between the two and the reasoning behind dropping our features.

(Note that we only drop the template needed to create new sandboxed Web Parts, existing code will remain to work)

Sandboxed compilation

The motivation for this feature in CKSDEV was to provide additional compile-time information because certain methods are not available in the sandbox and normal compilation still allows you to call the unavailable code. My approach sucks a bit. It is only partly integrated into Visual Studio. When you hit 'Compile for Sandbox' the project references are updated to point to the sandboxed object model, a compile is forced and next the references are put back into place. This means you have to check out the project for this to work, and it modifies your project too. (It did only take a few lines of code thoughJ)

The Microsoft approach is integrated much further into the build process of Visual Studio. No fussing with swapping project references. All in all it is a much cleaner model. When you compile it either compiles against the sandbox or it compiles normally, depending on project settings. It also enables the red squiggly lines that appear as you type your code to indicate something will not compile when you would hit F5. This is something that we as the CKSDEV team cannot achieve with the current approach. So, Microsoft's version clearly wins in terms provided level of functionality. Luckily, we only have to remove our button and drop the code. There are no runtime dependencies within your actual projects.

Sandboxed Visual Web Part

This one is a bigger story. Both CKSDEV and the PowerTools provide their own template for creating a Sandboxed Visual Web Part. There is only one similarity in the approach. Both versions have no runtime requirement for including our DLLs. Everything you need is either generated or typed by you, but that is pretty much it. Let me begin with explaining how the CKSDEV version works (which was first to hit the market! They'll never take that away from me J).

Basically both approaches parse the ASCX file when you save it, and the generated code is added to your project. That way parsing does not take place at runtime outside of the sandboxed environment.

One of the biggest challenges for CKSDEV was to find a way to parse a User Control (ASCX) file and push the generated code into the project. The ASP.NET User Control parser is hidden from the public so calling it directly is not an option. There are a few ways to work around this issue. The workaround applied by CKSDEV was to call the aspnet_compiler.exe tool with the –debug flag. This forces the code generation to take place, obviously with too details like line pragma's and other unnecessary stuff. We then scoop up the generated code and push the code into the project. The overall code structure resulting from this approach is shown in the following graphic. Blue means generated, green is stuff you type.

Lots of blue stuff for little green stuff!

The Microsoft approach to parsing the ASCX is to use the ClientBuildManager class provided by ASP.NET. I also wanted to use this class but getting it to work exactly as I wanted involved lots of CodeDom and more work than I wanted to do. The ClientBuildManager is able to generate code into a CodeDom CodeCompileUnit which you then transform into code using an ICodeGenerator from .NET. This approach is more involved and requires the generated to be buffed and polished. We choose not to learn too much CodeDOM, but obviously that knowledge is already inhouse somewhere in Redmond. The structure is much different though. Since you get back a CodeCompileUnit (basically a parse tree) you can modify the tree to suite your needs. One cool effect the Microsoft approach then has is that your resulting code does not use the UserControl base class but directly creates a Web Part. The benefit is less classes to generate and maintain. The graphic is as follows.

The difference for you as a user of the template is primarily visible in the code-behind. For the CKSDEV approach the method that instantiates the generated controls is called automatically by the UserControl base class in the Init phase of the page lifecycle. For the PowerTools edition this method is called by you. Other notable differences is that the CKSDEV approach allows you to use <script runat="server"> blocks differently from the PowerTools. The reason for this is that the PowerTools use a single class and CKSDEV has a class hierarchy. Say that you use a script block to override the OnLoad method. If you do the same in the code-behind you'll have two methods with the same signature, going in the same class. For the CKSDEV version the OnLoad would be added in a different class and hence you can combine <script runat="server"> blocks with normal code-behind without thinking about it.

Supporting the CKSDEV Sandboxed Web Part

Given the fact that you may have already invested in the CKSDEV Sandboxed Web Part we are not happy to remove the feature. To ensure that we don't break your build we choose to keep the internal code in place, but we'll remove the Visual Studio template. This means you'll no longer have an easy time creating new CKSDEV Sandboxed Visual Web Parts, but the existing ones will keep on working as is. We do plan to provide a conversion tool to convert the CKSDEV version to the Microsoft version. But given the large differences in the approach there are a few technical difficulties that take a bit of time to overcome. (we'll for instance need to swap out your base class of UserControl in favor of WebPart). One thing that we'll not likely be able to achieve is a conversion tool that will not break existing deployed Web Parts, so there's still some discussing to be done how to handle that.

Hope this clarifies some of the differences between the PowerTools and the CKSDEV version. Of course CKSDEV will continue to provide you with much needed enhancements to the Visual Studio 2010 out of the box experience, these two will just not be part of that).

Did I say you should get CKSDEV RIGHT NOW! J

Naming your SharePoint accounts

One of my big focusses when writing software is not to get it to just work, but to get it to work correctly. Hence I spend a ton of time learning about different approaches to solving my SharePoint needs. One area that I focus on in a similar fashion is building my SharePoint VMs. Back in the 2007 days I started building my VMs according to the least privilege principle, e.g. not making everything run under the admin account. Now, if you do that, you must name your service accounts. It suffices to say I take the same level of passion I have on coding approaches to the world of IT Pro stuff. I come across a ton of funky account names that make me wonder how discoverable it all is. Stuff like SPSVCAPP. Right, I cannot even pronounce it, let alone remember.

So, without further ado, here's my list of account names I typically use when installing SharePoint. Usually I create a separate OU in active directory to group them, or I use the existing OU when running on 2008R2. Note that this is for SharePoint 2007.

Account

Goal

Configured when

SPSqlService

Run SQL Server

Installing SQL Server

SPAdminService

Run Central Admin

Installing SharePoint

SPSharedService

Run Shared Services

Creating the SSP

SPSearchService

Run WSS / MOSS Search

Configuring search

SPCrawlerService

Crawl SharePoint content

Configuring search

SPWebService

Run content application pools

Creating app pools

As you can see I have a naming convention with the following characteristics:

  • Readable, not just acronyms. Don't make me think rule at play here
  • Prefix with SP. Just to stuff it all together a bit more and to indicate that they are for SharePoint
  • Postfix with Service. Indicate that you should not use these accounts for actual logging in, except for the SPAdminService.

Personally I especially like the SPWebService account. You *must* be a SharePoint geek to enjoy that one right? It is the service account that spoons up webs out of the database, hence, SPWebService. Some name it SPWorkerProcess, also fine I'd say.

Hope it helps, and have fun naming your accounts.

Presenting at SharePoint Connections Autumn

Just got word that my proposal for the SharePoint Connections event was accepted. I'll be presenting on the new Access Services capabilities in SharePoint 2010 as well as presenting a full day post conference on SharePoint development techniques. Awesome! Personally I was quite amazed to learn how much cool stuff you can build on Access so I am very much looking forward to spreading the news. Many of you perhaps know me as a developer, and as it is with many developers, Access was a loooooong way down the Technologies-I-Would-Use stack, but with the pretty awesome server side presence in SharePoint….. Next up: post conference. This will be an ideal way for you to pick up on development techniques that are vital to any project, Foundation or Server, small or large. We'll go deep on a bunch of topics, all Foundation features so usable anywhere. Come visit and enjoy learning SharePoint even better!

Service Applications 104 – Across the wire

This is the fourth part of a series on Service Applications. The following has already been posted:

Find the code for this sample on my CodePlex demo portal under the Navigation Service with WCF Proxy release.

Introducing WCF as an offloading mechanism

In the first three parts of this walkthrough you were introduced to the concept of service applications, on the basic steps to create one and finally on how to add a proxy layer to provide an extra level of indirection between the application and the consumers. In this blog post will show how to move the proxy to the next level by introducing WCF as a mechanism to push incoming requests to backend application servers.

The earlier three blog posts laid down the foundation for this first full-blown service application. A few extra components need to be added. Another few existing classes need some extra attention. I also threw in a testing page that is accessible from the Ribbon on the application management page. Hopefully this enables you to have an easy time seeing whether your code actually works (mine does, yay!)

The following is a list of todo items for moving the last application with the simple proxy to one that is enabled by WCF

  • Start making use of new base classes for the service, service proxy, service application and service application proxy.
  • Create a new service instance class to represent the service on a particular backend server
  • Add a WCF contract interface
  • Add the WCF service and client configuration
  • Implement the WCF client and server code

That's it. A bit involved as you can see from the list of items that need to get done, but we can just start at the first and work your way down the list.

Introducing new base classes

Now that we are moving towards a WCF enabled system there are a lot of new base classes to use. Earlier we had the SPService, SPServiceProxy, SPServiceApplication and SPServiceApplicationProxy. For working WCF you can swap all these out with their counterparts. SPIisWebService, SPIisWebServiceProxy, SPIisWebServiceApplication and SPIisWebServiceApplicationProxy.

The SPIisWebService

Where earlier you derived your service class from SPService, you now need to move towards the SPIisWebService. Not that much difference in implementation. The only code that goes in this class is internal. It maintains a bunch of settings such as default endpoint names and network port numbers.

The SPIisWebServiceProxy

The replacement for the SPServiceProxy is the SPIisWebServiceProxy. Examine the class with .NET Reflector and notice that there is absolutely nothing it does extra. The reason it exists is likely to achieve some parity between all relevant classes (all SPIisWeb… classes).

The SPIisWebServiceApplication

The service application for WCF is a bit more complex in its internals. It maintains references to the IIS application pool used to serve incoming requests. There are many IIS related settings such as endpoint configuration. It iments a configurable backup strategy for the application, proxies and any databases you may have. You will also find a small model for configuring service security, allowing you to implement your own permission types. So, this class is definitely worth a further look after you have gotten your basic application going.

The SPIisWebServiceApplicationProxy

Closing the line of new base classes is the proxy for the service application. Again you will find support for easily integrating with the backup functionality. The proxy also serves as a place to store what address the proxy will connect to when used.

Updating the service and service proxy

When it comes to code changes, let's begin with the service and service proxy since these two components have the least going on. They are only there to support the larger infrastructure and do not contain any WCF specifics. The service itself only has a new base class. The rest of the changes are specific to the service proxy.

The first change you find in the service proxy is that you need to add the SupportedServiceApplication attribute. This attribute links the service proxy to a service application. You can add as many attributes as the number of service application types that your service supports. The attribute is used to fill the user interface presented as part of the Connect menu. After you enter the service URL you will be shown a list of service applications you can connect to. This list is created using the information from this attribute. Since our service will now truly support connecting proxies with applications you'll need to add this attribute. Earlier editions of the proxy didn't need this since we weren't using WCF yet.

How it works is that you will open the Connect menu and choose a service application type to connect to. Under the covers the value in this attribute is read. In the Connect to a Remote Service Application dialog that appears you will enter the URL of a farm, hit next. On the second page of the connection wizard a filtered list of available service applications is provided for you to choose from. This list is filtered based on the attribute's value, allowing filtering on the application type and the application version.

[SupportedServiceApplication(
    "f46c5a6a-0f73-4c1e-b11b-c2ffb70c19f9"
    "1.0.0.0"
    typeof(NavigationApplicationProxy))]
The next major change that you find in the service proxy is an implementation of the IServiceProxyAdministration interface. This interface is used by SharePoint during automated processes as well as to fill the Connect menu.


The implementation of this interface is a huge no-brainer. All the methods you need to add are one-liners.

Implementing the WCF Service
Moving to a client / server model obviously requires you to implement the server (hint, the client too!). In many of the service applications that you find inside SharePoint you find a common approach. Most of the service application objects implement the WCF service. For the Navigation Service we'll do the same. Although technically not necessary, we'll begin with defining a service contract. For the demo's sake it is a bit sparse in terms of the functionality that we'll provide to consumers.

[ServiceContract]
public interface INavigationApplication
{
    [OperationContract]
    string GetNavigationInformation();
}
The next step is to change the base class for the NavigationApplication. Instead of deriving from SPServiceApplication we now extend SPIisWebServiceApplication. This base class requires you to implement two properties that point to the .SVC file that is used as the endpoint address. You will deploy the .SVC file to the WebServices folder which is a new folder found directly under the SharePoint 2010 installation path.

public class NavigationApplication
    : SPIisWebServiceApplication
    INavigationApplication
{
    protected override string InstallPath
    {
        get 
        { 
            return SPUtility.GetGenericSetupPath(
                @"WebServices\CodeCounsel.SharePoint.NavigationService"); 
        }
    }

    protected override string VirtualPath
    {
        get { return "Navigation.svc"; }
    }
}
Under the covers the InstallPath and VirtualPath values are combined to locate the .SVC file. This file is deployed as part of your project. In the .SVC file there is a pointer to the NavigationApplication class as well as to a new class which task it is to instantiate the WCF service host.

<%@ServiceHost

language=C#

Service="..."

Factory="..."%>

The factory is specific to your scenario. There is a factory for SOAP based services, for REST services and for ADO.NET data services. In the factory class there is only one specific bit. It activates claims security for the service.

public class NavigationApplicationHostFactory
    : MultipleBaseAddressBasicHttpBindingServiceHostFactory 
{
    public override ServiceHostBase CreateServiceHost(
        string constructorString, Uri[] baseAddresses)
    {
        ServiceHost host = new ServiceHost(
            typeof(NavigationApplication), 
            baseAddresses);
        host.Configure(SPServiceAuthenticationMode.Claims);
        return host;
    }
}
The final part on the server side of the service application is the web.config that defines the service endpoints. You can specify details such as the communication protocol, TCP, HTTP, HTTPS etcetera. There are a huge amount of settings you can configure but luckily you don't need them all. The easiest is to copy an existing web.config, for instance from the Topology service and modify that to suite your needs. Just make sure you set the <service name=""> to the actual name of the service class (namespace + classname) and do the same for the contract.

Implementing the WCF client

Now that we have a server let's also create the client. The service application proxy will serve this task. When you examine existing implementations there is quite a lot of juggling with delegates to prevent duplication of code. In the Navigation Service demo however I chose to implement all functionality inline. Not smart, but better to read.

The first change in this class is that you can and most likely want to add a load balancer class. SharePoint provides a basic load balancer that chooses between available endpoints in a round robin fashion. You can also not use a load balancer, up to you. But it's only a few lines of code to add, so, add it already!

Since the WCF proxy class is mostly the same as the previous edition without WCF I'll not reiterate all the existing methods. Let's focus on the how to call the service application running on a backend server. The first thing you'll need to do is open the .NET configuration file that contains similar information as the server configuration. Endpoint and security data is what you'll find in the client.config file. You can make use of the .NET configuration APIs to open the correct client.config, which will be provisioned to the WebClients folder under the SharePoint 2010 installation path. Based on this configuration data you will instantiate a ChannelFactory for the service interface you added earlier. The ChannelFactory wants to know the specific endpoint that you want to use. In this sample it is hardcoded, but you could also determine the correct endpoint based on the URL that the proxy is connected to (URL starts with HTTPS:// it'll be the HTTPS endpoint right?) Next, use the load balancer to open a session and open the channel to the backend. The last step is to actually call the WCF service and return results.

public string GetNavigationInformation()
{
    string channelConfigPath = SPUtility.GetGenericSetupPath(
        @"WebClients\CodeCounsel.SharePoint.NavigationService");
    Configuration clientConfig = OpenClientConfiguration(channelConfigPath);
    ChannelFactory<INavigationApplication> factory =
        new ConfigurationChannelFactory<INavigationApplication>(
            "http", clientConfig, null);
    factory.ConfigureCredentials(SPServiceAuthenticationMode.Claims);

    SPServiceLoadBalancerContext context = _loadBalancer.BeginOperation();
    try
    {
        INavigationApplication channel = 
            factory.CreateChannelActingAsLoggedOnUser<INavigationApplication>(
                new EndpointAddress(context.EndpointAddress));
        return channel.GetNavigationInformation();
    }
    finally
    {
        context.EndOperation();
    }
}
In terms of doing things better you'll likely want to do some caching since instantiating channel factories and opening / parsing configuration files are expensive pieces of code.

Enabling the service on backend servers

Now that we have both a WCF server and a WCF client we also need a way to specify on what servers in our farm we want to run the service. This task falls in the hand of the SPServiceInstance, which is basically a class that couples your service with a specific server. What you need to do is instantiate an instance of this class for each server in the farm that you may want to run your service on. You can then go to the Services on Server page and start your service. This action will provision your service instance on that server and make it available for WCF requests.

Testing your work
The last step is to test the new WCF proxy based implementation. To make this easier to do I added a menu item to the Ribbon. It opens a testing page which calls the service application via the proxy.


Hope it helps!



















Service Applications 103 – Simple Proxy Big Results

This is the third part of a series on Service Applications. The following has already been posted:

Find the code for this sample on my CodePlex demo portal under the Navigation Service with Proxy release.

Working with proxies

The first sample Service Application that I showed only brings a certain level of usefulness. The first demo application did not use a proxy and without a proxy you are functionally stuck with having only a single Service Application instance to service all the web applications in the entire farm. This stems from the fact that you can't configure the Web Application binding to Service Applications when you do not create a proxy. So, quite quickly you'll want to move away from this simple approach and tack on a proxy layer too. For some added background, a service proxy is a component that relays calls to your application on behalf of a consumer. It allows you to implement an extra level of indirection between caller and callee. The most common implementation of this pattern is to use the proxy as a WCF client and expose the application as a WCF service. That way you can offload incoming requests to backend application servers. Great stuff! You can also create a Service Application / Proxy combination without using WCF. Simply call methods on the application directly from the proxy instead of instantiating a WCF client and going through that route. You still get to enjoy the benefit of binding web applications to specific instances of the service, but obviously you lose out on pushing requests out to the backend.

In this blog post I will show how to add this second layer of indirection to the Navigation Application introduced in part 2. No WCF proxies just yet though. I'll cover that in the next post.

New components in this version

In my previous post I showed the Navigation Application and the two primary components. You were introduced to the SPService, representing a farm-wide service and the SPServiceApplication which implements that farm wide service for specific web applications. When moving towards a proxy based implementation you get to add a few extra pieces to the puzzle, most notably a service proxy and a service application proxy.

The SPServiceProxy class allows SharePoint to know about what the proxies in your specific solution. This is similar to how the SPService provides information about the service applications that you have. Next is the service application proxy, which is a proxy to the service application itself, instantiated by the service proxy.

Service Proxies

The service proxy in the new demo application is doing two things. First of all it serves as a factory for new service application proxies. Next, it provides a known point for SharePoint to ask about what proxies you can create, for instance to populate the Connect menu on the Service Application Management page.

Service Application Proxies

These then, are the components that forward calls to the Service Application they are a proxy for. How they do this is to be decided however. In the simplest case you just look up the correct SPServiceApplication instance by ID and call methods directly on it. The harder case uses WCF as an intermediate layer. Doing so is not as hard as exposing a WCF service in SharePoint 2007. You now benefit from built-in support for WCF, and it is not as gnarly as creating web services in 2007.

The IServiceAdministration Interface

There are a few important things that SharePoint needs to know about the Service Applications that your code supports. First of all, during farm provisioning (psconfig) you can opt in for having your service application created. Also, SharePoint needs to populate the New and Connect menus on the Manage Service Applications page. You cannot really ask the item that is created on the New menu for the content of the New menu right? You need to use the parent, and in this case that parent is the SPService. Being a generic 'farm-wide' service it makes no sense to ask all SPService objects about their support for service applications. The IServiceAdministration interface was introduced to allow SharePoint to ask registered services for their needs and capabilities. If you do not implement this interface all is not lost, but you do lose out on specific integration points. You can still create new instances using your own means though, such as a feature receiver.

The IServiceProxyAdministration interface

Similar to how the IServiceAdministration interface allows SharePoint to find out about your service application capabilities, SharePoint also provides IServiceProxyAdministration. As you can expect from the name it serves a similar purpose but not for the application itself but for the proxy. The interface provides a connection point for SharePoint to create instances of the proxy during automated tasks (psconfig principally). It also provides a way to fill the menu items shown in the 'Connect' menu.

However!…

The design for this first proxy-enabled demo is to call methods directly on the service application, in-process. Meaning, the 'Connect' capability is a bit odd since you'll connect to an in-memory construct instead of a WCF backend that might be in another farm and is identified by a URI. In effect you are not connecting at all, or at least not in the way it was intended by the Connect functionality. So, we'll not implement this interface just yet and leave that one for a later version.

Building the application

In this section I'll show some of the code that make up the new application. The focus is on what is new in this version of the demo application. If you are interested in the basics check out an earlier blog post.

The NavigationServiceProxy

In the second version of the demo application that you can download from CodePlex you'll find the NavigationServiceProxy. This class is the service proxy. A not so interesting class right now, but it'll grow on you after I have had time to write my next blog post. It's basically an empty persisted object. In most persisted objects you find at least two constructors. The first is parameterized and used for initializing a new instance and adding it to the configuration store, the second is used for deserializing the object when it is retrieved later on. A persisted object is identified by both a name and an ID. The ID defaults to the value found in the Guid attribute. Since there is only going to be exactly one instance for this proxy class the name is defaulted to String.Empty.

[Guid("0bc4db91-dac2-4ad6-90cf-394997131d54")]
public class NavigationServiceProxy
    : SPServiceProxy
{
    public NavigationServiceProxy()
    {
    }

    public NavigationServiceProxy(SPFarm farm)
        : base(String.Empty, farm)
    {
    }
}

The NavigationApplicationProxy

Similar to the service proxy the application proxy is a persisted object stored within the configuration database. Since you can create more than one proxy the constructor takes in a name. The constructor also requires you to specify the NavigationApplication for which the proxy is created. The last parameter is a reference to the singleton NavigationServiceProxy that will serve as the parent object of the application proxy (it is passed to the base constructor).

[GuidAttribute("0c1a4b04-90d5-4cef-be3a-f4591b1ac873")]
public class NavigationApplicationProxy
    : SPServiceApplicationProxy
{
    [Persisted]
    Guid _serviceApplicationID;

    public NavigationApplicationProxy() { }

    public NavigationApplicationProxy(string name,
        NavigationApplication application,
        NavigationServiceProxy serviceProxy)
        : base(name, serviceProxy)
    {
        _serviceApplicationID = application.Id;
    }

    NavigationApplication GetNavigationApplication()
    {
        return (NavigationApplication)Farm.GetObject(
          _serviceApplicationID);
    }
}

The class is completed with two static methods. The first is a factory method used for creating a new application proxy instance. The second is used for retrieving existing proxies. One added treat is that you can specify whether the newly created application proxy should be added to the default proxy group. Only a few lines of code are needed to implement this behavior.

public static NavigationApplicationProxy Create(
    string name, 
    NavigationApplication application,
    NavigationServiceProxy applicationProxy, 
    bool addToDefaultGroup)
{
    NavigationApplicationProxy proxy = 
        new NavigationApplicationProxy(
            name, application, applicationProxy);
    proxy.Update();
    if (addToDefaultGroup)
    {
        SPServiceApplicationProxyGroup group = 
            SPServiceApplicationProxyGroup.Default;
        group.Add(proxy);
        group.Update();
    }
    return proxy;
}

public
 static NavigationApplicationProxy GetProxy(
    SPServiceContext context)
{
    return (NavigationApplicationProxy)context.GetDefaultProxy(
        typeof(NavigationApplicationProxy));
}

The class further contains a method which implement the business side of the system (it is specific to the navigation application demo). First, the application is retrieved using the persisted application ID. Next, a method is called directly on the application.

public string GetNavigationInformation()
{
    NavigationApplication application = GetNavigationApplication();
    return application.GetNavigationInformation();
}

This is the bulk of the functionality provided by the second demo application. Next there is also the IServiceProxyAdministration interface to allow some administration on the demo service.

The IServiceProxyAdministration implementation

This interface is used for two purposes. It is called by SharePoint to create new applications and proxies as part of the farm configuration. The interface is also queried for the items to show in the New menu. Since the implementation of these methods is so simple I'll omit the specifics. Download the demo application to see what tasks it performs (it just calls the existing Create method or returns some simple information).

public interface IServiceAdministration
{
    SPServiceApplication CreateApplication(string name, 
        Type serviceApplicationType, 
        SPServiceProvisioningContext provisioningContext);

    SPServiceApplicationProxy CreateProxy(string name, 
        SPServiceApplication serviceApplication, 
        SPServiceProvisioningContext provisioningContext);

    Type[] GetApplicationTypes();

    SPPersistedTypeDescription GetApplicationTypeDescription(
        Type serviceApplicationType);

    SPAdministrationLink GetCreateApplicationLink(
        Type serviceApplicationType);

    SPCreateApplicationOptions GetCreateApplicationOptions(
        Type serviceApplicationType);
}

The New Application Page

Version two of the navigation application does contain one added item of interest. The ASP.NET page used to create new service applications. You know. It's the page where you'll allow administrators to enter a name, perhaps choose an application pool or two and a database here or there. The following specifics are interesting when implementing your own New Application page.

First of all the page directive hardwires the page to use the dialog master.

<%@ Page Language="C#" Inherits="..." MasterPageFile="~/_layouts/dialog.master" %>

Next, in the OnInit for the page, the dialog master is retrieved and the OK button is hooked up to a delegate.

 

protected override void OnInit(EventArgs e)
{
    ((DialogMaster)this.Page.Master).OkButton.Click += OkButton_Click;
    base.OnInit(e);
}

In the method that is bound using the delegate, the following takes place. First you use the SPLongOperation (a little gem IMHO). To finish the long operation don't redirect but instead send some script to close the dialog and that's it!

void OkButton_Click(object sender, EventArgs e)
{
    using (SPLongOperation operation = new SPLongOperation(this))
    {
        operation.LeadingHTML = "Creating new Navigation Application";
        operation.Begin();
        try
        {
            ...
        }
        finally
        {
            operation.EndScript("window.frameElement.commitPopup();");
        }
    }
}

The logic contained within the try / finally block first creates and provisions a service application, and next it creates a proxy too, adding it to the default proxy group. The idea of also creating a proxy is that we are not offering any user interface that allows administrators to create new proxies. The reason for not providing this is that the demo proxy calls methods directly on the application without needing an extra level of interaction configured using a URI. So, if an administrator is not going to create a proxy, we'd better do it for him!

NavigationService service = SPFarm.Local.Services.GetValue<NavigationService>();
string title = nameField.Text;
NavigationApplication application = NavigationApplication.Create(title, service);
application.Provision();
SPFarm farm = application.Farm;
NavigationServiceProxy serviceProxy = (NavigationServiceProxy)farm.GetObject(
    String.Empty, farm.Id, typeof(NavigationServiceProxy));
NavigationApplicationProxy proxy = NavigationApplicationProxy.Create(title, application, serviceProxy, true);
proxy.Provision();

 

That's it for today. Hopefully I'll have the time to write up the next part. I'll cover how to move your service proxy to the next step by adding WCF. Hope it helps!




























 

Service Applications 102 – Ten lines and one F5

This is the second part of a series on Service Applications. The following has already been posted:

Find the code for this sample on my CodePlex demo portal under the Navigation Service Basic release.

Building a service application

So, let's get started. As expressed in my previous post the demo application is focused on cross-site collection navigation. By will of keyboard there will be summoned a service application called the Global Navigation Service, and each joined web application will be able to use a SiteMapProvider that provides truly global navigation. Of course we'll not begin with WCF proxies or load balancing, not even PowerShell. Let's get cracking with a basic Service Application and build it out over time.

This first sample will have a service and a service application. Since we're in the 'no proxy' mode you provision both the service and the service application using a feature receiver. Next the project contains a simple Web Part to test calling the Service Application.

I'll walk through the code with you from the leaf level to the root, meaning starting with the NavigationApplication, next the NavigationService and finally the event receiver that provisions all of this.

Implementing the NavigationApplication

Although you'll likely code up the NavigationService first since it passes itself into the NavigationApplication, I'll explain how to build the application code first. Have to start somewhere, and there is a two-way dependency between service and application, meaning no good start point anyway.

To create a service application you derive a class of SPServiceApplication, add a GuidAttribute and finally you add at least two constructors, one empty and the other one to form the hierarchy of persisted objects (configuration database objects).

[Guid("f46c5a6a-0f73-4c1e-b11b-c2ffb70c19f9")]
public class NavigationApplication
    : SPServiceApplication
{
    public NavigationApplication()
    {
    }

    public NavigationApplication(NavigationService service)
        : base(String.Empty, service)
    {
    }
}
That's it. You're done with building the world's most useless application. It only gets to be, not to actually do anything J Just a few more steps to add in some extra functionality. You can override the TypeName property to determine what text to display in the Manage Service Applications page and you should add methods that express the functionality that you are building in your service application. You'll end up with something similar to the following class definition.

[Guid("f46c5a6a-0f73-4c1e-b11b-c2ffb70c19f9")]
public class NavigationApplication : SPServiceApplication
{
    public override string TypeName
    {
        get { return "Navigation Application (Demo)"; }
    }

    public NavigationApplication()
    {
    }

    public NavigationApplication(NavigationService service)
        : base(String.Empty, service)
    {
    }

    internal static NavigationApplication Create(NavigationService service)
    {
        return new NavigationApplication(service);
    }

    public string GetNavigation()
    {
        return "Demo";
    }
}
That's on the Service Application side. Next up is the farm wide service that manages this application.

Implementing the NavigationService

The service application will be managed by the farm-wide service class dubbed NavigationService. During provisioning the NavigationService will create the NavigationApplication. It isn't doing anything else but this. The 'singleton' application is exposed as a property so that code can call the application via the service.

[Guid("50c2366b-24a5-4b9a-ad47-e6d6177c630c")]
public class NavigationService : SPService
{
    public NavigationApplication Application
    {
        get { return Applications.Cast<NavigationApplication>().First(); }
    }

    public NavigationService()
    {
    }

    public NavigationService(SPFarm farm)
        : base(String.Empty, farm)
    {
    }

    public override void Provision()
    {
        base.Provision();
        NavigationApplication application = 
            GetChild<NavigationApplication>(String.Empty);
        if (application == null)
        {
            application = NavigationApplication.Create(this);
            application.Update();
            application.Provision();
        }
    }
}
Provisioning the service

To get the service application going you need to instantiate the service one time within the farm. One vehicle to achieve this is a feature receiver bound to a farm-level feature. There are some things to consider namely that the Manage Service Applications page also has a delete button to remove applications. Since the feature receiver is only called once you cannot use this approach to recreate your Service Application.

public override void FeatureActivated(
    SPFeatureReceiverProperties properties)
{
    SPWebService adminService = 
        (SPWebService)properties.Feature.Parent;
    SPFarm farm = adminService.Farm;
    NavigationService service = 
        farm.Services.GetValue<NavigationService>();
    if (service == null)
    {
        service = new NavigationService(farm);
        service.Update();
        service.Provision();
    }
}
Now that you have both a running service which houses a Service Application it is time to test this application using a Web Part.

Calling the Service Application

The last step is also the easiest. You of course need a consumer for the service application, and a Web Part is one easy vehicle to use. To call the Service Application you first retrieve the service. Via the service you can grab the service application and call methods on it.

public class NavigationWebPart : WebPart
{
    protected override void Render(HtmlTextWriter writer)
    {
        NavigationService service = SPFarm.Local.GetChild<NavigationService>();
        writer.WriteEncodedText(service.Application.GetNavigation());
    }
}
That's it for today. This concludes the demo on building a very simple service application. You can now start tacking on extra stuff. Check out the SPServiceApplication base class to see what is available.

 

Hope it helps!

Service Applications 101 – The Road to Rome

This is the first part of a series on Service Applications. The following has already been posted:

Find the code for this sample on my CodePlex demo portal under the Navigation Service Basic release.

About Service Applications

One of the new features of SharePoint that I am super excited about is the new model for providing functionality that crosses the site collection boundary. Although technically you could already do this in SharePoint 2007 by creating a hierarchy of SPPersistedObject instances that you bind against either the farm or a web application, you now get a better programming model, easier integration with enterprise features such as backup / restore and claims security as well as one common UI platform for administrators to, eh, administrate your application. Awesome!

While there are many things that you can do with a Service Application, such as offloading load balanced calls to backend application servers through WCF you don't actually need to do this. There is a huge amount of flexibility in the framework meaning that quite quickly a Service Application becomes an interesting component to add to your solution. The key question to ask is obvious. When would you create a Service Application?

When to create a Service Application

As with all big questions there are many answers. Also the opposite is interesting, when not to do so. If you examine the built-in services there is one obvious, perhaps overlooked, common notion. They share data across site collection (across web applications typically). So one big motivator that I recognize for building service applications is exactly this need. Many of the medium / large sized document management solutions have this need to share data. I will not say that it is as easy as need shared data à thus application, RSS for one is also a great roll-up candidate. But especially this need is what I have time and time again implemented in one way, shape or form. A Service Application is a great way to express application level functionality that encompasses multiple site collections.

Components of a Service Application

Before discussing the types of Service Applications you can create, let's first focus a bit on the components that you have available. The global picture is not so big. The hierarchy of interesting objects is part of the configuration database and expressed as a series of SPPersistedObject objects. The hierarchy root being the SPFarm.

The SPService class represents a farm-wide service. It contains a collection of SPServiceInstance objects each of which can be seen as a component for that farm-wide service bound to a particular server in your farm. You for instance have the farm-wide database service which contains a SPServiceInstance for each actual server in your farm. What is new is that the SPService now has a collection of SPServiceApplication objects. Like the SPServiceInstance representing the service for a particular SPServer, the SPServiceApplication represents the service for a series of Web Applications. Each SPServiceApplication can contain specific resources to facilitate that goal. You might provision a database for each SPServiceApplication, meaning each instance of a Service Application has its own database. You might also, eh, not do this. It's all up to you. Many built-in services take this approach though. When you create and configure a new instance of a service application the administrator gets presented with a nice interface to create new databases with.

A large part of the scalability capabilities of the Service Application framework is the ability to offload data to backend application servers. SharePoint provides for this through integration with WCF as the communication platform. Typically your SPServiceApplication class will be the WCF host and you will create the SPServiceApplicationProxy derived class to communicate with this host. You can now use the SPServiceApplication on a backend server, and use the SPServiceApplicationProxy to talk with it from a frontend webserver. You can also add in some load balancing to further increase scalability.

Since SharePoint needs to know about what proxies you support you create a SPServiceProxy class that knows about your Service Application proxies. Note the distinction between the SPServiceProxy and SPServiceApplicationProxy. Like the SPService you'll most likely create only one SPServiceProxy per farm. Service Applications and proxies are created as needed. As such the SPService acts as a conduit for discovering SPServiceApplications and the SPServiceProxy acts as a conduit to discover SPServiceApplicationProxy objects.

Types of Service Applications

Given the different needs when expressing application level functionality there is quite some flexibility in how you can build a service application. There are of course benefits and downsides to each approach.

  1. Just a Service Application
    This first type is the simplest case and the most inflexible. You only create a SPService and SPServiceApplication, no proxies at all. There is a big consideration however. Without having a proxy layer to your service application you'll not be able to associate web applications with your service (at least not easily, perhaps not at all). So, since you'll cannot bind a web application to the service application, you're left with having a single SPServiceApplication that services the entire farm (similar to the parent SPService). I am not sure if you should take this approach
  2. Direct proxy
    The second mode of operation you do create a proxy layer, and hence you're configurable through Central Administration. However, you don't use WCF as a communication conduit between your service application and the proxy, but the proxy calls methods directly on the service application. Meaning, no offloading to application servers,
  3. WCF proxy
    Perhaps the only 'real' service application, not sure on that yet. This time the proxy does use WCF framework to offload calls to backend servers. Also the hardest since you'll need to create more components and you'll need to understand WCF to a certain degree.

So, that concludes my first post on the new service Applications framework. In the next blog post I will introduce the simplest Service Application to facilitate a common SharePoint goal; cross-site collection navigation.

Hope it helps!

(2010)Adding Site Definition items to your main project

One of the many things you get to enjoy when moving towards SharePoint 2010 is the flexibility of the Visual Studio 2010 project system. You can develop custom extensions for just about everything you find in this great IDE, but you will not always have to do that. One sample is the Site Definition. In this blog post I will show how you can add site definitions to your main Visual Studio 2010 project. The reason I say 'main' is because the Site Definition is not a project item template that is available. You only get the Site Definition project:

When you add this project you will find that you now have a site definition project item added for you:

Cross-project packaging

Good stuff! But, what if you don't want to have a separate project? There is no Site Definition project item that you can add to an existing project. Does that mean you're stuck? Of course not!

First of all, you can use the cross-project packaging capability and add a second (normal) SharePoint project for the packaging. Just choose to include the correct files in the Packaging designer for your second project.

This is not the only thing you can do. If you like you can also opt for not having two projects but just one. A Site Definition is little more than a bunch of files deployed as TemplateFile. Any project item can do that!

Single project packaging

To achieve a similar result, create a normal SharePoint project. Add an 'Empty Element' project item. Add your onet.xml file to this project item and configure the onet.xml file to be deployed as a TemplateFile using the Properties window.

Next, remove the feature that is generated for you since you will not need a feature to deploy this content.

Done! Great isn't it?

In the end it is probably a good idea to imagine why there is no separate project item template for site definitions. Remember that once deployed a site definition should never be mutated anymore. A separate project and hence a separate solution facilitates this and makes it easier for people to 'do the right thing'. So, be warned!

Using Windows Libraries to your SharePoint advantage

One thing I personally used to do on SharePoint developer machines was to add a toolbar to the start menu. You right-click the start menu, expand Toolbars and choose New toolbar.

Next you direct Windows to the SharePoint installation folder:

And presto, instant pop-up SharePoint folders.

While this gives me some benefit when needing to locate a log file or feature, it is not really integrated in the rest of Windows. Say, the save dialogs. Those looking carefully will notice that in that dialog two images up there is proof that this dog learned a new trick. In later versions of Windows you can create a nice new library for all SharePoint folders. Just right-click any folder and choose Include in Library à New Library and create one named SharePoint. Put all the root folders that you find under the '12' or '14' and you'll be good to go.

Next add the commonly used subfolders Template\Layouts, Template\ControlTemplates and Template\Admin. Personally I added the '14' folder itself too. And while doing that, found the a bit under-used wpresources folder too so decided to add that in there as well.

Nice! These library thingies show up everywhere in Windows, meaning I can always quickly overwrite a SharePoint file….. Oh wait… J If only there were a feature to make the library read-only. One thing I do really like is the content view that allows me to quickly see files in all the folders from a single view. No more searching for ASPX pages in either ADMIN or LAYOUTS. Yay!

Have fun with libraries, and SharePoint obviously!

 

 

Deploying SharePoint administration pages

Most likely you will know that SharePoint supports two types of pages; site pages and application pages. There are quite a few differences between the two, especially in SharePoint 2007. A site page can be customized on a per-page basis, application pages are static. Site pages are branded, application pages typically are not since they use their own master page, just to name the two most eye catching gaps.

There is however, a less mentioned difference that has a big impact on how you package and deploy your SharePoint customization. Site pages are compiled against the Microsoft.SharePoint assembly and application pages have their base class LayoutsPageBase in the Microsoft.SharePoint.Administration assembly. And here-in lies the rub so to speak. While the Microsoft.SharePoint assembly is in the GAC, the administration assembly is not.

So, when you create some code that can be executed as a part of a scripted environment, be sure to separate out your code that is administration related and that which is content related. By putting your code in two separate assemblies, you can be sure that your content assemblies do not reference the Microsoft.SharePoint.Administration assembly. Since the SharePoint administration assembly is stored in the CONFIG\BIN folder, the .NET runtime cannot find it when for instance loading feature receivers or safe controls.

So, separate your administration from your content!

Hope it helps!

1 - 10 Next

 Projects

Databinding toolkit for Word 2007Use SHIFT+ENTER to open the menu (new window).
Open XML Activities for Windows Workflow FoundationUse SHIFT+ENTER to open the menu (new window).
Package ExplorerUse SHIFT+ENTER to open the menu (new window).
Windows SharePoint Services 3 Workflow DesignersUse SHIFT+ENTER to open the menu (new window).
Word 2007 Source ViewUse SHIFT+ENTER to open the menu (new window).