By Chris R. Chapman at May 10, 2010 23:28
Filed Under: windows7, windows server 2008

Since leaving MSFT, I’ve had to undertake building my own dev machine that’s ready to take on SharePoint 2010 projects, and today I got the final piece in place.  Well, it’s actaully a “penultimate final piece”:  8 GB of DDR3 1066Mhz RAM.  I’ve already configured my Lenovo T510 to dual boot using VHDs for Win7 Ultimate and Win2k8 R2, but the latter was really taxed after installing SQL Server 2008 and SharePoint 2010 – it was peaking at 3.67 GB, bringing my machine to its knees.

No longer:  With the new RAM installed, it now cruises along at a liesurely 2.68 GB with all four engines sipping cycles:

Win2k8r2_sharepoint_8gb_awwyeah

Fantastic.  Next up is to put Visual Studio 2010 Premium on the image and she will be complete!  Then I can back up the VHD to an external drive for disaster recovery, or to run as a Hyper-V image from a stock Win2k8 R2 VHD.

By Chris R. Chapman at May 08, 2010 02:47
Filed Under: claims based auth, sharepoint2010

While recently helping out my friends at Envision IT with their SharePoint 2010 FBA configuration, I came across an unsurprisingly frustrating aspect of using a custom ASP.NET form to handle the authentication.  From most of the sparse documentation that is available on this topic (re: custom FBA forms – there’s tons on OOTB FBA), you’d think that all that’s required is to provide an URL to your form in Central Administration and Bob is your father’s brother.

Centraladmin_customform
  Ta-da!  Ready to go home now!

Um, noooo.

The Bad News:  It Ain’t Gonna Work

It’d be great if things worked so easily as just slapping in an URL and the back-end wiring itself up automagically like it came out of Hogwarts – not so fast.  Say you have a basic ASP.NET form and you’ve configured it thus with standard <asp:Login> control:

<%@ Page Language="c#" AutoEventWireup="false" Inherits="System.Web.UI.Page" Trace="false" %>
<form id="fbaLoginForm" runat="server">
<asp:login id="signInControl" runat="server" displayrememberme="False"></asp:login>
<asp:checkbox id="chkRememberMe" runat="server" cssclass="RememberMe" text="Remember me and my language preference" tooltip="Tooltip goes here" visible="False" /> <br />
<span style="margin-left: 4px">
  <
a href="../ForgotPass/default.aspx" class="Label">
    <asp:label id="lblForgotPass" runat="server" text="Forgot Password?"></asp:label>
  </a>
</
span> </div> <script type="text/javascript" language="javascript">
// This Script focuses on the Username field (or the password field if the username was remembered)
if (document.getElementById("ctl00_ContentPlaceHolder1_Login1_UserName").value != "") {
document.getElementById(
"ctl00_ContentPlaceHolder1_Login1_Password").focus();
}
else {
document.getElementById(
"ctl00_ContentPlaceHolder1_Login1_UserName").focus();}
</script> </form>

Assuming that you’ve already set up the ASP.NET Membership SQL database, configured the Membership and Role providers, made the commensurate changes in the web app, Secure Token Service and Central Admin web.configs and gone into Central Administration to configure Forms Based authentication, you’d find that all your efforts would have been for nought:  This form would dutifully validate your credentials against the Membership database, but then unmercilessly given you a 403 HTTP error when the form attempted to redirect to /_layouts/Authenticate.aspx. (See my “How-To” FBA links on Delicious for reference if you’re lost in what I just said)

Why? 

Because a vanilla ASP.NET form has no idea how to create the required claims based authentication token to pass along to SharePoint’s doorman to say that you really are on “the list” and that you know this guy inside who can vouch for you.  This form inherits from System.Web.UI.Page – you are a nobody as far as Club SharePoint 2010 is concerned.  Move along.

The Good News:  You Can Make It Work

There is another way, but it is top-secret.  Well, at least it seems that way given the rigamarole I had to go through to put it together – there’s no API documentation on this, you see.  The solution is to go in-cognito:  In this case, to set your login form page to inherit from the same class that the out-of-the-box SharePoint FBA login form implementsMicrosoft.SharePoint.IdentityProvider.FormsSignInPage (this can be found in the /_forms sub folder of any SharePoint 2010 web application that has been set for FBA).

Ootb_login
  Our target:  The OOTB SharePoint 2010 FBA Form

Now through the magic of polymorphism, you too can access all the SharePoint FBA/Claims Auth token creation goodness out-of-the-box FBA forms get for “free”.  Please, hold your applause.

Ootb_fba_defaultaspx
  /_forms/default.aspx – You want to rip this code off

