SP2010: Custom logout page
If you use a login mechanism that uses cookies to store your token, you may find the logout option a tad redundant.
What happens is, you choose to logout, get sent to the logout page where you are prompted to close the page, which you probably don’t want to do, then you click the link “go back to site” which on doing so, logs you back in!
If your authentication provider (ADFS, IDM, etc) has a logout page, then you probably want to redirect them to that. Or if you want to customize your own logout page, well more power to you!
To change where the logout link brings you to, you need to modify the Welcome.ascx control template.
Browse to /14/TEMPLATE/CONTROLTEMPLATES and edit the welcome.ascx file.
You can add a property called ClientOnClickNavigateUrl to overwrite where the “log me out” link brings you to.
Once you save this control and refresh your page, you will have a new logout destination!
SP2010: Creating a wiki page using the OM
SharePoint 2010 has made immense improvements over the wiki page, so much that that they are popping up all over the place in SharePoint sites. With SharePoint Server, the home page of the team site template is a wiki page.
If you already have a standard (non-wiki) site, and want to wiki’fy the home page, you can activate the feature Wiki Page Home Page. This will create a pages library if one does not exist, create a wiki page in the library, and make that the site home page.
Need To Know
If you want to build your own feature to create a custom wiki page, there are a few things you need to know.
The wiki page is not a web part page
Well, technically it is, but not really. While you can add web parts to a wiki page, it operates much differently to a web part page with zones etc. There is one (hidden) web part zone (“wpz”) on the page, where all web parts are contained. How they are presented on the page is all done through markup.
Know your HTML
The layout of the page is handled through html tables. For example, the default table has two columns. When you use the ribbon to change the layout, it creates a new table and moves the content around. When creating your page, you should start with one of these layouts. And above all else, make user you use fully complaint html, otherwise you may find manipulating the page in the UI will yield unexpected results.
Spacing
Allow a little spacing so the user can drop elements. If you only add web parts and don’t provide spacing in the page, it will be very hard for them to add or move elements around the page.
Web Parts
Web parts get added to the zone and to the markup. You need to assign a guid to the web part when adding to the zone, then reference that id from the markup. See below for the proper format of the web part reference html.
With that in mind…
lets look at creating a custom wiki page and adding it to the library.
We are doing this through a feature receiver.
The steps we are going to take are:
- Layout the page using HTML table.
- Define a couple of web parts
- Add web parts to web part zone
- Add web parts to table
- Create web part page in site pages library
- Replace wiki content with new table.
- Save page
- Eat nachos
Assumptions
To keep the example simple, we will assume the following (so we don’t have to manage in code).
- A Site Pages library already exists
- An Announcements list already exists
- A Shared Documents library already exists
- We’re not to concerned about error trapping (for demo purposes only!!)
- Below is the markup for our page layout.
- <table id="layoutsTable" style="width: 100%">
- <tbody>
- <tr style="vertical-align: top">
- <td style="width: 66.6%">
- <div class="ms-rte-layoutszone-outer" style="width: 100%">
- <div class="ms-rte-layoutszone-inner" style="min-height: 60px; word-wrap: break-word">
- {{0}}
- <p></p>
- </div>
- </div>
- </td>
- <td style="width: 33.3%">
- <div class="ms-rte-layoutszone-outer" style="width: 100%">
- <div class="ms-rte-layoutszone-inner" style="min-height: 60px; word-wrap: break-word">
- <p>
- <img style="margin: 5px" alt="People collaborating" src="/_layouts/images/homepageSamplePhoto.jpg" /></p>
- {{1}}
- <p></p>
- </div>
- </div>
- </td>
- </tr>
- </tbody>
- </table>
- <span id="layoutsData" style="display: none">false,false,2</span>
- This layout creates a 2-column layout similar to the default team site wiki page.
- You can see we have several tokens that we are going to replace with the markup for our web part references.
- Below is a sample of a web part referenced in the page html.
- <div class='ms-rtestate-read ms-rte-wpbox' contenteditable='false'>
- <div class='ms-rtestate-read 5e2446a1-fc9d-49ad-8a23-4d8e71960ff0' id='div_5e2446a1-fc9d-49ad-8a23-4d8e71960ff0'>
- </div>
- <div style='display: none' id='vid_5e2446a1-fc9d-49ad-8a23-4d8e71960ff0'>
- </div>
- </div>
You will notice this doesn’t actually contain the web part html, just a reference to it. The client script will move all the web parts into their correct position using the guids.
Adding the web part to the page
We use the SPLimitedWebPartManager to add the web part to the page as normal.
- private Guid AddWebPartControlToPage(SPFile wikiFile, System.Web.UI.WebControls.WebParts.WebPart wp)
- {
- SPLimitedWebPartManager limitedWebPartManager = wikiFile.GetLimitedWebPartManager(PersonalizationScope.Shared);
- Guid storageKeyGuid = Guid.NewGuid();
- string storageKeyId = StorageKeyToID(storageKeyGuid);
- wp.ID = storageKeyId;
- limitedWebPartManager.AddWebPart(wp, "wpz", 0);
- return storageKeyGuid;
- }
Adding the web part markup to the page
Once we format the html correctly, we inject it into the layout table.
- private void AddWebPartMarkUpToPage(Guid wpGuid, string replaceToken)
- {
- string wpDiv = string.Format(CultureInfo.InvariantCulture, "<div class='ms-rtestate-read ms-rte-wpbox' contentEditable='false'><div class='ms-rtestate-read {0}' id='div_{0}'></div><div style='display:none' id='vid_{0}'></div></div>", new object[] { wpGuid.ToString("D") });
- wikiFullContent = wikiFullContent.Replace(replaceToken, wpDiv);
- }
Updating the Wiki Content
Each wiki page contains one wiki field that we can reference.
- wikiItem[SPBuiltInFieldId.WikiField] = wikiFullContent.ToString();
- wikiItem.UpdateOverwriteVersion();
Put it all together
So, putting all of the above together (and a little bit more) we get:
- using System;
- using System.Runtime.InteropServices;
- using System.Security.Permissions;
- using Microsoft.SharePoint;
- using Microsoft.SharePoint.WebPartPages;
- using System.Web.UI.WebControls.WebParts;
- using System.Text;
- using System.Globalization;
- using System.Reflection;
- using System.Xml;
- namespace donalconlon.net
- {
- [Guid("381cfa14-13a6-426a-9ee8-ecd6e7082c23")]
- public class WikiPage_EventReceiver : SPFeatureReceiver
- {
- private string wikiFullContent = string.Empty;
- public override void FeatureActivated(SPFeatureReceiverProperties properties)
- {
- using (SPWeb site = (SPWeb)properties.Feature.Parent)
- {
- //* Define page payout
- wikiFullContent = FormatBasicWikiLayout();
- //* Add page to library
- SPList sitePages = site.Lists["Site Pages"];
- SPFolder rootFolder = sitePages.RootFolder;
- SPFile wikiPage = rootFolder.Files.Add(String.Format("{0}/{1}", rootFolder.ServerRelativeUrl, "mywikipage.aspx"), SPTemplateFileType.WikiPage);
- SPListItem wikiItem = wikiPage.Item;
- //* Define content and add
- #region Announcements
- SPList listAnnouncements = site.Lists["Announcements"];
- ListViewWebPart wpAnnouncements = new ListViewWebPart();
- wpAnnouncements.ListName = listAnnouncements.ID.ToString("B").ToUpper();
- wpAnnouncements.ViewGuid = listAnnouncements.DefaultView.ID.ToString("B").ToUpper();
- Guid wpAnnouncementsGuid = AddWebPartControlToPage(wikiPage, wpAnnouncements);
- AddWebPartMarkUpToPage(wpAnnouncementsGuid, "{{0}}");
- #endregion
- #region Shared Documents
- ListViewWebPart wpDocs = new ListViewWebPart();
- SPList listDocs = site.Lists["Shared Documents"];
- wpDocs.ListName = listDocs.ID.ToString("B").ToUpper();
- wpDocs.ViewGuid = listDocs.DefaultView.ID.ToString("B").ToUpper();
- Guid wpDocsGuid = AddWebPartControlToPage(wikiPage, wpDocs);
- AddWebPartMarkUpToPage(wpDocsGuid, "{{1}}");
- #endregion //Shared Documents
- //* Update Wiki page content and save
- wikiItem[SPBuiltInFieldId.WikiField] = wikiFullContent.ToString();
- wikiItem.UpdateOverwriteVersion();
- }
- }
- private string FormatBasicWikiLayout()
- {
- StringBuilder sb = new StringBuilder();
- sb.Append("<table id=\"layoutsTable\" style=\"width: 100%\">");
- sb.Append("<tbody>");
- sb.Append("<tr style=\"vertical-align: top\">");
- sb.Append("<td style=\"width: 66.6%\">");
- sb.Append("<div class=\"ms-rte-layoutszone-outer\" style=\"width: 100%\">");
- sb.Append("<div class=\"ms-rte-layoutszone-inner\" style=\"min-height: 60px; word-wrap: break-word\">");
- sb.Append("{{0}}");
- sb.Append("{{1}}");
- sb.Append("<p></p>");
- sb.Append("</div>");
- sb.Append("</div>");
- sb.Append("</td>");
- sb.Append("<td style=\"width: 33.3%\">");
- sb.Append("<div class=\"ms-rte-layoutszone-outer\" style=\"width: 100%\">");
- sb.Append("<div class=\"ms-rte-layoutszone-inner\" style=\"min-height: 60px; word-wrap: break-word\">");
- sb.Append("<p><img style=\"margin: 5px\" alt=\"People collaborating\" src=\"/_layouts/images/homepageSamplePhoto.jpg\" /></p>");
- sb.Append("<p></p>");
- sb.Append("</div>");
- sb.Append("</div>");
- sb.Append("</td>");
- sb.Append("</tr>");
- sb.Append("</tbody>");
- sb.Append("</table>");
- sb.Append("<span id=\"layoutsData\" style=\"display: none\">false,false,2</span>");
- return sb.ToString();
- }
- private Guid AddWebPartControlToPage(SPFile wikiFile, System.Web.UI.WebControls.WebParts.WebPart wp)
- {
- SPLimitedWebPartManager limitedWebPartManager = wikiFile.GetLimitedWebPartManager(PersonalizationScope.Shared);
- Guid storageKeyGuid = Guid.NewGuid();
- string storageKeyId = StorageKeyToID(storageKeyGuid);
- wp.ID = storageKeyId;
- limitedWebPartManager.AddWebPart(wp, "wpz", 0);
- return storageKeyGuid;
- }
- private void AddWebPartMarkUpToPage(Guid wpGuid, string replaceToken)
- {
- string wpDiv = string.Format(CultureInfo.InvariantCulture, "<div class='ms-rtestate-read ms-rte-wpbox' contentEditable='false'><div class='ms-rtestate-read {0}' id='div_{0}'></div><div style='display:none' id='vid_{0}'></div></div>", new object[] { wpGuid.ToString("D") });
- wikiFullContent = wikiFullContent.Replace(replaceToken, wpDiv);
- }
- public static string StorageKeyToID(Guid storageKey)
- {
- if (!(Guid.Empty == storageKey))
- {
- return ("g_" + storageKey.ToString().Replace('-', '_'));
- }
- return string.Empty;
- }
- }
- }
So what we get is a new wiki page with a couple of web parts and a picture. Lovely jubley.
Wrapping Up
The wiki page is a great feature of SharePoint 2010, and using code, you can manipulate it to create your own custom pages. I’ve shown how to create a new page, add web parts and content, then save that page to the Site Pages library.
References
Many thanks to Habañero for their very useful post on the topic.