共用方式為


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";

       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";

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.

CASI_Kit_Part5.zip

Comments

  • Anonymous
    January 01, 2003
    The comment has been removed
  • Anonymous
    February 28, 2015
    This post is most useful when used as a companion to my five-part series on the CASI (Claims, Azure and
  • Anonymous
    February 28, 2015
    This post is most useful when used as a companion to my five-part series on the CASI (Claims, Azure and