Tuesday, October 18, 2005
New Customer Success Story
If you, your firm, your clients, partners or other SharePointers are interested in reading the case study, it is available for download here.
If you have any questions or would like more details on the technical architecture/development/etc., feel free to post a comment with your email addy and I'll respond accordingly.
Monday, October 10, 2005
Extreme SharePoint Design: Custom MySite Titles
This is important to remember when modifying the menus, links and other navigational elements. In some instances, such as the public and private pages, you will be referring to MySite url's (/mysite/); in others, such as document libraries and lists, you will be referring to Personal url's (/personal/[username]/). This can be quite confusing when, for example, you need to create a site title that is displayed on every page and links back to either the public or private view.
The SharePoint object model has some built-in functions that help you determine your site context but they don't span multiple contexts (in other words, there's no way to know which mysite is associated with the current personal path a page is in) and they don't always expose data the way you need it. In the following example, we'll use various properties of the GetContextWeb method to create a personal site title based on the user's full name from Active Directory that, when viewed by the site owner, links back to the private home page, and when viewed by a reader, links back to the public page.
//Retrieve the site title, which should be the user's full name from AD
string strFullName = SPControl.GetContextWeb(Context).Title;
string strTitle;
int intLocation, intLength;
// Determine length of string, find comma separator if one exists
intLength = strFullName.Length;
intLocation = strFullName.IndexOf(", ");
// If a comma is not found (the user name is not separated into Last Name, First Name), set the Title value to the full Title from AD; otherwise, parse out the first name and last name, remove the comma and space, and reverse the strings to read First Name Last Name
if (intLocation == -1)
strTitle = strFullName;
else
strTitle = strFullName.Substring(intLocation + 1) + " " + strFullName.Substring(0,intLocation );
// Determine if the current user is the site author; if so, set the link href value to mysite and write out the Title. If the current user is only a reader, set the link href to the public url and write out the same Title value.
if (SPControl.GetContextWeb(Context).CurrentUser.LoginName == SPControl.GetContextWeb(Context).Author.LoginName)
{
Response.Write("<a href='/mysite/default.aspx'>" + strTitle + "</a>");
}
else
{
Response.Write("<a href='/mysite/public.aspx?accountname=" +
SPControl.GetContextWeb(Context).Author.LoginName + "'>" + strTitle + "</a>");
}
Note that you will only be able to execute this code from a user control; standard web part pages won't allow code execution. To call a user control from within a web part page, create an .ascx file, insert the required registrations (be sure to utilize Microsoft.SharePoint.WebControls) and code, then register the page location (usually the /bin folder on the virtual server), and call the registration from within the web part page.
Friday, September 30, 2005
Search Index Rules Syntax
When creating a rule that references a URL path, such as http://servername/Area, you must replace any spaces and special characters (ampersands, apostrophes, commas, etc.) with the proper URL encoding (%20, %26, %2C, etc.). Otherwise, the MSSearch process will ignore the rule and continue evaluating results against valid rules.
Also, remember that the order of the rules is important. If you are trying to exclude the above URL, the Portal_Content index will have a default inclusion rule of http://servername/; any new rules you create will be processed after this rule is satisfied. Since the default rule includes all content, any antecedent rules will be ignored. To address this issue, simply move your exclusions to precede the blanket inclusion and the search service will properly exclude the specified content source.
Thursday, September 29, 2005
Extreme SharePoint Design: 'Go Back To [Area/Site]' Link
There's just one problem: when accessing these pages, users often get lost with no way to return to where they came from. Nothing is more frustrating than finding yourself seven steps into a wizard with no way to bail out but to smack the 'Back' button repeatedly. The solution is a 'Go Back To [Area/Site]' link at the top of each administration page which gives the user one-click access to the place they started from.
Insert the following code into AlternateHeader.aspx or directly into your administration pages just after the PageHeader section (if you're using heavily customized Site Definitions as I often do, most of your admin pages will have header code in them to overwrite AlternateHeader and PortalHeader; just paste the following code into the appropriate section and format it as needed):
<%
try
{
Response.Write ("<a href='" + SPControl.GetContextWeb(Context).Url + "'>Go Back to " + SPControl.GetContextWeb(Context).Title + "</a>");
}
catch
{Response.Write ("Portal Administration Page");
}
%>
The 'try' block creates a link back to the root of the referring area/site using the title field as the link text. The 'catch' block writes out a general statement that you can replace with anything you like, just in case the link fails to render properly.
NOTE: In 'Extreme SharePoint Design: Creating Custom User Menus', I used the same function to replicate the behavior of the 'Home' button on WSS sites. Use SPControl.GetContextWeb(Context) anytime you want to refer to the root URL of an area or site; use SPControl.GetContextSite(Context) to reference the site collection the current site belongs to.
UPDATE: I forgot to mention that you'll need to insert the following code at the top of alternateheader.aspx in order for SharePoint to parse inline code blocks on the page (otherwise you will receive the dreaded 'External component has thrown an exception' error):
<%@ Page language="C#" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
Updated SharePoint Resources List
If you're looking for a list of tools and utilities, including commercial and non-commercial software, web parts, add-ons, and the like, I maintain a brief list here and Joris Poelmans has a monster list here.
BTW, whatever happened to the Sharepoint Template Project???
Wednesday, September 28, 2005
New Blog Template
Drop a comment and let me know if this one works any better...
Tuesday, September 27, 2005
Extreme SharePoint Design - Creating Custom User Menus
Originally intended to be a much shorter article, I kept finding additional things I felt needed to be included to present a complete picture, so the final version is rather lengthy. Hence the linked PDF as opposed to one big blog post. Download the article here (right-click, choose 'Save Target As'):
Extreme SharePoint Design - Creating Custom User Menus (PDF, 464k)
Enjoy!
Wednesday, September 14, 2005
New SharePoint Features
- RSS. Everything about sites, lists, libraries, etc., can be syndicated via RSS automatically.
Blogs and Wikis. Templates and features in the box.
Excellent. This will save a great deal of frustration with email-based alerts.
- Content Types. These aren’t just like SPS 2001’s document profiles. They define sets of metadata, but they also contain view information. And associated workflows. And events bound to them (synchronous or asynchronous). And you can have more than one in the same list/library.
Hmm...not sure. Will this help with the problem of retrieving views via web services?
- Workflow. Windows Workflow Foundation is embedded in WSS. It’s used everywhere.
I want to jump up and shout for joy...BUT...if they don't include a visual designer embedded into the UI ala Nintex SmartLibrary then they will have completely missed the boat. LOB managers, content editors, and designers cannot AND WILL NOT be forced to rely upon developers to create workflows.
- Recycle Bin. We did it. It’s scoped to a site and captures deleted documents, items, etc. It has a user restore and an administrative restore.
Now that deserves a jump and a shout (assuming, of course, that it applies to SPS as well).
- Per-item security. Even on list items.
I can die happy now. Is it really true? Oh, please, let it be so!
- FrontPage has evolved into a feature set that makes it truly a SharePoint site designer. (Ghosting’s still around, but it won’t be a problem anymore. I’ll explain why in an upcoming post.
Interesting. This could make the job of customization a bit easier, which would make my life a much better place.
- Forms services in Office “12” servers. That’s right — design a form in the InfoPath rich client, publish it as a SharePoint site, and it can be either viewed/filled out in the full smart client or in a browser as HTML.
One word: S-W-E-E-T!
- Search. Better APIs. Better results. Alternate search suggestions (misspelled words,etc.). A highly customizable default Web-based UI.
I'm definitely excited about this. Search is a bit of a blessing and a curse, so any improvement will be welcome.
- Office “12” servers will also contain a Business Data Catalog, a facility that registers LOB application data and Web services. Once that’s happened, BDC-aware Web Parts can pull data from them, we can index them, and a lot more. There’s a session on this tomorrow.
Not sure about this one. Sounds interesting, though.
- Office “12” servers will also be able to take a spreadsheet published to a SharePoint site and reneer it as an HTML application.
Like it but not sure how useful that will be...
- Mobile views of SharePoint lists. That’s right, a way to render a list on a mobile device.
Very nice.
- Lists now have a Business Data type that will use the aforemntioned Business Data Catalog
Unsure on this one. Need more info.
- Access will be able to treat SharePoint site data as fulll-blown data sources.
Yeah, baby!
All in all, it sounds promising. So, looking back, how'd they do with regards to my various predictions, rants and ravings? Not bad, I'd say.
Tuesday, September 06, 2005
Extreme SharePoint Design: Modifying The 'Grouped By' Headers
<GroupByHeader> <HTML><![CDATA[ <TBODY id="titl]]></HTML> <GetVar Name="GroupByLevelString"/> <HTML><![CDATA["><TR]]></HTML> <Switch> <Expr><GetVar Name="GroupByIndent"/></Expr> <Case Value="0"> <HTML> <![CDATA[ class="ms-gb" ]]> </HTML> </Case> <Default> <HTML> <![CDATA[ class="ms-gb2" ]]> </HTML> </Default> </Switch> <HTML><![CDATA[><TD colspan="100" nowrap><img src="/_layouts/images/blank.gif" alt="" height=1 width=]]></HTML> <GetVar Name="GroupByIndent"/> <HTML><![CDATA[><a href="javascript:" onclick="javascript:ExpCollGroup(']]></HTML> <GetVar Name="GroupByLevelString"/> <HTML><![CDATA[','img_]]></HTML> <GetVar Name="GroupByLevelString"/> <HTML><![CDATA[');return false;"><img id="img_]]></HTML> <GetVar Name="GroupByLevelString"/> <HTML><![CDATA[" src="/_layouts/images/minus.gif" alt="]]></HTML> <HTML>Expand/Collapse</HTML> <HTML><![CDATA[" border="0"></a> ]]></HTML> <GetVar Name="GroupByField" HTMLEncode="TRUE" /> <HTML><![CDATA[ : ]]></HTML> <GetVar Name="GroupByValue"/> <HTML><![CDATA[</TD></TR></TBODY>]]></HTML> </GroupByHeader>
Remove the field label and colon by deleting or commenting out the following code from this section:
<GetVar Name="GroupByField" HTMLEncode="TRUE" /> <HTML><![CDATA[ : ]]></HTML>
You may also wish to change the drab gray style by modifying ms-gb and ms-gb2 or assigning a class in a custom style sheet.
Once you're finished editing the file, save it and reset IIS. Note that this is a global change that will affect all lists in the definition. For localized changes, create a Data View Web Part and modify the XSL accordingly.
Compiling Locally Without SharePoint Installed
The dependency 'Microsoft.SharePoint.Security' could not be found.
The dependency 'Microsoft.SharePoint.Dsp' could not be found.
The dependency 'Microsoft.SharePoint.Library' could not be found.
To circumvent this issue, extract the underlying DLL's from the GAC and copy them to your local machine. You'll need to perform the copy from the command prompt as Windows Explorer does not expose the full directory structure for the GAC. Each DLL resides in a directory with a path similar to the following:
c:/windows/assembly/gac/[Strong Name]/[Version Number]__[Public Key]/[Strong Name].dll
Once you have the DLL's you can include them as a reference in your project and compile without errors.