Google Analytics

Monday, May 9, 2011

SharePoint 2010 Error Logging

New to SharePoint 2010 is the ability for developers to readily log to either the SharePoint Unified Logging Service (ULS) or to the Windows application event log.  What a win-win-win situation for all involved, from the developer to the end user to the admin.  The namespace to investigate if you're interested in performing either of these tasks is Microsoft.SharePoint.Administration.  More specifically, the classes under the prefix SPDiagnostics (SPDiagnosticsArea, SPDiagnosticsCategory, ...).  Even more specifically, the methods SPDiagnosticsService.WriteTrace (for ULS logging) and SPDiagnosticsService.WriteEvent (for Windows application event logging).

A great place to put this type of logging is in web parts.  Always be sure to wrap your CreateChildControls or Render methods with a try/catch.  There's nothing worse than the whole page blowing up just because one piece of the page has failed unexpectedly.  On to the example....

catch (Exception ex)
{
     // Get the local instance of the diagnostics service
     SPDiagnosticsService diagService = SPDiagnosticsService.Local;
     // Log the event under the SharePoint Foundation, Web Part category
     SPDiagnosticsCategory diagCategory = diagService.Areas["SharePoint Foundation"].Categories["Web Parts"];
     // The exception message to write to the log
     string exceptionId = "Web Part Exception Unique ID: " + Guid.NewGuid().ToString();
     string exceptionMsg = exceptionId + " " + ex.Message + ex.StackTrace;

     // Log the event as unexpected
     diagService.WriteTrace(0, diagCategory, TraceSeverity.Unexpected, exceptionMsg);

     (...)
}

At this point, it'd be good to write something back to the user of your web part.  Depending on the method you're overriding, you would replace the above ellipsis with code to either add some literal controls to the web part controls collection, or by writing directly to the HTMLTextWriter provided.

     // Provide the user some nice feedback with a follow-up for the admin
     writer.WriteLine("An unexpected error has occurred.");
     writer.WriteBreak();
     writer.WriteLine("If this problem persists, please contact your administrator.");
     writer.WriteBreak();
     writer.WriteBreak();
     writer.WriteLine("Events have been added to the ULS log.");
     writer.WriteBreak();
     writer.WriteLine(exceptionId);

Also new to SharePoint 2010 is a more useful error messaging system in general.  If a page errors out, a dialog box containing a correlation ID is made available for admins to use in troubleshooting.  You may be asking yourself, how do I include this correlation ID into my message back to the user.

I did a lot of digging and found this post by Tobias Zimmergren.  In the section titled "Get the current Correlation ID by using code", he talks about just how to do this.  However, in my opinion, this is overkill.  I say this because...
1.  The correlation ID is not unique to the error itself.  It really reflects the page request as a whole.  Therefore several lines, at least in the ULS log, will have this correlation ID stuck on the end of them.
and
2.  You're already providing the system administrator a new GUID that uniquely identifies this error.

Thursday, April 28, 2011

A Poor Man's Date Filter Web Part

Recently, I was asked to create a date filter to give users an easy mechanism to filter down some data in a list.

Normally, I'd create myself a view on the list then edit the page and add a date filter web part.  At that point, all you have to do is wire up the date filter and the list view web parts and you're done (see this article for more information).

That's all fine and dandy if you've got the SharePoint Enterprise license.  All of the filter web parts are in the Enterprise feature.  What if you don't have Enterprise?  Am I out of luck?

Absolutely not.  Instead of the Date Filter Web Part, why not slap on a Form Web Part?  This little guy lets you define your own HTML to filter with.  Need a text box?  Great.  Need a check box, dropdown list, ...?  Great.  Need a calendar?  Uhm...wait, there's no easy HTML control for a date picker.

Ah, but you're in SharePoint.  SharePoint has date pickers all over the place.  An easy way to toss one on a page is to add a Microsoft.SharePoint.WebControls.DateTimeControl server control to it.  If we can figure out what that control adds to the page, we're golden.

Modify the Form Web Part and add the below HTML to the Source Editor.  The text is red is what renders the date picker functionality onto the page.

<div onkeydown="javascript:if (event.keyCode == 13) _SFSUBMIT_">
  <SCRIPT language='javascript' src='/_layouts/datepicker.js'></SCRIPT>
  <SCRIPT language='javascript'>var g_strDateTimeControlIDs = new Array();</SCRIPT>
  <SCRIPT language='javascript'>g_strDateTimeControlIDs[""] = "ctl00_PlaceHolderMain_ctl00_Date";</SCRIPT>
  <input name="ctl00$PlaceHolderMain$ctl00$Date" type="text" maxlength="45" id="ctl00_PlaceHolderMain_ctl00_Date" class="ms-input" AutoPostBack="0" />
  <A href="#" onclick='clickDatePicker("ctl00_PlaceHolderMain_ctl00_Date", "\u002f_layouts\u002fiframe.aspx?&cal=1&lcid=1033&langid=1033&ww=0111110&fdow=0&fwoy=0&hj=0&swn=False&minjday=109207&maxjday=2666269&date=", ""); return false;' >
    <IMG id=ctl00_PlaceHolderMain_ctl00_DateDatePickerImage src="/_layouts/images/calendar.gif" border="0" alt="Select a date from the calendar."></IMG>
  </A>
  <IFRAME id=ctl00_PlaceHolderMain_ctl00_DateDatePickerFrame SRC="/_layouts/images/blank.gif" FRAMEBORDER=0 SCROLLING=no style="DISPLAY:none;POSITION:absolute; width:200px; Z-INDEX:101;" title="Select a date from the calendar."></IFRAME>

  <input type="button" value="Go" onclick="javascript:_SFSUBMIT_"/>
  <input type="button" value="Reset" onclick="javascript:_SFRESET_"/>
</div>

Awesome!  Now we've got a date picker in our Form Web Part.  All that's left is to wire it up to our list view web part the same way we always did.

Friday, February 11, 2011

Remove Default SharePoint Web Part CSS - Part 2

A post is long over due.  I wanted to revisit this topic for two reasons.  It was my first post ever, and according to best practices, this is not (necessarily) what you should do to remove SharePoint CSS classes from your custom developed web part.

If you follow best practices, you should not be inheriting from Microsoft.SharePoint.WebPartPages.WebPart.  According to SDK, "this class exists primarily for the purpose of backward compatibility, and secondarily, to provide a small set of features that are not available in the ASP.NET web part class."

The UseDefaultStyles Property, unfortunately, is available only in the Microsoft.SharePoint.WebPartPages.WebPart class and not in the System.Web.UI.WebControls.WebParts.WebPart class (the class you should really be using 99% of the time).

So...how do I fix my cumbersome SharePoint default CSS for my System.Web.UI.WebControls.WebParts.WebPart inherited class?!  This is what I came up with.

public class NoCssWebPart : System.Web.UI.WebControls.WebParts.WebPart
{
      protected override void OnInit(EventArgs e)
      {
            base.OnInit(e);

            // No default styles
            if (this.Zone != null && this.Zone.WebPartChrome != null)
            {
                  SPChromeSettings chromeSettings = ((SPChrome)this.Zone.WebPartChrome).GetSPChromeSettings(this);
                  chromeSettings.UseDefaultStyles = false;
            }
      }

}