The CASI Kit Announcement from SharePoint Conference

Just wanted to update folks with the announcement made at the SharePoint Conference yesterday regarding the CASI Kit.  I have decided to release everything for it – full source code to the base class, the web part, and all of the sample projects – up to CodePlex.  If you go to casikit.codeplex.com now you can get everything that makes this toolkit.  In addition to that you will find:

  • A video that walks you through the process of building an application with the CASI Kit
  • The sample project that I built out at SharePoint Conference – both the starting project and completed project – along with written step by step instructions for building it yourself.  The CASI Kit is simple enough to use that the instructions for building the application fit on a single page!
  • All of the written guidance for using the CASI Kit

The reasons for doing this primarily came down to this:

  1. By having the source code available, if you have any issues or find bugs, etc., you have the source code – you can put it in the debugger, you can step through code, you can make changes as needed.  So you should have full comfort that you aren’t just relying on a black box unsupported component; now you can see everything that’s going on and how it’s doing it.
  2. As features in the SharePoint product change over time, having the source code allows you to modify it and change it to stay in step with those changes.  For example, if new ways are added to connect up SharePoint and other cloud services then you can modify the code to take advantage of those new platform features, or even transition off the CASI Kit in a prescriptive manner.  With the source code, you’re in control of adapting to those changes in the future.
  3. You now have the opportunity to build other solutions, whatever you want, using the CASI Kit as is or breaking it apart and using it as a really big building block to your own custom applications. 

Hopefully you will find this source code and kit useful for connecting to Windows Azure and other cloud-based services going forward.  Enjoy!

Advertisements

Adding Support for Multiple SharePoint 2010 Farms and the CASI Kit in Your WCF

