Monday, April 30, 2012

Helpers in Sharepoint Code :

Last week I managed to secure decent score in getting my MCTS Sharepoint configuration exam.
Being a hectic week ( I had a >100% utilization as well at work), I wanted to share some good code snippets with everyone which helps us get things done faster in Sharepoint ...I am panning to share with everyone my preperation guide and my strategy to get going in a week's timeframe if someone's interested in getting certified!

Now..coming back to the blog...
Helper functions to the rescue: Often as developers we use helper functions, I have planned to use this space to collate them here to get all of them at one Central location!

  • Get Custom User profile properties
Often we create custom properties in Active directory which need to be accessible via code. In my most recent project we had such a scenario and a generic helper function below helped us in code reuse

accountName can be the account of the current logged in user  or any user and property is the string which we need to find.
   // this function fetches a property of a user
        public static string GetUserProperty(SPSite site, string accountName, string property)
        {
            try
            {
                string userProperty = string.Empty;
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    SPServiceContext context = SPServiceContext.GetContext(site);
                    var UserProfMgr = new UserProfileManager(context);
                    UserProfile UserProf = UserProfMgr.GetUserProfile(accountName);

                    if (UserProf[property].Value != null)
                    {
                        userProperty = UserProf[property].Value.ToString();
                    }
                });
                return userProperty;
            }

            catch (Exception ex)
            {
                throw new Exception("Could not get the property:" + property + "of the User:" + accountName);
            }

        }
    }
  • Trace Log an Exception
Often for the development team it is a challenge to debug issues in share point. Catching and Throwing proper exceptions is the Best way to troubleshoot issues. the one class i have started using recently is below :

    Define an enum for the severity :

   public enum LogSeverity
    {
        Unexpected,
        High,
        Medium,
        Info,
        Monitorable,
        Verbose,
        VerboseEx,
        None
    }


Class file :
 public static class TraceLog
    {
        private static DiagnosticsService myULS = null;

        public static void Log(string msg, LogSeverity severity)
        {
            if (myULS == null)
            {
                myULS = DiagnosticsService.Local;
            }

            if (myULS != null)
            {
                TraceSeverity tSeverity = mapTraceSeverity(severity);
                SPDiagnosticsCategory cat = myULS[CategoryId.General];

                myULS.WriteTrace(5555, cat, tSeverity, msg, myULS.TypeName);
            }
        }

        public enum CategoryId
        {
            None = 0,
            Deployment = 100,
            Provisioning = 200,
            CustomAction = 300,
            Rendering = 400,
            WebPart = 500,
            General = 600
        }

        [System.Runtime.InteropServices.GuidAttribute("DBEWW5AB-C5A7-46B5-A2BB-5581F960C333")]
        class DiagnosticsService : SPDiagnosticsServiceBase
        {
            private static string DiagnosticsAreaName = "Project Name";

            public DiagnosticsService()
            {
            }

            public DiagnosticsService(string name, SPFarm farm)
                : base(name, farm)
            {
            }

            protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
            {
                List<SPDiagnosticsCategory> categories = new List<SPDiagnosticsCategory>();
                foreach (string catName in Enum.GetNames(typeof(CategoryId)))
                {
                    uint catId = (uint)(int)Enum.Parse(typeof(CategoryId), catName);
                    categories.Add(new SPDiagnosticsCategory(catName, TraceSeverity.Verbose, EventSeverity.Error, 0, catId));
                }

                yield return new SPDiagnosticsArea(DiagnosticsAreaName, categories);
            }

            public static DiagnosticsService Local
            {
                get
                {
                    return SPDiagnosticsServiceBase.GetLocal<DiagnosticsService>();
                }
            }

            public SPDiagnosticsCategory this[CategoryId id]
            {
                get
                {
                    return Areas[DiagnosticsAreaName].Categories[id.ToString()];
                }
            }
        }

        private static TraceSeverity mapTraceSeverity(LogSeverity severity)
        {
            TraceSeverity tr = TraceSeverity.None;
            switch (severity)
            {
                case LogSeverity.Unexpected:
                    tr = TraceSeverity.Unexpected;
                    break;
                case LogSeverity.High:
                    tr = TraceSeverity.High;
                    break;
                case LogSeverity.Monitorable:
                    tr = TraceSeverity.Monitorable;
                    break;
                case LogSeverity.Medium:
                    tr = TraceSeverity.Medium;
                    break;
                case LogSeverity.Info:
                case LogSeverity.Verbose:
                    tr = TraceSeverity.Verbose;
                    break;
                case LogSeverity.VerboseEx:
                    tr = TraceSeverity.VerboseEx;
                    break;
                case LogSeverity.None:
                    tr = TraceSeverity.None;
                    break;
            }
            return tr;
        }
    }

A simple call in catch will, serve the purpose

