Showing posts with label csharp. Show all posts
Showing posts with label csharp. Show all posts

27 October 2011

SharePoint: Get parent site title

In SharePoint, we can use subsites to handle navigation beyond the 2nd level; let's assume we have a structure such as this:
  • Site Collection Root
    • Site 1: site title - "Products & Software"
      • Subsite A: site title - "Widgets"
        • Subsite AA: site title - "Widget X"
        • Subsite BB: site title - "Widget Y"
    • Site 2
    • Site 3
It often makes sense to show Site 1's title "Products & Software" down that branch of subsites, regardless of how deep you are. This helps users know they're still under "Products & Software". To fetch the root parent's title (Site1, not the Site Collection Root), you have to use a recursive function, thanks to W0ut and help from Stack Exchange:
protected override void OnLoad(EventArgs e)
{
  // To ensure page behaves correctly, must call base.OnLoad(e).
  base.OnLoad(e);

  GetRootTitle();
}

private void GetRootTitle()
{
  string title = string.Empty;

  /* 
     On admin pages, this label object doesn't exist and will throw
     a NullReferenceException if we don't check it before trying
     to use it.
  */
  if (sectionTitle == null) return;

  using (SPSite site = new SPSite(SPContext.Current.Site.ID))
  {
    using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
    {
      title = IterateThroughParentsAndStoreInfo(web, title);
    }
  }

  sectionTitle.Text = title; // Set a label's value to the title.
}

private string IterateThroughParentsAndStoreInfo(SPWeb web, string title)
{
  if (web.ParentWeb != null)
  {
    title = web.Title;
    return IterateThroughParentsAndStoreInfo(web.ParentWeb, title);
  }
  return title;
}
Note the using statements; these ensure there are no memory leaks by disposing of the objects properly and also implicitly handling the try/catch/finally block. The change to W0ut's code is the addition of the OnLoad() handler, which can be either in your master page or page layout. Also, we've added the title variable, which gets set in the recursive function; note that its value is always of the title for the site one before the last. This is because when the web variable's ParentWeb becomes null, we've reached the site collection. This is exactly what we need.

One last thing to note: We do a null check for the label object which will hold the title's value. On some administrative (system) pages, the label isn't rendered so we'll throw a NullReferenceException. Another way to do this is to always add the title label as a new Label(); this way it's always present, regardless of which page we're on.

02 October 2011

SharePoint: Fetch environment variables and store in JavaScript

For a header text, we needed the current site's name. In addition, to generate a "Share this page with a friend" button, we needed the current user's login name and full name. We could use SharePoint's Client Object Model, which does an asynchronous call from JavaScript to get the information.

However, we needed the site's name to be available with the DOM, not when the page loads; we tried the AJAX call and it took a second or two to fetch the data. During this time, the page had no header text saying which site the user was on.

What to do? We could use jQuery to get the site name from the breadcrumbs generated via the asp:SiteMapPath control, but there could be times when we wouldn't be using this control. Else we could fetch it from the top-left navigation tree dropdown; even that was clunky. So we decided to put the following code in the Page Layout's PlaceHolderAdditionalPageHead control; it can also be placed in the master page:
<asp:Content ContentPlaceholderID="PlaceHolderAdditionalPageHead" runat="server">
<%
String currentUserName = Microsoft.SharePoint.SPContext.Current.Web.CurrentUser.Name.ToString();
String currentUserEmail = Microsoft.SharePoint.SPContext.Current.Web.CurrentUser.LoginName.ToString().Replace("MYDOMAIN\\","");
String currentSite = Microsoft.SharePoint.SPContext.Current.Web.ToString();
String currentTitle = (Microsoft.SharePoint.SPContext.Current.Item["Title"] == null) ?
 "" : Microsoft.SharePoint.SPContext.Current.Item["Title"].ToString();

StringBuilder sb = new StringBuilder();
sb.Append("<script type='text/javascript'>var currentElements = { currentUserName: '");
sb.Append(currentUserName);
sb.Append("', currentUserEmail: '");
sb.Append(currentUserEmail);
sb.Append("', currentSite: '");
sb.Append(currentSite);
sb.Append("', currentTitle: '");
sb.Append(currentTitle);
sb.Append("'}</script>");
Response.Write(sb.ToString());
%>

....

</asp:Content>
We fetch the current user's name using the SPContext.Current property, which gives us a handle to the current HTTP request in SharePoint. Then we get the various items we need, such as the user's name, login name, web (current site name), and the publishing page's title.

Once we have the values, we plug them into a JavaScript array that we build server-side. When the page loads in the browser, the array will be instantiated with the values we set using C#. We use a StringBuilder object for optimal performance because of the string concatenations.

So what does it look like when the page loads? Here it is:
<script type='text/javascript'>var currentElements = { currentUserName: 'Alex C', currentUserEmail: 'myemailid', currentSite: 'My Site Name', currentTitle: 'Page Title'}</script>
To use any of the array elements in jQuery or elsewhere, just call it via something like this: currentElements.currentSite

A final note: If any of the values will have a single quote in them, just escape the value using a .Replace("'","\'")on the string in C#.

07 August 2011

SharePoint: Conditionally display content for authors and readers

For a current project, I needed to display an Article Date content field in a page layout. The author could pick a date when in Edit View; the reader would only see the value the author had selected, or nothing if no value had been picked.

To do server-side code blocks in a page layout, we'll first need to enable it from our app's web.config file; otherwise it'll throw an error saying "Code blocks are not allowed in this file," as described here. To enable code blocks, open your app's web.config and locate the PageParserPaths tag, which is empty, and modify it to look like this:


Note the VirtualPath; this needs to point to the location of your page layout (or ASPX) file.

Next, we'll use Bart McDonough's blog post to add the EditModePanel and AuthoringContainer; the nesting of these controls is well explained by Bart:











http://www.blogger.com/img/blank.gif
Note the DateTimeField element; that allows authors to edit the "Article Date" field.

Now we need to add some server-side code to determine if we can display the "Article Date," and to format it properly (this code is based on Johan Leino's blog post):
<%= (Microsoft.SharePoint.SPContext.Current.Item["Article Date"] == null) ? "" : 
"Last update on " + DateTime.Parse(Microsoft.SharePoint.SPContext.Current.Item["Article Date"].ToString()).ToString("d MMMM yyyy") +
"." %>
This code displays the text "Last update on 9 August 2011." if there's a value in the "Article Date" content field; otherwise, it displays nothing.