Using the default.aspx page as a guide, you can adapt your own custom login .aspx page and master page to implement the required <asp:Content> areas – you might want to keep them all or put the ones you don’t plan to use inside an <asp:Panel> control with the Visible property set to false.  Here’s what my revised login page default.aspx looks like – note the Assembly and Import directives and the Inherits property for the <% Page %> directive, and the <asp:Content> controls – these are required by the FormsSignInPage.

    1 <%@ Assembly Name="Microsoft.SharePoint.IdentityModel, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

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

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

    4 <%@ Import Namespace="Microsoft.SharePoint.WebControls" %>

    5 <%@ Import Namespace="Microsoft.SharePoint" %>

    6 

    7 <%@ Page Language="c#" AutoEventWireup="false" MasterPageFile="DefaultGoodMasterPage.master"

    8     Inherits="Microsoft.SharePoint.IdentityModel.Pages.FormsSignInPage" Trace="false" %>

    9 

   10 <%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"

   11     Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

   12 <%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities"

   13     Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

   14 

   15 <asp:Content ID="Content2" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">

   16     <SharePoint:EncodedLiteral runat="server" EncodeMethod="HtmlEncode" ID="ClaimsFormsPageTitle" />

   17 </asp:Content>

   18 <asp:Content ID="Content3" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea"

   19     runat="server">

   20     <SharePoint:EncodedLiteral runat="server" EncodeMethod="HtmlEncode" ID="ClaimsFormsPageTitleInTitleArea" />

   21 </asp:Content>

   22 <asp:Content ContentPlaceHolderID="PlaceHolderSiteName" runat="server" />

   23 <asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server" />

   24 

   25 <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">

   26     <SharePoint:EncodedLiteral runat="server" EncodeMethod="HtmlEncode" ID="ClaimsFormsPageMessage" />

   27     <div style="text-align: left; margin-top: 10px;">

   28         <asp:Login ID="signInControl" runat="server">

   29         </asp:Login>

   30         <asp:CheckBox ID="chkRememberMe" runat="server" Text="Remember me"

   31             ToolTip="Tooltip goes here" Visible="False" />

   32         <br />

   33         <span style="margin-left: 4px"><a href="~/forgotmypassword/default.aspx">

   34             <asp:Label ID="lblForgotPass" runat="server" Text="Forgot Password?">

   35             </asp:Label>

   36         </a></span>

   37     </div>

   38     <script type="text/javascript" language="javascript">

   39         // This Script focuses on the Username field (or the password field if the username was remembered)

   40         if (document.getElementById("ctl00_ContentPlaceHolder1_Login1_UserName").value != "") {

   41             document.getElementById("ctl00_ContentPlaceHolder1_Login1_Password").focus();

   42         } else {

   43             document.getElementById("ctl00_ContentPlaceHolder1_Login1_UserName").focus();

   44         } 

   45     </script>

   46 </asp:Content>

   47 

Below is the master page code for my demo login form.  Note the <asp:Panel> control I’ve placed at line 32 that contains the <asp:ContentPlaceHolder> controls that are required by the FormsSignInPage class, but I don’t want to implement right now so I’ve hidden them.  This is an old trick I’ve borrowed from creating minimal master pages for SharePoint 2007 (nod to Heather Solomon;  what?  you don’t know who she is?  For shame…)

    1 <%@ Master Language="c#" %>

    2 

    3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    4 <html xmlns="http://www.w3.org/1999/xhtml" runat="server" id="html">

    5 <head id="Head1" runat="server">

    6     <title>Good SharePoint 2010 FBA Login</title>

    7     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    8     <meta name="keywords" content="" />

    9     <!-- Head Content Ends here -->

   10     <asp:ContentPlaceHolder ID="ContentPlaceHolderHead1" runat="server">

   11     </asp:ContentPlaceHolder>

   12     <!-- Head Content Ends here -->

   13 </head>

   14 <body onload="if (typeof(body_onload) == 'function') window.setTimeout('body_onload();', 500);">

   15     <form id="form1" runat="server">

   16     <h1 style="color: Green">

   17         Good SharePoint 2010 FBA Login Form</h1>

   18     <div>

   19         This form will process and validate credentials for an FBA user and successfully

   20         redirect them to the SharePoint Site.

   21         <p>

   22             Specifically, it inherits from <b>Microsoft.SharePoint.IdentityModel.Pages.FormsSignInPage</b>

   23         </p>

   24     </div>

   25     <div>

   26         <!-- Page Content Starts here -->

   27         <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">

   28         </asp:ContentPlaceHolder>

   29         <!-- Page Content Ends here -->

   30     </div>

   31     <!-- Required ContentPlaceHolders for parent page object -->

   32     <asp:Panel runat="server" Visible="false">

   33         <asp:ContentPlaceHolder ID="PlaceHolderPageTitle" runat="server">

   34         </asp:ContentPlaceHolder>

   35         <asp:ContentPlaceHolder ID="PlaceHolderPageTitleInTitleArea" runat="server">

   36         </asp:ContentPlaceHolder>

   37         <asp:ContentPlaceHolder ID="PlaceHolderSiteName" runat="server">

   38         </asp:ContentPlaceHolder>

   39         <asp:ContentPlaceHolder ID="PlaceHolderMain" runat="server">

   40         </asp:ContentPlaceHolder>

   41     </asp:Panel>

   42     </form>

   43 </body>

   44 </html>

   45 

