Microsoft

User Profile Personalized Links

Recently my company performed a migration for our old production environment to a new production environment so we had a more stable and robust platform to support the company, including providing leadership with better business intelligence about our operations. As part of the migration one of my goals was to launch My Sites for our internal users so they had somewhere to store information they were working on.

As I was thinking about what would be useful to our employees I ran across the Personalized Links capability available in the User Profile Service Application. In general this capability allows us to “push” links onto a user’s My Site. Since our company uses Great Plains for timecards and financial management integrated into SharePoint I thought it would be worthwhile to place the link to an employee’s Timecard Entry page along with a link to our primary portal. I then decided a link for Timesheet Reviewers made sense, but I didn’t want it to show up on all of the employee’s pages, just the employees who actually review timesheets. We have already scoped this link on our portal by using the Business Portal security groups, but since we are working in the context of the My Site we don’t have those security groups to rely on.

User Profile Personalized Links like most other things in SharePoint include the ability to apply audiences, so controlling who sees the links are possible, but I needed to create the right audience. I jumped over to the Profile Audiences and told my profile service to compile the audience. While the audience was compiling I applied it to my Personalized Link for Timesheet Review. I then checked to see that the audience had compiled and took a look at my My Site…no Timesheet Review link.

I took another look at my audience and realized it had 0 members, so I decided to delete it. After deleting the audience I then decided I would remove the Timesheet Review Link for the time being ad that is where the trouble began.

When I pulled up the Personalized Links page the only item showing where my links should have been was a message “The query returned and error. Contract your SharePoint Administrator” *Crap! I am the SharePoint Administrator! *

Ok, I figured I could fix this easily, I’ll just recreate the Audience with the same name…Nope, same error message.

Ok, the add new link button is available, I’ll add a new Link and the bad one will get “fixed” magically…Nope, no magic here.

Ok, so I checked my SharePoint Logs, my server application logs, and everywhere else in hopes I would see what the exact error was, alas nothing…

Fine, SharePoint is nothing more than a database application when we boil it down to the root I decided to crack it open and see what was going on. I opened the My Site Content Database and began looking at the various tables and opening the ones I thought had the highest probability of containing the list of links I had created.

After about an hour of searching I finally opened the table SharedListSync, and there I found my entry for the Timesheet Review along with the audience GUID. I decided the best method at this point was to change the audience GUID to 0, like the other entries that I had not applied Audiences to.

When I returned to the Personalized Links page sure enough all the links I had entered were now available and I was able to finally remove the Timesheet Review link.

Advertisements

SharePoint 2010 and Windows Azure App Fabric Access Control (ACS)

Last month I was working on a demo for a charitable organization that has lots of volunteers around the country. The charity didn’t want to have to create new active directory accounts for each of these volunteers so as part of the demo we integrated SharePoint 2010 site with Windows Azure App Fabric Access Control (ACS), this way we could use Google, Windows Live, and Yahoo! as authentication providers. (Yes I know we could hook directly to each of these providers, but using ACS allowed me to use all the providers with one SharePoint Trusted Provider instead of using three different trust providers). We demoed the site to the charity and they were very excited and happy with the solution.

This week we began building a demo for an accounting firm who needs to be able to grant access to external clients. While talking with our Business Developers and other team members I recommended we re-use the ACS access for this new site to give the external users access. I first attempted just enabling the current ACS Trust for my new Account site, but found that it was trying to authenticate me to the original charity site. After a little playing around here are the steps to allow multiple sites to authenticate with a single Windows ACS.

Add a new Relying Party Application

From the Windows Azure AppFabric portal (or the demo portal as we are using) select your existing SharePoint 2010 Service Namespace and click on the Access Control Portal button.

From the Access Control portal select the Relying Party Applications


In the Relying Party Applications click Add.


Provide a unique name and realm for the new application.

Make sure you increase the Token lifetime so you don’t get stuck in a token issue-reissue cycle. For the Rule Group use the same rules I created for my previous application. Also make sure you select the “Use a dedicated certificate” for the Token Signing Setting. You can re-use the same certificate for each application or issue a new one, but if you don’t set this value one of the certificates created by Windows ACS will be used and your services will fail to authenticate due to certificate signing issues.

Now click the Save button.

At this point you should have a new relying party application listed.

Update your SharePoint Trust

Now you will need to go to your SharePoint 2010 environment and log in as one of the SharePoint Farm Administrators.
In Central Administration view the application previously configured with the Windows ACS. Here you are just looking for the name of the Trusted Authentication provider, we will need that name in order to access it from the SharePoint Management Shell.
Open the SharePoint Management Shell and type the following command:


To see all the properties of the provider type $provider in the management shell. This will result in a printout of all the properties.
Next we need to create a URI object so we can add a new realm to the Trusted Identity Issuer.


Now we can add the realm with the URI to the trusted provider we retrieved


Now update the provider.


Now when you display the Trusted Identity Issuer you will see an entry in the Provider Realms like this.