catch (Exception ex)
            {
                throw new Exception("Exception Occurred, Details :" + " + ex.message.tostring());
            }

Thursday, April 5, 2012

Sharepoint XML world...

I have used XML in a variety of my earlier projects and find it very interesting concept.

In one of my recent projects, To Read an XML file from Layouts folder to display a Megamenu which is audience targetted based on a userprofile property was pretty challenging for me... so I am sharing this with my fellow SP developement team for reference!

Define the string constant for the path to XML file
 public const string XMLFILEPATH = "Template/Layouts/Banfield.Portal/MyFile.xml";  
Let's say the XML is in the below format

<?xml version="1.0" encoding="UTF-8"?>
<Menu>
  <Tab Title="Tab 1">
    <Audience>Audience1,Audience2</Audience>
    <Content>
      <![CDATA[
      <ul> <!-- ul for the tab -->
        <li> <!-- li per column in the tab -->
          <ul> <!-- ul for the column -->
            <li> <!-- li per group in the column -->
              <h3>Tab One, Column One, Group One</h3>
              <ul> <!-- ul for the group -->
                <li> <!-- li per link -->
                  <a href="something">Tab One, Column One, Group One, Link One</a>
                </li>
                <li>
                  <a href="something else">Tab One, Column One, Group One, Link Two</a>
                </li>
              </ul>
            </li>
            <li>
              <h3>Tab One, Column One, Group Two</h3>
              <ul>...</ul> <!-- ul for the group, with li's per link -->
            </li>
          </ul>
        </li>
        <li>

      ]]>
    </Content>
  </Tab>
  <Tab Title="Tab 2">
    <Audience>Audience1,Audience3</Audience>
    <Content>
      <![CDATA[<ul> <!-- ul for the tab -->
        <li> <!-- li per column in the tab -->
          <ul> <!-- ul for the column -->
            <li> <!-- li per group in the column -->
              <h3>Tab 2, Column One, Group One</h3>
              <ul> <!-- ul for the group -->
                <li> <!-- li per link -->
                  <a href="something">Tab 2, Column One, Group One, Link One</a>
                </li>
                <li>
                  <a href="something else">Tab 2, Column One, Group One, Link Two</a>
                </li>
              </ul>
            </li>
            <li>
              <h3>Tab 2, Column One, Group Two</h3>
              <ul>...</ul> <!-- ul for the group, with li's per link -->
            </li>
          </ul>
        </li>
        <li>
      ]]>
    </Content>
  </Tab>
  <Tab Title="Tab 3">
    <Audience>Audience1,Audience2,Audience3</Audience>
    <Content>
      <![CDATA[<ul> <!-- ul for the tab -->
        <li> <!-- li per column in the tab -->
          <ul> <!-- ul for the column -->
            <li> <!-- li per group in the column -->
              <h3>Tab 3, Column One, Group One</h3>
              <ul> <!-- ul for the group -->
                <li> <!-- li per link -->
                  <a href="something">Tab 3, Column One, Group One, Link One</a>
                </li>
                <li>
                  <a href="something else">Tab 3, Column One, Group One, Link Two</a>
                </li>
              </ul>
            </li>
            <li>
              <h3>Tab 3, Column One, Group Two</h3>
              <ul>...</ul> <!-- ul for the group, with li's per link -->
            </li>
          </ul>
        </li>
        <li>
      ]]>
    </Content>
  </Tab>
</Menu>

In CreateChildControls - using System.LinQ we will try to retrieve the data of the XML

  System.Xml.Linq.XDocument doc = XDocument.Load(Microsoft.SharePoint.Utilities.SPUtility.GetGenericSetupPath(XMLFILEPATH));
  

Now we can safely start the process of data retrieval for the megamenu elements for the user's departrment ( this is specified as a user profile property.)

  
  XElement navElement = doc.Element("Menu");
  
         using (SPSite siteCollection = new SPSite(SPContext.Current.Web.Url))
  
         {
  
             
           var AudienceCategory = GetUserProfile.GetUserProperty(SPContext.Current.Site, loginName, GetUserProfile.AudienceCategory);
  
           var newElement = from el in navElement.Descendants("TopNode")
    
                   where el.Element("Audience").Value.Contains(strDepartment)
  
                    select new
  
                      {
  
                        TopNodeTitle = el.Attribute("Title").Value,
  
                        TopNodeContent = el.Element("Content").Value 
  
                      };
  
           if (newElement != null)
  
           {
  
             // Prepare for the rendering of megamenu classes, UL and Li's
  
             StringBuilder sb = new StringBuilder();
  
             foreach (var c in newElement)
  
             {
  
               RenderTopNodeContents(c.TopNodeTitle.ToString(), c.TopNodeContent.ToString(), sb);
  
             }
  
             MegaMenuUl.InnerHtml = sb.ToString();
  
           }
  
         }  
HTML for the usercontrol

 <div class="Menu" runat="server" >
  
 <ul id="MenuUl" runat="server">
 </ul>
  
 </div>  

RenderTabContents function :

  private void RenderTabContents(string strTabTitle, string strContent, StringBuilder sb)
  
     {
  
       sb.Append("<li>"); // Begin Li for each Tab
  
       sb.Append("<h2>"); // H2 for the Menu name
  
       sb.Append(strTabTitle);
  
       sb.Append("</h2>"); // End for H2
  
       sb.Append(strContent); // This should have the UL and Li embedded in the content from XML
  
       sb.Append("</li>"); //End Li for each tab
  
     }