Someone raised an interesting question the other day about the ability of a WCF application, that’s configured as described in Eric White’s blog (http://blogs.msdn.com/b/ericwhite/archive/2010/06/18/establishing-trust-between-a-wcf-web-service-and-the-sharepoint-2010-security-token-service.aspx) and the CASI Kit Part 2 (http://blogs.technet.com/b/speschka/archive/2010/11/06/the-claims-azure-and-sharepoint-integration-toolkit-part-2.aspx).  The configuration in these blogs describes modifying the web.config for the WCF so that it includes links to an issuer and issuerMetadata address, which is a SharePoint site Url, and the thumbprint for a SharePoint farm STS certificate.  So if have these values coded for a single farm, can a single WCF support requests from the CASI Kit in multiple farms?  Happily the answer is yes, but it does require one additional bit of configuration.

The basic elements that are configured in the WCF to build the trust between it and a SharePoint farm are:

  • The Url to a SharePoint site for issuer
  • The Url to a SharePoint site for issuerMetadata
  • The thumbprint of the farm’s token signing certificate used by the STS

The first two as it turns out are not a problem, because the CASI Kit base class programmatically overrides those values in the web.config, with the Url of the site from which the CASI Kit component is being invoked.  So that lets us remove those two items from the blocking list.  The last item is fortunately added to the web.config not as a single item, but really as one in an array of potential items.  Meaning it as added with a simple <add> tag, which means it supports adding multiple thumbprints that the WCF will support.  So here, for example, is what the web.config for my WCF looks like after I add support for two different farms to it:

<add thumbprint=”2e074b9965abc3434c20ed0be8bfe82b03e5c9f9″ name=”farm2″/>
<add thumbprint=”F53DE039BB2081E7DF6FEC03E8A644F3743A5A7C” name=”app1″/>

As you can see, you can just keep adding thumbprints to the list to support as many farms as you like, and the CASI Kit will take care of the rest for you.

CASI Kit Part 6 – Integrating SQL Azure with SharePoint 2010 and Windows Azure

This post is most useful when used as a companion to my five-part series on the CASI (Claims, Azure and SharePoint Integration) Kit. 

·         Part 1:  an introductory overview of the entire framework and solution and described what the series is going to try and cover.

·         Part 2:  the guidance part of the CASI Kit.  It starts with making WCF the front end for all your data – could be datasets, Xml, custom classes, or just straight up Html.  In phase 1 we take your standard WCF service and make it claims aware – that’s what allows us to take the user token from SharePoint and send it across application or data center boundaries to our custom WCF applications.  In phase 2 I’ll go through the list of all the things you need to do take this typical WCF application from on premises to hosted up in Windows Azure.  Once that is complete you’ll have the backend in place to support a multi-application, multi-datacenter with integrated authentication.

·         Part 3:  describes the custom toolkit assembly that provides the glue to connect your claims-aware WCF application in the cloud and your SharePoint farm.  I’ll go through how you use the assembly, talk about the pretty easy custom control you need to create (about 5 lines of code) and how you can host it in a page in the _layouts directory as a means to retrieve and render data in web part.  The full source code for the sample custom control and _layouts page will also be posted.

·         Part 4:  the web part that I’m including with the CASI Kit.  It provides an out of the box, no-code solution for you to hook up and connect with an asynchronous client-side query to retrieve data from your cloud-hosted service and then display it in the web part.  It also has hooks built into it so you can customize it quite a bit and use your own JavaScript functions to render the data.

·         Part 5:  a brief walk-through of a couple of sample applications that demonstrate some other scenarios for using the custom control you build that’s described in part 3 in a couple of other common scenarios.  One will be using the control to retrieve some kind of user or configuration data and storing it in the ASP.NET cache, then using it in a custom web part.  The other scenario will be using the custom control to retrieve data from Azure and use it a custom task; in this case, a custom SharePoint timer job.  The full source code for these sample applications will also be posted.

With the CASI Kit I gave you some guidance and tools to help you connect pretty easily and quickly to Windows Azure from SharePoint 2010, while sending along the token for the current user so you can make very granular security decisions.  The original WCF application that the CASI Kit consumed just used a hard-coded collection of data that it exposed.  In a subsequent build (and not really documented in the CASI Kit postings), I upgraded the data portion of it so that it stored and retrieved data using Windows Azure table storage.  Now, I’ve improved it quite a bit more by building out the data in SQL Azure and having my WCF in Windows Azure retrieve data from there.  This really is a multi-cloud application suite now:  Windows Azure, SQL Azure, and (ostensibly) SharePoint Online.  The point of this post is really just to share a few tips when working with SQL Azure so you can get it incorporated more quickly into your development projects.

Integration Tips

1.       You really must upgrade to SQL 2008 R2 in order to be able to open SQL Azure databases with the SQL Server Management Studio tool.  You can technically make SQL Server 2008 work, but there are a bunch of hacky work around steps to make that happen.  2008 R2 has it baked in the box and you will get the best experience there.  If you really want to go the 2008 work-around route, check out this link:  http://social.technet.microsoft.com/wiki/contents/articles/developing-and-deploying-with-sql-azure.aspx.  There are actually a few good tips in this article so it’s worth a read no matter what.

2.       Plan on using T-SQL to do everything.  The graphical tools are not available to work with SQL Azure databases, tables, stored procedures, etc.  Again, one thing I’ve found helpful since I’m not a real T-SQL wiz is to just create a local SQL Server database first.  In the SQL Management tool I create two connections – one to my local SQL instance and one to my SQL Azure instance. I create tables, stored procedures, etc. in the local SQL instance so I can use the graphical tools.  Then I use the Script [whatever Sql object] As…CREATE to…New Sql Query Window.  That generates the SQL script to create my objects, and then I can paste it into a query window that I have open to my SQL Azure database.

3.       This one’s important folks – the default timeout is frequently not long enough to connect to SQL Azure.  You can change it if using the .NET SqlClient classes in the connection string, i.e. add “Connection Timeout=30;”.  If you using SQL Server Management Studio then click the Advanced button on the dialog where you enter the server name and credentials and change it to at least 30.  The default is 15 seconds and fails often, but 30 seconds seems to work pretty well.  Unfortunately there isn’t a way to change the connection timeout for an external content type (i.e. BDC application definition) to a SQL Azure data source.

4.       Don’t use the database administrator account for connecting to your databases (i.e. the account you get to create the database itself).  Create a separate account for working with the data.  Unfortunately SQL Azure only supports SQL accounts so you can’t directly use the identity of the requesting user to make decisions about access to the data.  You can work around that by using a WCF application that front-ends the data in SQL Azure and using claims authentication in Windows Azure, which is exactly the model the CASI Kit uses.  Also, it takes a few steps to create a login that can be used to connect to data a specific database.  Here is an example:

–create the database first

CREATE DATABASE Customers

 

–now create the login, then create a user in the database from the login

CREATE LOGIN CustomerReader WITH PASSWORD = ‘FooBarFoo’

CREATE USER CustomerReader FROM LOGIN CustomerReader

 

–now grant rights to the user

GRANT INSERT, UPDATE, SELECT ON dbo.StoreInformation TO CustomerReader

 

–grant EXECUTE rights to a stored proc

GRANT EXECUTE ON myStoredProc TO CustomerReader

 

For more examples and details, including setting server level rights for accounts in SQL Azure, see http://msdn.microsoft.com/en-us/library/ee336235.aspx.

 

5.       You must create firewall rules in SQL Azure for each database you have in order to allow communications from different clients.  If you want to allow communication from other Azure services, then you must create the MicrosoftServices firewall rule (which SQL Azure offers to do for you when you first create the database), which is a start range of 0.0.0.0 to 0.0.0.0.  If you do not create this rule none of your Windows Azure applications will be able to read, add or edit data from your SQL Azure databases!  You should also create a firewall rule to allow communications with whatever server(s) you use to route to the Internet.  For example, if you have a cable or DSL router or an RRAS server, then you want to use your external address or NAT address for something like RRAS. 

 

Those should be some good tips to get your data up and running.

 

Data Access

Accessing the data itself from your custom code – Windows Azure WCF, web part, etc. – is fortunately pretty much exactly the same as when retrieving data from an on-premise SQL Server.  Here’s a quick code example, and then I’ll walk through a few parts of it in a little more detail:

//set a longer timeout because 15 seconds is often not

//enough; SQL Azure docs recommend 30

private string conStr = “server=tcp:foodaddy.database.windows.net;Database=Customers;” +

“user ID=CustomerReader;Password=FooBarFoo;Trusted_Connection=False;Encrypt=True;” +

“Connection Timeout=30”;

 

private string queryString = “select * from StoreInformation”;

private DataSet ds = new DataSet();

 

using (SqlConnection cn = new SqlConnection(conStr))

{

SqlDataAdapter da = new SqlDataAdapter();

da.SelectCommand = new SqlCommand(queryString, cn);

da.Fill(ds);

//do something with the data

}

 

Actually there’s not really here that needs much explanation, other than the connection string.  The main things worth pointing out on it that are possibly different from a typical connection to an on-premise SQL Server are:

·         server:  precede the name of the SQL Azure database with “tcp:”.

·         Trusted_Connection: this should be false since you’re not using integrated security

·         Encrypt:  this should be true for any connections to a cloud-hosted database

·         Connection Timeout:  as described above, the default timeout is 15 seconds and that will frequently not be enough; instead I set it to 30 seconds here.

One other scenario I wanted to mention briefly here is using data migration.  You can use the BCP tool that comes with SQL Server to move data from an on-premise SQL Server to SQL Azure.  The basic routine for migrating data is like this:

1.       Create a format file – this is used for both exporting the local data and importing it into the cloud.  In this example I’m creating a format file for the Region table in the Test database, and saving it to the file region.fmt.

 

bcp Test.dbo.Region format nul -T -n -f region.fmt

 

2.       Export data from local SQL – In this example I’m exporting out of the Region table in the Test database, into a file called RegionData.dat.  I’m using the region.fmt format file I created in step 1.

 

bcp Test.dbo.Region OUT RegionData.dat -T -f region.fmt

 

3.       Import data to SQL Azure.  The main thing that’s important to note here is that when you are importing data into the cloud, you MUST include the “@serverName” with the user name parameter; the import will fail without it.  In this example I’m importing data to the Region table in the Customers database in SQL Azure.  I’m importing from the RegionData.dat file that I exported my local data into.  My server name (the -S parameter) is the name of the SQL Azure database.  For my user name (-U parameter) I’m using the format username@servername as I described above.  I’m telling it to use the region.fmt format file that I created in step 1, and I’ve set a batch size (-b parameter) of 1000 records at a time.

 

bcp Customers.dbo.Region IN RegionData.dat -S foodaddy.database.windows.net -U speschka@foodaddy.database.windows.net -P FooBarFoo -f region.fmt -b 1000

 

That’s all for this post folks.  Hopefully this gives you a good understanding of the basic mechanics of creating a SQL Azure database and connecting to it and using it in your SharePoint site.  As a side note, I used the CASI Kit to retrieve this data through my Windows Azure WCF front end to SQL Azure and render it in my SharePoint site.  I followed my own CASI Kit blog when creating it to try and validate everything I’ve previously published in there and overall found it pretty much on the mark.  There were a couple of minor corrections I made in part 3 along with a quick additional section on troubleshooting that I added.  But overall it took me about 30 minutes to create a new custom control and maybe 15 minutes to create a new Visual web part.  I used the CASI Kit web part to display one set of SQL Azure data from the WCF, and in the Visual web part I created an instance of the custom control programmatically to retrieve a dataset, and then I bound it to an ASP.NET grid.  I brought it all together in one sample page that actually looks pretty good, and could be extended to displaying data in a number of different ways pretty easily.  Here’s what it looks like:

You can download the attachment here:

The Claims, Azure and SharePoint Integration Toolkit Part 5

This is part 5 of a 5 part series on the CASI (Claims, Azure and SharePoint Integration) Kit. 

·         Part 1:  an introductory overview of the entire framework and solution and described what the series is going to try and cover.

·         Part 2:  the guidance part of the CASI Kit.  It starts with making WCF the front end for all your data – could be datasets, Xml, custom classes, or just straight up Html.  In phase 1 we take your standard WCF service and make it claims aware – that’s what allows us to take the user token from SharePoint and send it across application or data center boundaries to our custom WCF applications.  In phase 2 I’ll go through the list of all the things you need to do take this typical WCF application from on premises to hosted up in Windows Azure.  Once that is complete you’ll have the backend in place to support a multi-application, multi-datacenter with integrated authentication.

·         Part 3:  describes the custom toolkit assembly that provides the glue to connect your claims-aware WCF application in the cloud and your SharePoint farm.  I’ll go through how you use the assembly, talk about the pretty easy custom control you need to create (about 5 lines of code) and how you can host it in a page in the _layouts directory as a means to retrieve and render data in web part.  The full source code for the sample custom control and _layouts page will also be posted.

·         Part 4:  the web part that I’m including with the CASI Kit.  It provides an out of the box, no-code solution for you to hook up and connect with an asynchronous client-side query to retrieve data from your cloud-hosted service and then display it in the web part.  It also has hooks built into it so you can customize it quite a bit and use your own JavaScript functions to render the data.

·         Part 5:  a brief walk-through of a couple of sample applications that demonstrate some other scenarios for using the custom control you build that’s described in part 3 in a couple of other common scenarios.  One will be using the control to retrieve some kind of user or configuration data and storing it in the ASP.NET cache, then using it in a custom web part.  The other scenario will be using the custom control to retrieve data from Azure and use it a custom task; in this case, a custom SharePoint timer job.  The full source code for these sample applications will also be posted.

In this final post I’ll walk through the two other core scenarios for this kit – using your custom control that you built in Part 3 to retrieve Azure data and store it in ASP.NET cache for use with other controls, and using it in a SharePoint task – in this case a custom SharePoint timer job.

Using the Control in Other Web Parts

One of the core scenarios that needed to be supported was to use the CASI Kit framework to retrieve data for use in other SharePoint web parts.  There remains though the other design goal, which was to NOT introduce routine server-side calls to potentially latent remote WCF endpoints.  To try and manage to those two divergent needs, the base class implements support for retrieving the data and storing it in ASP.NET cache directly.  That allows you to develop other custom web parts and follow a fairly simple pattern:

1.       Check to see if your data is in ASP.NET cache.

a.       If it is, retrieve it from there

b.      If it is not:

                                                              i.      Create an instance of the custom control

                                                            ii.      Set the OutputType to ServerCache, and the ServerCacheName and ServerCacheTime to appropriate values

                                                          iii.      Call the ExecuteRequest method and get the data

To begin with, start a new Visual Studio Project – in this case I’ll assume Visual Studio 2010 so we can create a new SharePoint 2010 project.  Get your project configured to create a new web part, and then you need to add two references – one to the CASI Kit base class and one to the custom control you wrote in Part 3.  Please note that if you don’t add a reference to the CASI Kit base class, then when you try and set any of the properties on the your control Visual Studio will underline it with the red squiggly and tell you it can’t find the property.  If you see that kind of error then you know that you haven’t added the reference to the CASI Kit base class yet.

Once you’re references are set you can write whatever code is appropriate for your web part.  When you get to the point where you need to pull in data from Azure – maybe it’s content, maybe it’s configuration information, etc. – here’s an example of how the pattern described above is implemented:

string CACHE_NAME = “AzureConfigConsumerCacheSample”;

int CACHE_TIME = 10;

 

//create a var of the type of configuration data we want to retrieve

AzureWcfPage.CustomersWCF.Customer[] Customers = null;

 

//look for our item in cache

if (HttpContext.Current.Cache[CACHE_NAME] != null)

{

//if we find, it cast it to our type and pull it out of cache

       Customers =

(AzureWcfPage.CustomersWCF.Customer[])

HttpContext.Current.Cache[CACHE_NAME];

}

else

{

//if it’s not in cache, then retrieve it and put it into cache

 

       //create an instance of the control

       AzureWcfPage.WcfDataControl cfgCtrl = new AzureWcfPage.WcfDataControl();

 

       //set the properties to retrieve data

       cfgCtrl.WcfUrl = https://azurewcf.vbtoys.com/Customers.svc&#8221;;

       cfgCtrl.OutputType = AzureConnect.WcfConfig.DataOutputType.ServerCache;

       cfgCtrl.ServerCacheName = CACHE_NAME;

       cfgCtrl.ServerCacheTime = CACHE_TIME;

       cfgCtrl.MethodName = “GetAllCustomers”;

 

       //execute the method

       bool success = cfgCtrl.ExecuteRequest();

 

       if (success)

       {

//get the strongly typed version of our data

//the data type needs to come from the control we are creating

Customers =

(AzureWcfPage.CustomersWCF.Customer[])cfgCtrl.QueryResultsObject;

 

              //if you wanted the Xml representation of the object you can get

              //it from QueryResultsString

              string stringCustomers = cfgCtrl.QueryResultsString;

}

       else

       {

              //there was some problem; plug in your error handling here

       }

}

 

Let’s take a look at some of the code in a little more detail.  First, it’s important to understand that in your new web part you DO NOT need to add a service reference to the WCF endpoint.  All of that is encapsulated in your custom control, so you can use the return types of your WCF application that are exposed via the custom control.  This line of code demonstrates that:

//create a var of the type of configuration data we want to retrieve

AzureWcfPage.CustomersWCF.Customer[] Customers = null;

In this example, AzureWcfPage was my custom control assembly.  CustomersWCF was the name I gave to my WCF service reference.  And Customer is the class type that my WCF method returned.  All of this flows into my new web part when I added my reference to the custom control assembly.

The first check I make is to see if my data is in cache; if it is then I just cast it to the array of Customer instances that I had stored there previously.  If it isn’t in cache then just write the seven lines of code necessary to create an instance of my custom control and retrieve the data.  You need to:

a.       Create a new instance of the control

b.      Set the WcfUrl, MethodName, OutputType, ServerCacheName and ServerCacheTime properties

c.       Call the ExecuteRequest method

That’s it.  If the method completes successfully then the return value from the WCF application is stored in ASP.NET cache so the next time this code executes, it will find the item in there.  Meanwhile, I can cast my local variable Customers to the QueryResultsObject property of the custom control, and then I can do whatever my web part needs with the data.  Overall this should be relatively straightforward and easy to implement for most web part developers.

Using the Control in a Task

Now I’ll describe how to use the custom control you developed in Part 3 to retrieve content and/or configuration data from Azure to be used in a task.  In this example, I wrote a custom SharePoint timer job and within it I am going to retrieve some data from Azure.  The pattern is fairly similar to the web part described above, but in this case, as with many tasks, you don’t have an HttpContext so the ASP.NET cache cannot be used.  In that case the OutputType is going to be None, because it doesn’t need to be rendered in a page and it doesn’t need to be stored in cache; instead we’ll just pull the value directory from QueryResultsObject and/or QueryResultsString.  Here’s a code sample for that – it’s code from the override of the Execute method in my custom timer job class:

SPWebApplication wa = (SPWebApplication)this.Parent;

 

//create an instance of the control

AzureWcfPage.WcfDataControl cfgCtrl = new AzureWcfPage.WcfDataControl();

 

//set the properties to retrieve data

cfgCtrl.WcfUrl = https://azurewcf.vbtoys.com/Customers.svc&#8221;;

cfgCtrl.OutputType = AzureConnect.WcfConfig.DataOutputType.None;

cfgCtrl.MethodName = “GetAllCustomers”;

 

//since there’s no Http context in a task like a timer job, you also need to

//provide the Url to a claims-enabled SharePoint site.  That address will be used

//to connect to the STS endpoint for the SharePoint farm

cfgCtrl.SharePointClaimsSiteUrl = wa.Sites[0].RootWeb.Url;

 

//execute the method

bool success = cfgCtrl.ExecuteRequest();

 

//check for success

if (success)

{

//now retrieve the data and do whatever with it

       AzureWcfPage.CustomersWCF.Customer[] Customers =

(AzureWcfPage.CustomersWCF.Customer[])cfgCtrl.QueryResultsObject;

 

       string AzureResults = cfgCtrl.QueryResultsString;

 

//this is where you would then do your tasks based on the data you got from Azure

foreach(AzureWcfPage.CustomersWCF.Customer c in Customers)

       {

Debug.WriteLine(c.Email);

       }

 

       Debug.WriteLine(AzureResults);

}

else

{

//do something to log the fact that data wasn’t retrieved

}

 

Here’s a little more explanation on this code.  The timer job is a web-application scoped job, so I begin by getting a reference to the SPWebApplication for which this job is being run by referring to the Parent property.  Next I create the custom control I made in Part 3 and set the minimal properties I need to retrieve the data from Azure.  In the next line of code I have to set the SharePointClaimsSiteUrl property.  As I explained in Part 3, when the CASI Kit base class runs through the ExecuteRequest method, it looks to see if it has an HttpContext available.  If it does it uses that context to figure out the current SharePoint site Url and makes the connection to the SharePoint STS through that site.  As I described above though, when you’re code is running in a task you typically will not have an HttpContext.  In that case the base class can’t determine what Url it should use to connect to the SharePoint STS, so in that case we need to give it the Url to a site in a claims-enabled web application.  The timer job code in this implementation assumes that it is ONLY going to be run on claims-enabled web applications, so that’s why I get the reference to the current web application and then just pass it the Url to the first site collection.  It doesn’t really matter which site collection is used, as long as it’s in a claims-enabled web application.

Once I’ve set the SharePointClaimsSiteUrl property then I can call the ExecuteRequest method as demonstrated previously.  If it executes successfully then I can pull my data off the control directly through the QueryResultsObject and/or QueryResultsString properties.

Both the web part and timer job projects are included in the zip file attached to this posting.

That’s A Wrap!

This is the final post in this series, and hopefully you have a good understanding now of the CASI Kit and how you can use it to connect pretty easily to data hosted in a WCF application on site or in the cloud, while being able to the user’s identity token across application and even data center boundaries.  In summary, the pattern is relatively easy to implement:

1.       Create a WCF front-end to your content and/or configuration data.  Claims-enable it and optionally move it into the cloud.  Optionally implement fine-grained permission decisions based on the calling user’s identity and claims.

2.       Write a custom control that inherits from the CASI Kit base class.  Override one method and write five lines of code.  Add the control to simple layouts page and deploy.

3.       Add the web part to a page, set one or more properties and start rendering your WCF data.  Optionally, use the control to retrieve content or configuration data in a custom web part or task like a custom timer job.

That’s pretty much it.  Hopefully the CASI Kit will take a lot of difficulty and mystery out of connecting your SharePoint farm to data stored anywhere around the world.  It will work equally well to retrieve configuration or personalization data, as well as content itself for display in your SharePoint sites.  And you now have the flexibility to use the security you implement in your organization across application and data center boundaries.  I had a great time envisioning, designing and developing this and I hope you find it to be useful.  As always, it is a v1 release and I’m sure there will be lots of things that we can do better, so feel free to add comments along these postings and I’ll periodically run through them as food for thought for the next big release.

You can download the attachment here:

The Claims, Azure and SharePoint Integration Toolkit Part 4

This is part 4 of a 5 part series on the CASI (Claims, Azure and SharePoint Integration) Kit. 

·         Part 1:  an introductory overview of the entire framework and solution and described what the series is going to try and cover.

·         Part 2:  the guidance part of the CASI Kit.  It starts with making WCF the front end for all your data – could be datasets, Xml, custom classes, or just straight up Html.  In phase 1 we take your standard WCF service and make it claims aware – that’s what allows us to take the user token from SharePoint and send it across application or data center boundaries to our custom WCF applications.  In phase 2 I’ll go through the list of all the things you need to do take this typical WCF application from on premises to hosted up in Windows Azure.  Once that is complete you’ll have the backend in place to support a multi-application, multi-datacenter with integrated authentication.

·         Part 3:  describes the custom toolkit assembly that provides the glue to connect your claims-aware WCF application in the cloud and your SharePoint farm.  I’ll go through how you use the assembly, talk about the pretty easy custom control you need to create (about 5 lines of code) and how you can host it in a page in the _layouts directory as a means to retrieve and render data in web part.  The full source code for the sample custom control and _layouts page will also be posted.

·         Part 4:  the web part that I’m including with the CASI Kit.  It provides an out of the box, no-code solution for you to hook up and connect with an asynchronous client-side query to retrieve data from your cloud-hosted service and then display it in the web part.  It also has hooks built into it so you can customize it quite a bit and use your own JavaScript functions to render the data.

·         Part 5:  a brief walk-through of a couple of sample applications that demonstrate some other scenarios for using the custom control you build that’s described in part 3 in a couple of other common scenarios.  One will be using the control to retrieve some kind of user or configuration data and storing it in the ASP.NET cache, then using it in a custom web part.  The other scenario will be using the custom control to retrieve data from Azure and use it a custom task; in this case, a custom SharePoint timer job.  The full source code for these sample applications will also be posted.

In this post I’ll cover the web part that is included as part of this framework.  It’s designed specifically to work with the custom control you created and added to the layouts page in Part 3.

Using the Web Part

Before you begin using the web part, it obviously is assumed that you a) have a working WCF service hosted in Windows Azure and b) that you have created a custom control and added it to the layouts page, as described in Part 3 of this series.  I’m further assuming that you have deployed both the CASI Kit base class assembly and your custom control assembly to the GAC on each server in the SharePoint farm.  I’m also assuming that your custom aspx page that hosts your custom control has been deployed to the layouts directory on every web front end server in the farm.  To describe how to use the web part, I’m going to use the AzureWcfPage sample project that I uploaded and attached to the Part 3 posting.  So now let’s walk through how you would tie these two things together to render data from Azure in a SharePoint site.