Custom_login_good
  Behold:  This login form has actually been nominated for several design awards.

Using this technique, you can now adapt your pre-existing FBA login forms to conform with the claims based auth requirements for SharePoint 2010.  As far as I can tell, as of this writing there is no documentation around doing this – I had to use Reflector to determine what was going on inside the FormsSignInPage object as the API has no corresponding entries.

It’s a little more involved than just slapping down an ASP.NET page and setting the Sign In Form URL – but not that much more.

Please enjoy responsibly!

By Chris R. Chapman at May 05, 2010 16:58
Filed Under: sharepoint, sharepoint2010

I had to post this as I know that it’s been a burning issue for developers and admins who have tried, as per the directions of many web casts and promises from MCS types like myself, to change a “classic” authentication web app into a “claims based authentication” web app after creation.  Typically, after you’ve created the web app in classic mode, the radio button to change it to Claims is greyed out:

Edit_authentication

So the UI is a bust, however I’ve suspected that there is an easy way to get around this through PowerShell – via Chun Liu’s post, Forms-based Authentication on a Claims-based Web App, we have an answer.  Well, at least the start of an answer.  I had to do some minor tweaks to his script – here’s what you’d need to enter on the command line:

> [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
> $webapp = [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup("
http://mywebapp")
> $webapp.UseClaimsAuthentication = ‘True’;
> $webapp.Update()
> $webapp.ProvisionGlobally()

Do this on one of your classic auth web apps, and when you load up the Authentication Providers in Central Administration, it will now be Claims enabled.  Ta-da!

Please enjoy responsibly.

Update:  Of course, if you use the SharePoint 2010 Management Shell you can use the abbreviation $webapp = Get-SPWebApplication(http://mywebapp) instead of the long-hand I've used above.

By Chris R. Chapman at May 04, 2010 06:30
Filed Under: better practices, sharepoint, sharepoint2010

One of the top questions SharePoint developers and consultants are asked by their customers is for a list of real-world deployments - either as examples of what can be done with the platform or because they feel more secure in their decision to deploy SharePoint when a lot of other people have done so before them.

Whatever the reason, you want to have some samples to draw on or point folks toward.  The standard canon has been compiled by Ian Morrish over at WSSDemo.com since WSS v2.0 was new.  Ian's since upgraded his site with each release of the platform and has one of the definitive lists of sites around - over 1,500.  However, I just came across another site earlier tonight called Top SharePoint that also has an impressive array (over 1,000) of SharePoint deployments that are apparently rated and ranked by site visitors.  Entries are searchable and feature screen captures and brief descriptions - and as a bonus for we Canucks, they include some prime examples.

What's not clear from TopSharePoint is the version of SharePoint each site is deployed on - keen eyes will be able to discern clues from URLs and navigating the sites, however, it is possible to have 2007 sites upgraded to 2010 with the original look and feel retained.  Nevertheless, these two sites should be kept in your kit for quick reference - sooner or later you'll be asked for them!

By Chris R. Chapman at May 01, 2010 03:41
Filed Under: sharepoint2010

It’s Friday, and that means some late-breaking link goodness courtesy of TechNet, the TechNet Script Center and Bill Baer:

First up:  Two that go hand-in-glove and have come up in recent conversations I’ve had with colleagues and customers:

Next, with PowerShell now superceding STSADM on the command line (although the latter hasn’t gone away completely) you may find it helpful to know correlations between the two:

Recently, a SharePoint tweep (is that right?) lamented the loss of the Site Directory in 2010.  It was deprecated due to limitations of the site template when being migrated from 2007.  Bill Baer has some counsel and workarounds:

Finally, some cool scripts by Ji Lie – for kicks:

Enjoy! 

Tags:

About Me

I am a Toronto-based software consultant specializing in SharePoint, .NET technologies and agile/iterative/lean software project management practices.

I am also a former Microsoft Consulting Services (MCS) Consultant with experience providing enterprise customers with subject matter expertise for planning and deploying SharePoint as well as .NET application development best practices.  I am MCAD certified (2006) and earned my Professional Scrum Master I certification in late September 2010, having previously earned my Certified Scrum Master certification in 2006. (What's the difference?)