Google Analytics

Thursday, May 8, 2014

Output Raw XML from New Content By Search Web Part

Following this blog post in an attempt to reuse some custom XML developed for SharePoint 2010, I ran into a problem with this technique for outputting raw XML from search in SharePoint 2013.  It seems other have had the same issue.

This is what I came up with to help.  It's not pretty or perfect, but it'll do for now and gives a "decent" picture of what's going on in the XML.

<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
    <xsl:template match='/'>
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="ResultTable">
        <h1>ResultTable</h1>
        <xsl:call-template name="out">
            <xsl:with-param name="in" select="ResultTable" />
        </xsl:call-template>
        <xsl:apply-templates select="Rows" />
    </xsl:template>

    <xsl:template match="Rows">
        <h1>Rows</h1>
        <xsl:call-template name="out">
            <xsl:with-param name="in" select="Rows" />
        </xsl:call-template>
        <xsl:apply-templates select="Row" />
    </xsl:template>

    <xsl:template match='Row'>
        <h1>Row</h1>
        <xsl:call-template name="out">
            <xsl:with-param name="in" select="Row" />
        </xsl:call-template>
    </xsl:template>
   
    <xsl:template name="out">
        <xsl:param name="in" />

        <table style="border: 1px solid #000;">
            <xsl:for-each select="*">
                <tr>
                    <td style="border: 1px solid #000;">
                        <xsl:value-of select="name()" />
                    </td>
                    <td style="border: 1px solid #000;">
                        <xsl:value-of select="." />
                    </td>
                </tr>
            </xsl:for-each>
        </table>
    </xsl:template>
</xsl:stylesheet>

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;
            }
      }

}

Monday, November 8, 2010

Search Core Results Web Part Doesn't Display Managed Property

Everything is set up right.  I've followed articles like this, or maybe this.  I've full crawled a million times, but I still can't get my managed property to display in the search core results web part.

First, double check search is crawling your content properly.  Go to Search administration -> Metadata properties and click the name of your metadata property.  There's a section here labeled 'Content using this property'.  'Number of items found using this property' obviously should not be zero.  If it is, take a look your managed property configurations.  Also, confirm you've actually set the value somewhere in your site and, if in a publishing environment, make sure everything is published and approved.

Second, go to the search box in the site and search for MetadataField:AValueYouKnowExists.  The results should be as expected.  Items with your MetadataField = AValueYouKnowExists should appear in the results.

Lastly, double check the Search Core Results XSLT.  Make sure you've got the proper <Column Name="MetadataField"/> tag.  Also, make sure you're using the right metadata property name in the <xsl:value-of> tag.  This tag is case sensitive.  If you don't get the case right, it's not going to work.  The easiest way to check the case is to edit the Search Core Results web part and put <xmp><xsl:copy-of select="*"/></xmp> into the section labeled <xsl:template match="Result">.  This is going to display all the XML nodes and the values contained in the results.  Refresh your MetadataField:AValueYouKnowExists search and look for your metadata property.