NOTE:  While not a requirement, it will typically be much easier to use the web part if the WCF methods being called return HTML so it can be displayed directly in the page without further processing.

The first step is to deploy the AzureRender.wsp solution to the farm; the wsp is included in the zip file attached to this posting.  It contains the feature that deploys the Azure DataView WebPart as well as jQuery 1.4.2 to the layouts directory.  Once the solution is deployed and feature activated for a site collection, you can add the web part to a page.  At this point you’re almost ready to begin rendering your data from Azure, but there is a minimum of one property you need to set.  So next let’s walk through what that and the other properties are for the web part.

Web Part Properties

All of the web part properties are in the Connection Properties section.  At a minimum, you need to set the Data Page property to the layouts page you created and deployed.  For example, /_layouts/AzureData.aspx.  If the server tag for your custom control has defined at least the WcfUrl and MethodName properties, then this is all you need to do.  If you did nothing else the web part would invoke the page and use the WCF endpoint and method configured in the page, and it would take whatever data the method returned (ostensibly it returns it in HTML format) and render it in the web part.  In most cases though you’ll want to use some of the other web part properties for maximum flexibility, so here’s a look at each one:

·         Method Name* – the name of the method on the WCF application that should be invoked.  If you need to invoke the layouts page with your own javascript function the query string parameter for this property is “methodname”.

·         Parameter List* – a semi-colon delimited list of parameters for the WCF method.  As noted in Parts 2 and 3 of this series, only basic data types are supported – string, int, bool, long, and datetime.  If you require a more complex data type then you should deserialize it first to a string then call the method, and serialize it back to a complex type in the WCF endpoint.  If you need to invoke the layouts page with your own javascript function the query string parameter for this property is “methodparams”.