Update your SharePoint Site Authentication

Now we can enable the site to use this claim provider.

Go back to Central Administration->Manage Web Applications and select the new site.


Then select Authentication Providers and the name of the Zone you want to allow ACS authentication for.


Scroll down in the Edit Authentication window and check the Trusted Identity provider and your Windows ACS provider name (this is the same name we used above in the SharePoint 2010 Management Shell).


Now scroll all the way down to the bottom and click Save.
Now go and log into your site with a non Windows ACS account. This way you can add some Windows ACS accounts to your site and test.
Once you have added some accounts go ahead and give it a try, you should be able to log in using your Windows ACS service on both the original and the new site.
Need to set up ACS for the first time? I recommend using these sites:

https://blogs.pointbridge.com/Blogs/nielsen_travis/Pages/Post.aspx?_ID=38 (this is a bit older version of ACS, so the UI is different)

http://blogs.technet.com/b/speschka/archive/2011/05/05/federated-saml-authentication-with-sharepoint-2010-and-azure-access-control-service-part-1.aspx

Visual Studio 2010 SharePoint List Template Error

I was attempting to create a custom FAST Search Center that would have a custom master page, and some web parts added to the search and result pages. My starting point was to grab the FAST Search Center site definition from the site templates in the SharePoint 14 Hive.

Next, I added the search tab and result tab lists to the site collection. Again I copied the XML from the SharePoint site definition…well almost. I actually copied all but the root node which had an XML namespace. After pasting this content I noticed under a few nodes, and some attributes, the little squiggly line. When I built the solution I noted warning messages but there were no errors. However, the deployment failed with an XML validation error.

As I began comparing the SharePoint list template with my list template I began removing various segments, starting with the ones that we marked as errors. While this resolved the deployment issue my lists did not function properly with the Site Template.

Next, I removed the XML namespace and the restored the previously erroneous XML, this time without any squiggly line or build warnings. When I deployed the solution no errors or failures occurred and my Custom FAST Site Template worked perfectly.

SQL Server Date vs. DateTime columns and the SharePoint 2010 External Content Type

Recently I have been working on a SharePoint 2010 solution that leverages External Content Types for storing information associated with Microsoft Dynamics Great Planes Timesheets. Part of the information captures when an task is expected to be completed, which the UI allows the user to select a date from a calendar. Since the only significant information for this field was the date when I designed the database I chose to only capture the date value. Testing on my local Windows 7 VM worked perfectly and we rolled the solution out to the customer for testing.

In the late testing stages the customer sent back a critical issue. The date value selected by the user was being changed, worse when the associated information was imported from Timesheet to Timesheet (because it was an ongoing task) the dates were moving further and further back in time.

I have seen this issue before with SharePoint 2007, pre SP1, that on DateTime field inputs if you didn’t convert to from local time to UTC your dates would not appear correctly. Immediately I added code to manually convert my captured time from local to UTC. I then changed the Time Zone on my VM so I would have a similar offset (originially I was running with GMT time myself thus I had not seen this issue). As I began testing I continued to see the same issue the customer was seeing, even with my conversion to UTC.

With the debugger attached I began looking at the values going into and out of the database. What I noticed was that a value going in would be something like 1/1/2011 05:00:00 but the value being returned looked like 12/31/2010 19:00:00. Looking into the External Content Type I noticed that it was using a DateTime .NET object. This means that when the value is retrieved from the database if the time is not in the database field then it defaults to 12:00:00. From there SharePoint performs the conversion from UTC to the local timezones (in this case subtracting 5 hours).

Lesson from this is to make sure you use full date time fields with your external content types.

Microsoft Silverlight 4 and SharePoint 2010 Integration

Recently I was contacted by PACKT Publishing because they have recently published a book Microsoft Silverlight 4 and SharePoint 2010 Integration and wanted me to review the book.  I’m actually quite excited about this opportunity because it is my first invitation to review a book, and the book is talking about two of my favorite technologies!

Currently I have a deadline approaching for a SharePoint 2007 Farm Architecture document, my least favorite thing to do, so I’m not allowing myself a lot of time with “fun” stuff like the topics in this book until the documentation is complete.  However, I have reviewed the first chapter and I really can’t wait to get back to it.  The first chapter is a very straight forward approach to creating a Silverlight Application and then including it in SharePoint 2010.

PACKT has published the first chapter “Integrating Silverlight 4 with SharePoint 2010” here for others to read before purchasing the book.

Once I have gotten through my documentation work I will take the time to review the book, try the examples, and will then post more about it here on my blog.

SharePoint Lists Web Service

During a recent project I was leveraging the SharePoint Lists Web Service to retrieve information from a list and push it to a Silverlight display.  The list I was using was a heavily customized list with about 35 different views and at least as may fields.  My Silverlight display would provide information like the “status” of the list item based on a number of other criteria.  This status field was stored as a simple “Single line of text” field in the SharePoint list.