·         Success Callback Address – the javascript function that is called back after the jQuery request for the layouts page completes successfully.  By default, this property uses the javascript function that ships with the web part.  If you use your own function, the function signature should look like this:  function yourFunctionName(resultData, resultCode, queryObject).  For more details see the jQuery AJAX documentation at http://api.jquery.com/jQuery.ajax/.

·         Error Callback Address – the javascript function that is called back if the jQuery request for the layouts page encounters an error.  By default, this property uses the javascript function that ships with the web part.  If you use your own function, the function signature should look like this:  function yourFunctionName(XMLHttpRequest, textStatus, errorThrown).  For more details see the jQuery AJAX documentation at http://api.jquery.com/jQuery.ajax/.

·         Standard Error Message – the message that will be displayed in the web part if an error is encountered during the server-side processing of the web part.  That means it does NOT include scenarios where data is actually being fetched from Azure.

·         Access Denied Message*this is the Access Denied error message that should be displayed if access is denied to the user for a particular method.  For example, as explained in Part 2 of this series, since we are passing the user’s token along to the WCF call, we can decorate any of the methods with a PrincipalPermission demand, like “this user must be part of the Sales Managers” group.  If a user does not meet a PrincipalPermission demand then the WCF call will fail with an access denied error.  In that case, the web part will display whatever the Access Denied Message is.  Note that you can use rich formatting in this message, to do things like set the font bold or red using HTML tags (i.e. <font color=’red’>You have no access; contact your admin</font>).  If you need to invoke the layouts page with your own javascript function the query string parameter for this property is “accessdenied”.

·         Timeout Message*this is the message that will be displayed if there is a timeout error trying to execute the WCF method call.  It also supports rich formatting such as setting the font bold, red, etc.  If you need to invoke the layouts page with your own javascript function the query string parameter for this property is “timeout”.

·         Show Refresh Link – check this box in order to render a refresh icon above the Azure data results.  If the icon is clicked it will re-execute the WCF method to get the latest data.

·         Refresh Style – allows you to add additional style attributes to the main Style attribute on the IMG tag that is used to show the refresh link.  For example, you could add “float:right;” using this property to have the refresh image align to the right.

·         Cache Results – check this box to have the jQuery library cache the results of the query.  That means each time the page loads it will use a cached version of the query results.  This will save round trips to Azure and result in quicker performance for end users.  If the data it is retrieving doesn’t change frequently then caching the results is a good option.

·         Decode Results* – check this box in case your WCF application returns results that are HtmlEncoded.  If you set this property to true then HtmlDecoding will be applied to the results.  In most cases this is not necessary.  If you need to invoke the layouts page with your own javascript function the query string parameter for this property is “encode”.

·         Show Debug Information – check this box to have the web part output debugging information along with the data to help troubleshoot issues.  Note that this will not do anything if the ReturnDiagnosticsInformation property of the user control is set to false.

* – these properties will be ignored if the custom control’s AllowQueryStringOverride property is set to false.

Typical Use Case

Assuming your WCF method returns HTML, in most cases you will want to add the web part to a page and set two or three properties:  Data Page, Method Name and possibly Parameter List. 

If you have more advanced display or processing requirements for the data that is returned by Azure then you may want to use a custom javascript function to do so.  In that case you should add your javascript to the page and set the Success Callback Address property to the name of your javascript function.  If your part requires additional posts back to the WCF application, for things such as adds, updates or deletes, then you should add that into your own javascript functions and call the custom layouts page with the appropriate Method Name and Parameter List values; the query string variable names to use are documented above.  When invoking the ajax method in jQuery to call the layouts page you should be able to use an approach similar to what the web part uses.  The calling convention it uses is based on the script function below; note that you will likely want to continue using the dataFilter property shown because it strips out all of the page output that is NOT from the WCF method:

$.ajax({

type: “GET”, 

       url: “/_layouts/SomePage.aspx”,

dataType: “text”,

data: “methodname=GetCustomerByEmail&methodparams=steve@contoso.local”,

dataFilter: AZUREWCF_azureFilterResults,

success: yourSuccessCallback,

error: yourErrorCallback

});

 

Try it Out!

You should have all of the pieces now to try out the end to end solution.  Attached to this posting you’ll find a zip file that includes the solution for the web part.  In the next and final posting in this series, I’ll describe how you can also use the custom control developed in Part 2 to retrieve data from Azure and use it in ASP.NET cache with other controls, and also how to use it in SharePoint tasks – in this case a custom SharePoint timer job.

 

UPDATED 3/6/2011:  Support was added for hosting multiple CASI Kit web parts on a single page.  Doing so required upgrading to jQuery 1.5.1.  You will need to retract and redeploy the web part if you want to take advantage of this new functionality; when you deploy it will automatically copy jQuery 1.5.1 to the _layouts directory.

 

You can download the attachment here:

The Claims, Azure and SharePoint Integration Toolkit Part 3

This is part 3 of a 5 part series on the CASI (Claims, Azure and SharePoint Integration) Kit. 

·         Part 1:  an introductory overview of the entire framework and solution and described what the series is going to try and cover.

·         Part 2:  the guidance part of the CASI Kit.  It starts with making WCF the front end for all your data – could be datasets, Xml, custom classes, or just straight up Html.  In phase 1 we take your standard WCF service and make it claims aware – that’s what allows us to take the user token from SharePoint and send it across application or data center boundaries to our custom WCF applications.  In phase 2 I’ll go through the list of all the things you need to do take this typical WCF application from on premises to hosted up in Windows Azure.  Once that is complete you’ll have the backend in place to support a multi-application, multi-datacenter with integrated authentication.

·         Part 3:  describes the custom toolkit assembly that provides the glue to connect your claims-aware WCF application in the cloud and your SharePoint farm.  I’ll go through how you use the assembly, talk about the pretty easy custom control you need to create (about 5 lines of code) and how you can host it in a page in the _layouts directory as a means to retrieve and render data in web part.  The full source code for the sample custom control and _layouts page will also be posted.

·         Part 4:  the web part that I’m including with the CASI Kit.  It provides an out of the box, no-code solution for you to hook up and connect with an asynchronous client-side query to retrieve data from your cloud-hosted service and then display it in the web part.  It also has hooks built into it so you can customize it quite a bit and use your own JavaScript functions to render the data.

·         Part 5:  a brief walk-through of a couple of sample applications that demonstrate some other scenarios for using the custom control you build that’s described in part 3 in a couple of other common scenarios.  One will be using the control to retrieve some kind of user or configuration data and storing it in the ASP.NET cache, then using it in a custom web part.  The other scenario will be using the custom control to retrieve data from Azure and use it a custom task; in this case, a custom SharePoint timer job.  The full source code for these sample applications will also be posted.

In this posting I’ll discuss one of the big deliverables of this framework, which is a custom control base class that you use to make your connection from SharePoint to your WCF application hosted in Windows Azure.  These are the items we’ll cover:

·         The base class – what is it, how do you use it in your project

·         A Layouts page – how to add your new control to a page in the _layouts directory

·         Important properties – a discussion of some of the important properties to know about in the base class

The CASI Kit Base Class

One of the main deliverables of the CASI Kit is the base class for a custom control that connects to your WCF application and submits requests with the current user’s logon token.  The base class itself is a standard ASP.NET server control, and the implementation of this development pattern requires you to build a new ASP.NET server control that inherits from this base class.  For reasons that are beyond the scope of this posting, your control will really need to do two things:

1.       Create a service reference to your WCF application hosted in Windows Azure.

2.       Override the ExecuteRequest method on the base class.  This is actually fairly simple because all you need to do is write about five lines of code where you create and configure the proxy that is going to connect to your WCF application, and then call the base class’ ExecuteRequest method.

To get started on this you can create a new project in Visual Studio and choose the Windows Class Library type project.  After getting your namespace and class name changed to whatever you want it to be, you will add a reference to the CASI Kit base class, which is in the AzureConnect.dll assembly.  You will also need to add references to the following assemblies:   Microsoft.SharePoint, System.ServiceModel, System.Runtime.Serialization and System.Web.

In your base class, add a using statement for Microsoft.SharePoint, then change your class so it inherits from AzureConnect.WcfConfig.  WcfConfig is the base class that contains all of the code and logic to connect to the WCF application, incorporate all of the properties to add flexibility to the implementation and eliminate the need for all of the typical web.config changes that are normally necessary to connect to a WCF service endpoint.  This is important to understand – you would typically need to add nearly a 100 lines of web.config changes for every WCF application to which you connect, to every web.config file on every server for every web application that used it.  The WcfConfig base class wraps that all up in the control itself so you can just inherit from the control and it does the rest for you.  All of those properties that would be changed in the web.config file though can also be changed in the WcfConfig control, because it exposes properties for all of them.  I’ll discuss this further in the section on important properties.

Because you’ll need to register this control in the Global Assembly Cache, you need to add a key that will be used to sign the assembly and give it a strong name.  As with any Visual Studio project, you can do so in the project Properties, by clicking on the Signing tab.

Now it’s time to add a new Service Reference to your WCF application hosted in Windows Azure.  There is nothing specific to the CASI Kit that needs to be done here – just right-click on References in your project and select Add Service Reference.  Plug in the Url to your Azure WCF application with the “?WSDL” at the end so it retrieves the WSDL for your service implementation.  Then change the name to whatever you want, add the reference and this part is complete.

At this point you have an empty class and a service reference to your WCF application.  Now comes the code writing part, which is fortunately pretty small.  You need to override the ExecuteRequest method, create and configure the service class proxy, then call the base class’ ExecuteRequest method.  To simplify, here is the complete code for the sample control I’m attaching to this post; I’ve highlighted in yellow the parts that you need to change to match your service reference:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Diagnostics;

using Microsoft.SharePoint;

 

//requires References to:

//1. AzureConnect

//2. Microsoft.SharePoint

//3. System.ServiceModel

//4. System.Runtime.Serialization

//5. System.Web

 

namespace AzureWcfPage

{

    public class WcfDataControl : AzureConnect.WcfConfig

    {

 

        //this method must be overridden so the proxy can be

 //configured and created correctly

        public override bool ExecuteRequest()

        {

            try

            {

                //create the proxy instance with bindings and endpoint the base class

                //configuration control has created for this

                CustomersWCF.CustomersClient cust =

                    new CustomersWCF.CustomersClient(this.FedBinding,

                     this.WcfEndpointAddress);

 

                //configure the channel so we can call it with

                //FederatedClientCredentials.

                SPChannelFactoryOperations.ConfigureCredentials<CustomersWCF.ICustomers>

                     (cust.ChannelFactory,

                     Microsoft.SharePoint.SPServiceAuthenticationMode.Claims);

 

                //create a channel to the WCF endpoint using the

  //token and claims of the current user

                CustomersWCF.ICustomers claimsWCF =

                    SPChannelFactoryOperations.CreateChannelActingAsLoggedOnUser

                    <CustomersWCF.ICustomers>(cust.ChannelFactory,

                     this.WcfEndpointAddress,

                    new Uri(this.WcfEndpointAddress.Uri.AbsoluteUri));

 

                //set the client property for the base class

                this.WcfClientProxy = claimsWCF;

            }

            catch (Exception ex)

            {

                Debug.WriteLine(ex.Message);

            }

               

            //now that the configuration is complete, call the method

            return base.ExecuteRequest();

        }

 

    }

}

 

So there you have it – basically five lines of code, and you really can just copy and paste directly the code in the override for ExcecuteRequest shown here into your own override. After doing so you just need to replace the parts highlighted in yellow with the appropriate class and interfaces your WCF application exposes.  In the highlighted code above:

·         CustomersWCF.CustomersClient:  “CustomersWCF” is the name I used when I created my service reference, and CustomersClient is the name of the class I’ve exposed through my WCF application.  The class name in my WCF is actually just “Customers” and the VS.NET add service reference tools adds the “Client” part at the end.

·         CustomersWCF.ICustomers:  The “CustomersWCF” is the same as described above.  “ICustomers” is the interface that I created in my WCF application, that my WCF “Customers” class actually implements.

That’s it – that’s all the code you need to write to provide that connection back to your WCF application hosted in Windows Azure.  Hopefully you’ll agree that’s pretty painless.  As a little background, the code you wrote is what allows the call to the WCF application to pass along the SharePoint user’s token.  This is explained in a little more detail in this other posting I did:  http://blogs.technet.com/b/speschka/archive/2010/09/08/calling-a-claims-aware-wcf-service-from-a-sharepoint-2010-claims-site.aspx. 

Now that the code is complete, you need to make sure you register both the base class and your new custom control in the Global Assembly Cache on each server where it will be used.  This can obviously be done pretty easily with a SharePoint solution.  With the control complete and registered it’s time to take a look at how you use it to retrieve and render data.  In the CASI Kit I tried to address three core scenarios for using Azure data:

1.       Rendering content in a SharePoint page, using a web part

2.       Retrieving configuration data for use by one to many controls and storing it in ASP.NET cache

3.       Retrieving data and using it in task type executables, such as a SharePoint timer job

The first scenario is likely to be the most pervasive, so that’s the one we’ll tackle first.  The easiest thing to do once this methodology was mapped out would have been to just create a custom web part that made all of these calls during a Load event or something like that, retrieve the data and render it out on the page.  This however, I think would be a HUGE mistake.  By wrapping that code up in the web part itself, so it executes server-side during the processing of a page request, could severely bog down the overall throughput of the farm.  I had serious concerns about having one to many web parts on a page that were making one to many latent calls across applications and data centers to retrieve data, and could very easily envision a scenario where broad use could literally bring an entire farm down to its knees.  However, there is this requirement that some code has to run on the server, because it is needed to configure the channel to the WCF application to send the user token along with the request.  My solution for came to consist of two parts:

1.       A custom page hosted in the _layouts folder.  It will contain the custom control that we just wrote above and will actually render the data that’s returned from the WCF call.

2.       A custom web part that executes NO CODE on the server side, but instead uses JavaScript and jQuery to invoke the page in the _layouts folder.  It reads the data that was returned from the page and then hands it off to a JavaScript function that, by default, will just render the content in the web part.  There’s a lot more to it that’s possible in the web part of course, but I’ll cover the web part in detail in the next posting.  The net though is that when a user requests the page it is processed without having to make any additional latent calls to the WCF application.  Instead the page goes through the processing pipeline and comes down right away to the user’s browser.  Then after the page is fully loaded the call is made to retrieve only the WCF content.

The Layouts Page

The layouts page that will host your custom control is actually very easy to write.  I did the whole thing in notepad in about five minutes.  Hopefully it will be even quicker for you because I’m just going to copy and paste my layouts page here and show you what you need to replace in your page. 

<%@ Page Language=”C#” AutoEventWireup=”true” Inherits=”Microsoft.SharePoint.WebControls.LayoutsPageBase,Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” MasterPageFile=”~/_layouts/simple.master” %>

 

<%@ Assembly Name=”Microsoft.SharePoint.ApplicationPages, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c”%>

<%@ Import Namespace=”Microsoft.SharePoint.ApplicationPages” %>

<%@ Register Tagprefix=”SharePoint” Namespace=”Microsoft.SharePoint.WebControls” Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>

<%@ Register Tagprefix=”Utilities” Namespace=”Microsoft.SharePoint.Utilities” Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>

<%@ Import Namespace=”Microsoft.SharePoint” %>

<%@ Assembly Name=”Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>

 

<%@ Assembly Name=”AzureConnect, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c0b51bd3d3b33212″%>

<%@ Register Tagprefix=”AzWcf” Namespace=”AzureWcfPage” Assembly=”AzureWcfPage, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ed63b2f4046026” %>

 

 

<asp:Content ID=”Content1″ ContentPlaceHolderId=”PlaceHolderPageTitle” runat=”server”>

    <SharePoint:EncodedLiteral ID=”wcfConnectPageTitle” runat=”server” text=”Azure Wcf Connect Page” EncodeMethod=’HtmlEncode’/>

</asp:Content>

<asp:Content ID=”Content2″ ContentPlaceHolderId=”PlaceHolderPageTitleInTitleArea” runat=”server”>

    <SharePoint:EncodedLiteral ID=”wcfConnectPage” runat=”server” text=”Azure Wcf Connect Page” EncodeMethod=’HtmlEncode’/>

</asp:Content>

<asp:Content ID=”Content3″ ContentPlaceHolderId=”PlaceHolderSiteName” runat=”server”/>

<asp:Content ID=”Content4″ ContentPlaceHolderId=”PlaceHolderMain” runat=”server”>

    <AzWcf:WcfDataControl runat=”server” id=”wcf” WcfUrl=”https://azurewcf.vbtoys.com/Customers.svc” OutputType=”Page” MethodName=”GetAllCustomersHtml” />

</asp:Content>

 

Again, the implementation of the page itself is really pretty easy.  All that absolutely has to be changed is the strong name of the assembly for your custom control.  For illustration purposes, I’ve also highlighted a couple of the properties in the control tag itself.  Note that the “WcfDataControl” part that is highlighted is the name of your class that you created.  These properties are specific to my WCF service, and can be change and in some cases removed entirely in your implementation.  The properties will be discussed in more detail below.  Once the layouts page is created it needs to be distributed to the _layouts directory on every web front end server in your SharePoint farm.  At that point it can be called from any site in any claims-aware web application in your SharePoint farm.  Obviously, you should not expect it to work in a classic authentication site, such as Central Admin.  Once the page has been deployed then it can be used by the CASI Kit web part, which will be described in part 4 of this series.

Important Properties

The WcfConfig contains two big categories of properties – those for configuring the channel and connection to the WCF application, and those that configure the use of the control itself.

WCF Properties

As described earlier, all of the configuration information for the WCF application that is normally contained in the web.config file has been encapsulated into the WcfConfig control.  However, virtually all of those properties are exposed so that they can be modified depending on the needs of your implementation.  Two important exceptions are the message security version, which is always MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10, and the transport, which is always HTTPS, not HTTP.  Otherwise the control has a number of properties that may be useful to know a little better in your implementation (although in the common case you don’t need to change them).

First, there are five read only properties to expose the top-level configuration objects used in the configuration.  By read-only, I mean the objects themselves are read-only, but you can set their individual properties if working with the control programmatically.  Those four properties are:

SecurityBindingElement SecurityBinding

BinaryMessageEncodingBindingElement BinaryMessage

HttpsTransportBindingElement SecureTransport

WS2007FederationHttpBinding FedBinding

EndpointAddress WcfEndpointAddress

The other properties can all be configured in the control tag that is added to the layouts aspx page.  For these properties I used a naming convention that I was hoping would make sense for compound property values.  For example, the SecurityBinding property has a property called LocalClient, which has a bool property called CacheCookies.  To make this as easy to understand and use as possible, I just made one property called SecurityBindingLocalClientCacheCookies.  You will see several properties like that, and this is also a clue for how to find the right property if you are looking at the .NET Framework SDK and wondering how you can modify some of those property values in the base class implementation.  Here is the complete list of properties:

SecurityAlgorithmSuite SecurityBindingDefaultAlgorithmSuite

SecurityHeaderLayout SecurityBindingSecurityHeaderLayout

SecurityKeyEntropyMode SecurityBindingKeyEntropyMode

bool SecurityBindingIncludeTimestamp

bool SecurityBindingLocalClientCacheCookies

bool SecurityBindingLocalClientDetectReplays

int SecurityBindingLocalClientReplayCacheSize

int SecurityBindingLocalClientMaxClockSkew