The first issue I had to resolve was how to get the right view for the SharePoint list.  The frustration with this is that the Lists Service’s (lists.asmx) GetListItems action has the second parameter “viewName” the documentation on this parameter actually specifies the proper value is a GUID.  I will write another blog about how I retrieved the view’s GUID later, but for now just understand that I did have to take that into account.

After getting the proper view information I now needed to filter the list so that only particular items I was interested in would be returned.  I added the query parameter to perform the filtering as well as adding the viewFields parameter to ensure that I received the fields I expected.

At this point I went ahead and executed my code thinking that I was now good to go and should receive my filtered list items.  On the initial execution an exception was thrown, so I placed a breakpoint on the xml result from the GetListItems call and re-executed.  When I hit the breakpoint I looked at the and noticed the status field was missing.  I allowed the code to continue and when it attempted to access the status field the exception was thrown.  I verified that I had the correct view, view fields, filters etc and nothing looked out of place.

I think downloaded U2U’s CAML Query Builder (a tool I HIGHLY recommend if you are building CAML queries) and tested my query in that.  Interestingly, I noticed that the status field was missing in U2U’s output.  I then modified the query, I removed the <where>…</where> statement, so that all list items would be returned and suddenly the status field appeared.

I reexamined the list item data, and since it had no value in the status field I decided to add one (something that normal users are not allowed to do in the production list).  I executed my query in the U2U tool and noticed that now the status field was available.  Again I went back to the list and removed the status field value, and again the field was removed from my query results.

I have tested this scenario with a number of other lists all using the single line of text field and have noticed similar outcomes, the field is not returned if it has no value.  I have since modified my code to handle the case where the field may not be returned and I use a default “status” value.  I have since noticed that this is pointed out in the commends (second from the bottom at the time of me writing this blog) but is not included anywhere in the documentation.

Best of luck!

A WCF “WHAT THE…”

I’ve been working with WCF and SharePoint 2007 and ran across an issue.  The scenario is an Account Registration process which allows the user to request access to “protected” sites within a portal.  This solution blends some jQuery and WCF using the JSON format for request and response messages.  The issue I ran into was when a user requested access to a/several sites I needed to pass the Site ID to the WCF service as part of the user request object.

User Request Object

[DataContract]
[KnownType(“GetKnownTypes”)]
public class UserDetails
{
[DataMember] public string UserName;
[DataMember] public string Provider;
[DataMember] public string FirstName;
[DataMember] public string LastName;
[DataMember] public string Email;
[DataMember] public string Organization;
[DataMember] public string Title;
[DataMember] public string Department;
[DataMember] public string Position;
[DataMember] public string WorkAddress1;
[DataMember] public string WorkAddress2;
[DataMember] public string City;
[DataMember] public string State;
[DataMember] public string Zip;
[DataMember] public string Phone;

        [DataMember] public string Country;

        [DataMember] public string CountryCode;

        [DataMember] public IUserDataExtension ExtendedInformation;

        private static Type[] GetKnownTypes()
{
return KnownTypesProvider.GetKnownTypes();
}

}

Ok, so the first thing you might notice is the KnownTypes, but for now lets just agree that it works and I’ll talk about it in a later blog.  Now you do notice I have a IUserDataExtension object in the User Details, and that is what we will talk about here, or at least an item in it.

Here is the implemenation of the IUserDataExtension:

[DataContract]
public class ExtendedUserDetails : IUserDataExtension
{
public ExtendedUserDetails()
{
Worksites = new List<string>();
}

        [DataMember] public List<string> Worksites;

        [DataMember] public string Justification;
}

So the key piece here is the Worksites List.  Notice I am capturing the values as string, but in reality they are Guids that I retrieve from SharePoint using a different web service.  I chose to use strings because Guid has a constructor that takes a string object and I figured this would let me handle the casting and exceptions if something when wrong.

At this point I began testing and everything worked, as long as I did not pass any worksite IDs to my service.  As soon as I would include a worksite ID I would end up with a 400 error code and a web page that said “The server encountered an error processing the request. See server logs for more details”, but of course the server logs had nothing about the error in them.  Attaching a debugger never did any good because my WCF functions were never reached, so somewhere earlier in the call stack an exception was being thrown.

I began experimenting, and just on a whim decided, “Well, javascript doesn’t know about ASP.NET Guid objects, it just sees them as string, but what if I set the List type to Guid?”  So I changed the class as follows.

[DataContract]
public class ExtendedUserDetails : IUserDataExtension
{
public ExtendedUserDetails()
{
Worksites = new List<Guid>();
}

        [DataMember] public List<Guid> Worksites;

        [DataMember] public string Justification;
}

Once I compiled and upgraded my solution, TA DA!  So the lesson of this story is that you CAN’T pass Guids as string to a WCF service.  My belief is that during the parsing of this object the format matches that of a Guid so WCF casts the object to string, but when it tries to find an object with List<Guid> container that fails and an exception is thrown, hopefully some of my contacts at Microsoft will be able to shed some light on this for me.