int SecurityBindingLocalClientMaxCookieCachingTime

int SecurityBindingLocalClientReplayWindow

int SecurityBindingLocalClientSessionKeyRenewalInterval

int SecurityBindingLocalClientSessionKeyRolloverInterval

bool SecurityBindingLocalClientReconnectTransportOnFailure

int SecurityBindingLocalClientTimestampValidityDuration

int SecurityBindingLocalClientCookieRenewalThresholdPercentage

bool SecurityBindingLocalServiceDetectReplays

int SecurityBindingLocalServiceIssuedCookieLifetime

int SecurityBindingLocalServiceMaxStatefulNegotiations

int SecurityBindingLocalServiceReplayCacheSize

int SecurityBindingLocalServiceMaxClockSkew

int SecurityBindingLocalServiceNegotiationTimeout

int SecurityBindingLocalServiceReplayWindow

int SecurityBindingLocalServiceInactivityTimeout

int SecurityBindingLocalServiceSessionKeyRenewalInterval

int SecurityBindingLocalServiceSessionKeyRolloverInterval

bool SecurityBindingLocalServiceReconnectTransportOnFailure

int SecurityBindingLocalServiceMaxPendingSessions

int SecurityBindingLocalServiceMaxCachedCookies

int SecurityBindingLocalServiceTimestampValidityDuration

int BinaryMessageMaxReadPoolSize

int BinaryMessageMaxWritePoolSize

int BinaryMessageMaxSessionSize

int BinaryMessageReaderQuotasMaxDepth

int BinaryMessageReaderQuotasMaxStringContentLength

int BinaryMessageReaderQuotasMaxArrayLength

int BinaryMessageReaderQuotasMaxBytesPerRead

int BinaryMessageReaderQuotasMaxNameTableCharCount

System.Net.AuthenticationSchemes SecureTransportAuthenticationScheme

System.ServiceModel.HostNameComparisonMode SecureTransportHostNameComparisonMode

System.Net.AuthenticationSchemes SecureTransportProxyAuthenticationScheme

System.ServiceModel.TransferMode SecureTransportTransferMode

bool SecureTransportManualAddressing

long SecureTransportMaxBufferPoolSize

long SecureTransportMaxReceivedMessageSize

bool SecureTransportAllowCookies

bool SecureTransportBypassProxyOnLocal

bool SecureTransportKeepAliveEnabled

int SecureTransportMaxBufferSize

string SecureTransportRealm

bool SecureTransportUnsafeConnectionNtlmAuthentication

bool SecureTransportUseDefaultWebProxy

bool SecureTransportRequireClientCertificate

HostNameComparisonMode FedBindingHostNameComparisonMode

WSMessageEncoding FedBindingMessageEncoding

Encoding FedBindingTextEncoding

SecurityAlgorithmSuite FedBindingSecurityMessageAlgorithmSuite

SecurityKeyType FedBindingSecurityMessageIssuedKeyType

bool FedBindingSecurityMessageNegotiateServiceCredential

int FedBindingCloseTimeout

int FedBindingOpenTimeout

int FedBindingReceiveTimeout

int FedBindingSendTimeout

bool FedBindingBypassProxyOnLocal

bool FedBindingTransactionFlow

long FedBindingMaxBufferPoolSize

long FedBindingMaxReceivedMessageSize

bool FedBindingUseDefaultWebProxy

int FedBindingReaderQuotasMaxDepth

int FedBindingReaderQuotasMaxStringContentLength

int FedBindingReaderQuotasMaxArrayLength

int FedBindingReaderQuotasMaxBytesPerRead

int FedBindingReaderQuotasMaxNameTableCharCount

bool FedBindingReliableSessionOrdered

int FedBindingReliableSessionInactivityTimeout

bool FedBindingReliableSessionEnabled

Again, these were all created so that they could be modified directly in the control tag in the layouts aspx page.  For example, here’s how you would set the FedBindingUseDefaultWebProxy property:

<AzWcf:WcfDataControl runat=”server” id=”wcf” WcfUrl=”https://azurewcf.vbtoys.com/Customers.svc” OutputType=”Page” MethodName=”GetAllCustomersHtml” FedBindingUseDefaultWebProxy=”true” />

 

Usage Properties

The other properties on the control are designed to control how it’s used.  While there is a somewhat lengthy list of properties, note that they are mainly for flexibility of use – in the simple case you will only need to set one or two properties, or alternatively just set them in the web part that will be described in part four of this series.  Here’s a list of each property and a short description of each.

string WcfUrl – this is the Url to the WCF service endpoint, i.e. https://azurewcf.vbtoys.com/Customers.svc.

 

string MethodName – this is the name of the method that should be invoked when the page is requested.  You can set this to what method will be invoked by default.  In addition, you can also set the AllowQueryStringOverride property to false, which will restrict the page to ONLY using the MethodName you define in the control tag.  This property can be set via query string using the CASI Kit web part.

 

string MethodParams – this is a semi-colon delimited list of parameter values that should be passed to the method call.  They need to be in the same order as they appear in the method signature.  As explained in part 2 of this blog series, parameter values really only support simple data types, such as string, bool, int and datetime.  If you wish to pass more complex objects as method parameters then you need to make the parameter a string, and deserialize your object to Xml before calling the method, and then in your WCF application you can serialize the string back into an object instance.  If passing that as a query string parameter though you will be limited by the maximum query string length that your browser and IIS supports.  This property can be set via query string using the CASI Kit web part.

 

object WcfClientProxy – the WcfClientProxy is what’s used to actually make the call to the WCF Application.  It needs to be configured to support passing the user token along with the call, so that’s why the last of configuration code you write in your custom control in the ExecuteRequest override is to set this proxy object equal to the service application proxy you created and configured to use the current client credentials.

 

string QueryResultsString – this property contains a string representation of the results returned from the method call.  If your WCF method returns a simple data type like bool, int, string or datetime, then the value of this property will be the return value ToString().  If your WCF method returns a custom class that’s okay too – when the base class gets the return value it will deserialize it to a string so you have an Xml representation of the data.

 

object QueryResultsObject – this property contains an object representation of the results returned from the method call.  It is useful when you are using the control programmatically.  For example, if you are using the control to retrieve data to store in ASP.NET cache, or to use in a SharePoint timer job, the QueryResultsObject property has exactly what the WCF method call returned.  If it’s a custom class, then you can just cast the results of this property to the appropriate class type to use it.

 

DataOutputType OutputType – the OutputType property is an enum that can be one of four values:  Page, ServerCache, Both or None.  If you are using the control in the layouts page and you are going to render the results with the web part, then the OutputType should be Page or Both.  If you want to retrieve the data and have it stored in ASP.NET cache then you should use ServerCache or Both.  NOTE:  When storing results in cache, ONLY the QueryResultsObject is stored.  Obviously, Both will both render the data and store it in ASP.NET cache.  If you are just using the control programmatically in something like a SharePoint timer job then you can set this property to None, because you will just read the QueryResultsString or QueryResultsObject after calling the ExecuteRequest method.  This property can be set via query string using the CASI Kit web part.

 

string ServerCacheName – if you chose an OutputType of ServerCache or Both, then you need to set the ServerCacheName property to a non-empty string value or an exception will be thrown.  This is the key that will be used to store the results in ASP.NET cache.  For example, if you set the ServerCacheName property to be “MyFooProperty”, then after calling the ExecuteRequest method you can retrieve the object that was returned from the WCF application by referring to HttpContext.Current.Cache[“MyFooProperty”].  This property can be set via query string using the CASI Kit web part.

 

int ServerCacheTime – this is the time, in minutes, that an item added to the ASP.NET cache should be kept.  If you set the OutputType property to either ServerCache or Both then you must also set this property to a non-zero value or an exception will be thrown.  This property can be set via query string using the CASI Kit web part.

 

bool DecodeResults – this property is provided in case your WCF application returns results that are HtmlEncoded.  If you set this property to true then HtmlDecoding will be applied to the results.  In most cases this is not necessary.  This property can be set via query string using the CASI Kit web part.

 

string SharePointClaimsSiteUrl – this property is primarily provided for scenarios where you are creating the control programmatically outside of an Http request, such as in a SharePoint timer job.  By default, when a request is made via the web part, the base class will use the Url of the current site to connect to the SharePoint STS endpoint to provide the user token to the WCF call.  However, if you have created the control programmatically and don’t have an Http context, you can set this property to the Url of a claims-secured SharePoint site and that site will be used to access the SharePoint STS.  So, for example, you should never need to set this property in the control tag on the layouts page because you will always have an Http context when invoking that page.

 

bool AllowQueryStringOverride – this property allows administrators to effectively lock down a control tag in the layouts page.  If AllowQueryStringOverride is set to false then any query string override values that are passed in from the CASI Kit web part will be ignored.

 

string AccessDeniedMessage – this is the Access Denied error message that should be displayed in the CASI Kit web part if access is denied to the user for a particular method.  For example, as explained in part 2 of this series, since we are passing the user’s token along to the WCF call, we can decorate any of the methods with a PrincipalPermission demand, like “this user must be part of the Sales Managers” group.  If a user does not meet a PrincipalPermission demand then the WCF call will fail with an access denied error.  In that case, the web part will display whatever the AccessDeniedMessage is.  Note that you can use rich formatting in this message, to do things like set the font bold or red using HTML tags (i.e. <font color=’red’>You have no access; contact your admin</font>).  This property can be set via query string using the CASI Kit web part.

 

string TimeoutMessage – this is the message that will be displayed in the CASI Kit web part if there is a timeout error trying to execute the WCF method call.  It also supports rich formatting such as setting the font bold, red, etc.  This property can be set via query string using the CASI Kit web part.

 

The following set of properties were added to help you do debugging from the web part itself:

 

bool ReturnDiagnosticsInformation – this property controls whether diagnostic information will be sent back to caller.  Since it could contain information that might be considered sensitive – such as the name of the server on which the request executed – you can set this to false to prevent the information from flowing back to the web part.

 

string ExecutionServerName – this is the name of the server on which the request was executed.  If you have issues with the request then you can use this information to know on which server you may want to examine the ULS logs.

 

string ExecutionErrorMessage – this contains any error messages that occurred during the execution of the WCF method call.

 

string TraceInfoMessage – this includes tracing information about the request that was made.  For example, it includes the method name, method parameters, the WCF Url that was used, etc.

Troubleshooting Tips

Troubleshooting can sometimes be difficult to do in  widely distributed system like this.  Here are some tips to help you get started:

  • Navigate to the custom _layouts page directly.  It’s often easier to see what data is being returned, or what error messages you are encountering if you just navigate to the custom page.
  • Enable the Show Debugging Information property on the CASI Kit web part.  It will tell you what all the parameter values were that it used in making the request, how long the request took, any error messages, etc.
  • If you see an error message like “secure fault”, make sure you have added the correct thumbprint for the SharePoint STS token signing certificate to the web.config for your WCF application, and also that you have added the SSL certificate and any root certificates above it to the trusted root authorities in SharePoint.

 

Okay, this was one LONG post, but it will probably be the longest of the series because it’s where the most significant glue of the CASI Kit is.  In the next posting I’ll describe the web part that’s included with the CASI Kit to render the data from your WCF application, using the custom control and layouts page you developed in this step.

Also, attached to this post you will find a zip file that contains the sample Visual Studio 2010 project that I created that includes the CASI Kit base class assembly, my custom control that inherits from the CASI Kit base class, as well as my custom layouts page.

 

UPDATE 2/4/2011:  I added a solution called AzureConnectRegister.wsp to the zip file attached to this post.  I highly recommend you use it to distribute the CASI Kit base class because it has a feature receiver that registers a custom ULS logging area.  Without it, the logging used in the base class will not be able to execute successfully, so you will lose all logging.  I also included the source code for the feature so you can see what code it is using to register the custom ULS logging area.

UPDATE 2/24/2011:  I added all of the additional debugging properties described above.

UPDATE 3/6/2011:  There was a problem with the connection to the WCF not being properly closed.  This could result in periodic timeout issues when the CASI Kit web part requested data from the WCF.  That problem has been fixed.  Also, the default SendTimeout and ReceiveTimeout properties are now set to 30 seconds, so if there were any issues they will appear more quickly than previously.

UPDATE 6/25/2011: Fixed a problem with some method parameter types not being cast correctly; this would result in an error stating that the method could not be found.  The standard types described above are supported for method parameters:  string, int, long, bool, and DateTime.  Custom types should be deserialized to a string and rehydrated server-side. 

UPDATE 7/12/2011:  No code updates here, but just a gentle reminder.  If you add the web part to a page and check the Show Debug Info checkbox, and then it fails to retrieve the data and says that it failed to establish a trust, there are two possible causes.  One, you didn’t properly configure the trust in the web.config file for the WCF application.  I describe how to do this in part 2 of this series at http://blogs.technet.com/b/speschka/archive/2010/11/06/the-claims-azure-and-sharepoint-integration-toolkit-part-2.aspx.  Two, you didn’t add the SSL certificate or one of it’s parent certificates to the list of trusted root authorities in your SharePoint farm.  I describe how to do this at http://blogs.technet.com/b/speschka/archive/2010/02/13/root-of-certificate-chain-not-trusted-error-with-claims-authentication.aspx.

You can download the attachment here:

The Claims, Azure and SharePoint Integration Toolkit Part 2

This is part 2 of a 5 part series on the CASI (Claims, Azure and SharePoint Integration) Kit. 

·         Part 1:  an introductory overview of the entire framework and solution and described what the series is going to try and cover.

·         Part 2:  the guidance part of the CASI Kit.  It starts with making WCF the front end for all your data – could be datasets, Xml, custom classes, or just straight up Html.  In phase 1 we take your standard WCF service and make it claims aware – that’s what allows us to take the user token from SharePoint and send it across application or data center boundaries to our custom WCF applications.  In phase 2 I’ll go through the list of all the things you need to do take this typical WCF application from on premises to hosted up in Windows Azure.  Once that is complete you’ll have the backend in place to support a multi-application, multi-datacenter with integrated authentication.

·         Part 3:  describes the custom toolkit assembly that provides the glue to connect your claims-aware WCF application in the cloud and your SharePoint farm.  I’ll go through how you use the assembly, talk about the pretty easy custom control you need to create (about 5 lines of code) and how you can host it in a page in the _layouts directory as a means to retrieve and render data in web part.  The full source code for the sample custom control and _layouts page will also be posted.

·         Part 4:  the web part that I’m including with the CASI Kit.  It provides an out of the box, no-code solution for you to hook up and connect with an asynchronous client-side query to retrieve data from your cloud-hosted service and then display it in the web part.  It also has hooks built into it so you can customize it quite a bit and use your own JavaScript functions to render the data.

·         Part 5:  a brief walk-through of a couple of sample applications that demonstrate some other scenarios for using the custom control you build that’s described in part 3 in a couple of other common scenarios.  One will be using the control to retrieve some kind of user or configuration data and storing it in the ASP.NET cache, then using it in a custom web part.  The other scenario will be using the custom control to retrieve data from Azure and use it a custom task; in this case, a custom SharePoint timer job.  The full source code for these sample applications will also be posted.

In this post we’ll focus on the pattern for the approach:

1.       Use a custom WCF application as the front end for your data and content

2.       Make it claims aware

3.       Make some additional changes to be able to move it up into the Windows Azure cloud

Using WCF

The main premise of CASI Kit framework is that all application data uses a WCF application as the front end.  Like all custom applications, this is a piece that you, the developer will need to create.  There’s virtually no SharePoint-specific knowledge required for this part of your project – any .NET developer that can use Visual Studio to create a WCF application can do this.  If your ultimate goal is to host this WCF service in Windows Azure then I highly recommend using the Windows Azure development kit to download the templates for creating Azure applications, and start out making an Azure WCF application from the beginning.  There is one important limitation to understand with the current version of the CASI Kit that’s worth pointing out here.  The CASI kit really only supports sending core .NET datatypes as parameters to WCF methods.  So strings, bools, ints and dates work fine, but there isn’t a method to pass in a custom class as a parameter.  If you need to do that however, I recommend creating the parameter as a string and deserializing your parameter to Xml before calling your WCF method, then serializing it back to an object instance in your WCF code.  Beyond that there aren’t any significant limitations I’ve seen so far, but I’m sure a wish list will start forming pretty soon after this is more broadly adopted and used.  As a brief side note, the kit you see today is really just my own v 1.0 ideas of how we could stitch all of these things together and was designed to meet the core scenarios that I’ve thought about and decided were important.  I have no doubt that there will be lots of room for improvement as folks use this.

Make it Claims Aware

Once the WCF application has been created, the next step is to make it claims aware.  For this step I can take absolutely zero credit – I started down this path and will point you to the excellent four part blog post that Eric White from the Office team did to describe how to integrate the claims from SharePoint into a WCF application.  NOTE:  See the update below about getting a sample web.config file if you don’t want to work through the integration or if Eric’s blog is down. Assuming you’ve built your WCF service already, I would start with part 2 of Eric’s blog series at http://blogs.msdn.com/b/ericwhite/archive/2010/05/13/determining-caller-identity-within-a-wcf-web-service.aspx.  Also you MUST continue on and do the steps he outlines in part 3 at http://blogs.msdn.com/b/ericwhite/archive/2010/06/18/establishing-trust-between-a-wcf-web-service-and-the-sharepoint-2010-security-token-service.aspx starting with the section titled  Procedure: Establish Trust between the Web Service and the SharePoint Server.  You need to do the all of the steps from that point forward, which effectively is copying the thumbprint of the SharePoint STS token signing certificate and copying it and some other information into the web.config file for your WCF application.  There are a couple of important additional points though:

  • I would not follow the SSL steps in part 3 step by step because using a self-signed certificate is not really going to be useful when your application is hosted in Windows Azure.  If you don’t have anything else available then that’s what you’ll need to do, but in general you should plan on getting a proper SSL certificate from an appropriate certificate authority for your Windows Azure WCF application. 
  • There is one point in this procedure that is slightly inaccurate.  Eric describes adding the SSL certificate used on the web service to the list of SPTrustedRootAuthorities in SharePoint only if you use a self-signed certificate.  In fact, you should always add any certs in the SSL cert trust chain to SharePoint’s SPTrustedRootAuthorities.  For example, my WCF is secured with a wildcard certificate that looks something like *.vbtoys.com.  *.vbtoys.com has a root authority certificate of vbtoys.com, so I need to add the .CER file (i.e. the public key) for the vbtoys.com root certificate to my trusted root authorities in SharePoint.  You can do this in PowerShell as I’ve described in various blog entries or via central admin, as I described here:  http://blogs.technet.com/b/speschka/archive/2010/07/07/managing-trusted-root-authorities-for-claims-authentication-in-sharepoint-2010-central-admin.aspx.

NOTE:  You DO NOT need to do the steps on part 4 of Eric’s blog.  Now, once you’ve followed the steps described above you have a working WCF, SharePoint claims –aware application.  In the final phase of this posting, I’ll walk you through the additional steps you need to do in order to move it up into Windows Azure.

Make it Work in Windows Azure

Now that you have your working WCF Azure application, there are a few other things that need to be done in order to continue have it support claims authentication and tokens through Windows Identity Framework (WIF) and host it up in the Windows Azure cloud.  Let’s just knock out the list right here:

1.       Configure your WebRole project (i.e. your WCF project) to use a local virtual directory for debugging.  I find this much easier to work with than the VS.NET development server for things using certificates, which you will want to do.  To change this, double-click on the WebRole project properties then click on the Web tab.  Select the radio button that says “Use Local IIS Web server” and then click the Create Virtual Directory button.  Once the virtual directory has been created you can close the project properties.

2.       Add a reference to Microsoft.Identity in your WebRole project.  You MUST change the reference to Copy Local = true and Specific Version = false.  That is necessary to copy the WIF assembly up into the cloud with your application package.

3.       Get this WCF Hotfix:  http://code.msdn.microsoft.com/KB981002/Release/ProjectReleases.aspx?ReleaseId=4009 for Win2k8 R2, http://code.msdn.microsoft.com/KB971842/Release/ProjectReleases.aspx?ReleaseId=3228 for Win2k8.

4.       You MUST add this attribute to your WCF class:  [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)].  So for example, the class looks like this:

namespace CustomersWCF_WebRole

{

    [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]

    public class Customers : ICustomers

    {

 

5.       You MUST include the following configuration data in the behavior element used by your service.  It fixes issues that can occur with random port assignments in the Azure environment.  To test it locally you will need to get the hotfix described in #3 above:

          <useRequestHeadersForMetadataAddress>

            <defaultPorts>

              <add scheme=”http” port=”80″ />

              <add scheme=”https” port=”443″ />

            </defaultPorts>

          </useRequestHeadersForMetadataAddress>

 

Here’s an example in context, of the web.config for my WCF service:

    <behaviors>

      <serviceBehaviors>

        <behavior name=CustomersWCF_WebRole.CustomersBehavior>

          <federatedServiceHostConfiguration name=CustomersWCF_WebRole.Customers/>

          <serviceMetadata httpGetEnabled=true httpsGetEnabled=true/>

          <serviceDebug includeExceptionDetailInFaults=false/>

          <useRequestHeadersForMetadataAddress>

            <defaultPorts>

              <add scheme=http port=80 />

              <add scheme=https port=443 />

            </defaultPorts>

          </useRequestHeadersForMetadataAddress>

        </behavior>

      </serviceBehaviors>

    </behaviors>

 

6.       Upload the SSL certificate you are using for the WCF application to the Azure developer portal first.  NOTE:  The CASI Kit base class is hard-wired to use SSL so you MUST implement SSL support in your WCF Windows Azure application.  Hopefully this should be an expected requirement for passing potentially sensitive data between a cloud service and SharePoint farm. Then add the certificate to the Azure role properties in Visual Studio, by double-clicking on the WebRole project name (in the Roles folder).  I found that using a wildcard certificate worked fine.  You need a PFX certificate though, and make sure you export all certificates in the chain when you create the PFX file.  Azure will expand them all out when you upload it to the developer portal.

7.       Your SSL certificate should be for someName.yourDnsName.com, even though all Azure apps are hosted at cloudapp.net.  For example, my SSL certificate was a wildcard cert for *.vbtoys.com.  In DNS I created a new CNAME record called azurewcf.vbtoys.com, and it referred to myAzureApp.cloudapp.net.  So when I make a connection to https://azurewcf.vbtoys.com my certificate works because my request and SSL certificate is for *.vbtoys.com, but DNS redirects my request based on the CNAME record, which is myAzureApp.cloudapp.net.

8.       In your Azure project double-click on the WebRole project name (in the Roles folder) and set these properties as follows:

a.       Configuration tab:  uncheck the Launch browser for:  HTTP and HTTPS endpoint

b.      Certificates tab:  add the certificate you are going to use for SSL with your service.  For example, in my lab I use a wildcard certificate that’s issued by my domain for all my web servers, so I added my wildcard certificate here.

c.       Endpoints tab:  check both the box for HTTP and HTTPS (the names should be HttpIn and HttpsIn respectively).  In the HTTPS section, the SSL certificate name drop down should now contain the SSL certificate that you added in step b.

9.       If you have a WCF method that returns script, the script tag must include the DEFER attribute in order to work properly when using the web part that is included with the CASI Kit, or if your own JavaScript function assigns it to the innerHTML of a tag.  For example, your script tag should look like this: <script defer language=’javascript’>

10.   If you have a WCF method that returns content that includes other formatting tags, like <style>, you need to wrap them in a <pre> tag or they will not be processed correctly when using the web part that is included with the CASI Kit, or if your own JavaScript function assigns it to the innerHTML of a tag.  For example, the content you return with a style tag should look like this: <pre><style>.foo {font-size:8pt;}</style></pre>

Those are the steps that are needed to configure the WCF application to be hosted in Azure; here are some additional tips that may be useful and in some cases required, depending on your implementation:

1.       Use the fully-qualified name when creating the endpoint address that consumes the service, i.e. machineName.foo.com rather than just machineName.  This will transition more cleanly to the final format hosted on Windows Azure and may also clear up errors that occur when your SSL certificate is designed to use a fully-qualified domain name.

2.       You MAY want to add this attribute: httpsGetEnabled=”true” to this element: <serviceMetadata httpGetEnabled=”true” />, if you want to get your WSDL over SSL.  There is currently a bug in SharePoint Designer though that prevents you from using SSL for WSDL.

3.       For debugging and data connection tips see my post at http://blogs.technet.com/b/speschka/archive/2010/09/19/azure-development-tips-for-debugging-and-connection-strings.aspx.

4.       In most cases you should assume your WCF service namespace is going to be http://tempuri.org.  For instructions on how to change it you can read the post at http://blogs.infosupport.com/blogs/edwinw/archive/2008/07/20/WCF_3A00_-namespaces-in-WSDL.aspx.

The Finished WCF Service

If you’ve followed all of the above configuration steps and deployed your WCF application to Windows Azure, when a user makes a call to that WCF service from a SharePoint site you will also get his or her entire user token, with all the claims that are associated with it.  It’s also worth noting that after you make these changes the WCF service will also work on premise, so it is quite easy to test if you want to try out some incremental changes before pushing the application up to the cloud.  Having that user token allows you to do some really interesting things in your WCF service.  For example, within your WCF service you can enumerate all of a user’s claims and make any kind of fine-grained permissions decisions based on that.  Here’s an example of using LINQ against the set of user claims to determine whether the current user is an administrator, because if he or she is then some additional level of detail will be returned in the request:

//look for the claims identity

IClaimsIdentity ci =

System.Threading.Thread.CurrentPrincipal.Identity as IClaimsIdentity;

 

if (ci != null)

{

//see if there are claims present before running through this

       if (ci.Claims.Count > 0)

       {                       

       //look for a group claim of domain admin

var eClaim = from Microsoft.IdentityModel.Claims.Claim c in ci.Claims

              where c.ClaimType ==

http://schemas.microsoft.com/ws/2008/06/identity/claims/role&#8221; &&

                     c.Value == “Domain Admins”

                     select c;

 

              //see if we got a match

              if (eClaim.Count() > 0)

                     //there’s a match so this user has the Domain Admins claim

                     //do something here

}

}

 

What’s equally cool is that you can also make permission demands directly on your WCF methods.  For example, suppose you have a WCF method that queries a data store and returns a list of customer CEOs.  You don’t want this information available to all employees, only Sales Managers.  One very slick and easy way to implement this is with a PrincipalPermission demand on the method, like this:

//the customer CEO list should not be shared with everyone,

//so only show it to people in the Sales Manager role

[PrincipalPermission(SecurityAction.Demand, Role = “Sales Managers”)]

public string GetCustomerCEOs()

{

//your code goes here

}

 

Now if anyone tries to call this method, if they don’t have a claim for “Sales Managers” then they will get an access denied if they are running code that tries to call this method.  Very cool!

It’s also important to understand that this cannot be spoofed.  For example, you can’t just create your own domain in a lab, add an account to it and create a Sales Manager role to which you add that account.  The reason it won’t work goes back to the steps that you did when going through Eric White’s blog (in the section above titled Make It Claims Aware).  If you recall, you added the thumbprint of the token signing certificate used by the SharePoint STS.  That means when a claim comes into your WCF application, it will look for the token to be signed by the public key of the SharePoint STS.  Only the SharePoint STS can sign it with that public key, since it’s the only entity that has the private key for that token signing certificate.  This assures you that only someone who has authenticated to that SharePoint farm will be able to use the WCF service, and users will only have the claims that were granted to them at the time they logged in.  What’s also interesting about that though is that it includes not only claims that were granted to them when they authenticated to their user directory, but ALSO any additional claims that were given to them via claims augmentation in SharePoint with any custom claims providers.  So this really is a truly integrated end-to-end solution.

UPDATE 8/6/2011:  Since Eric White’s blog has now been moved and I’m not sure how long the old one will be up, I created a sample web.config file with all the SharePoint SAML trust goodness baked in and have included it in the zip file that’s part of this posting.  The parts you need to change for your project are clearly marked with an html comment and five stars, like this:  <!– *****.  Just look for those and update to reflect your project and SharePoint farm and you should be good to go.

Next Steps

In the next post, I’ll start describing the custom base class and web part that comes with the CASI Kit, which will allow you to connect to your new Azure WCF application very quickly and easily.  Also, from this point forward I’ll be using a WCF service I wrote for the CASI Kit as means to demonstrate the functionality.  I’m attaching the .cs file that I used for this service to this posting.  You won’t be able to use it as is, but it’s included merely so you can see the different methods that it contains, the type of data it contains, and how certain features were implemented for this kit.  Primarily during the following postings you’ll mainly see me using the a) GetAllCustomersHtml, b) GetCustomerCEOs, and c) GetAllCustomers methods.  They are interesting because they a) return HTML (which is going to be the defacto preferred return type for displaying data in web parts), b) use a PrincipalPermission demand and c) show how you can return a custom class type from your WCF application and use that same rich class type after you get that data back in SharePoint with the CASI Kit.

You can download the attachment here: