Category Archives: CKS

Custom Field Types in SharePoint 2013 Apps

Synopsis and Key Take-Aways

Custom field types in SharePoint provide the ability to customize all aspects of SharePoint form fields– from how they are displayed, to how values are validated to how values are stored within SharePoint and a couple of other things along the way. They provide significant capability for enforcing business rules and providing a much more user friendly experience than what is available via the out-of-the-box field types.  Unfortunately, this power has never been available in a cloud-hosting scenario such as Office 365.  Things are changing for the better, however, with new capabilities available in SharePoint 2013 Preview.  We now have the ability to provide the same functionality to our end users without running custom code on the server.  With SharePoint 2013 Preview, we can modify the presentation and validation of a custom field (or technically any field) on any form in SharePoint as well as in Views simply via JavaScript.  This is an incredibly powerful capability.  It provides a nice, easy, standard (and supported) way of customizing the end user experience to be more efficient and friendly.

This article introduces the scenario, walks through the end user experience using a sample custom field and then dives into a code-level review of how to implement this new functionality.  The commented source code listing for the required JavaScript is available for download.

Note that as of the initial publication of this article (October 2012), this is based on the SharePoint 2013 Public Preview.  Once I can download RTM I’ll look to revisit this and update the article as necessary.

Introduction

Custom field types in SharePoint provide the ability to customize all aspects of SharePoint form fields– from how they are displayed, to how values are validated to how values are stored within SharePoint and a couple of other things along the way.  They provide significant capability for enforcing business rules and providing a much more user friendly experience than what is available via the out-of-the-box field types (single line of text, yes/no, date/time, user, url, etc.)

Unfortunately, this power and flexibility is simply not available in a cloud scenario such as Office 365 because they require that files be deployed to the server file system which you can’t do in a cloud solution.  For the 2010 release of SharePoint, there have been various attempts at simulating custom field types in a cloud scenario, but all have suffered from varying degrees of fragility or other problems.

Fast-forward to SharePoint 2013 and Microsoft has made things much easier for developers and much less fragile all around with regard to custom field types.  For the first time, it is possible to truly get most of the value of custom field types in a cloud scenario such as Office 365 or an on-premises scenario (without all of the work of doing it the old way).  Notice that I said most of the value.  There are some things that are still not possible and two major caveats of which you must be aware.  First the caveats:

  1. Even though we are building things which look and act like custom field types, we are not technically building custom field types.  We are technically just customizing the rendering and validation of the out of the box field types.  More on this later; just remember it for now
  2. All of our customizations are happening on the client side via JavaScript.  There are implications to this for your data and business rules.  What happens if a user has JavaScript turned off and therefore your customizations do not run?  What are the implications to the security and validity of your data?  We will touch briefly on custom validation later, but just keep it in mind – it’s not guaranteed to run)

Acknowledgements

Before going any further, I need to give credit where credit is due.  Andrew Connell and I hacked up the first portion of this together.  I took the rough POC AC and I had pulled together that almost did everything we wanted, finished it off and cleaned it up to produce the samples in this article.  Keep an eye on AC’s blog as he’ll be posting a follow-up article taking some of this in new directions.

Overview of the Solution

With all of that said, let’s see what it is that we’re going to get at the end of this.  Here are some screenshots and descriptions of what we’re going to build out in the rest of this article:

The New Item Form

In this example, we’ve customized the rendering of our custom field:

image_thumb40


Site Column 1 is our custom field.  Technically, it is just a simple text field.  Without our customizations, it would render as a textbox.  Our customizations change it’s rendering to a dropdown list.

The choices available in the dropdown (One through Five) are added dynamically.  In a real world scenario, these could come from a web service call.  To keep things simple and focused here, I’m simply hardcoding an array.  You’ll see when we get to the code how simple it would be to make this truly dynamic.

We’ve also added some rudimentary validation.  For the sake of this demo, FOUR is not a valid choice:

image_thumb20


(Michael Palin would be so proud)

Notice, too, that our field is marked as required in SharePoint and regular field validation continues to function:

image_thumb38


One of the things I’d like to play with in a later version of this is the possibilities for additional validation via CSOM and perhaps even some event receiver work to provide additional server-side validation.

Display in Views

Once we’ve entered a legal value, our item is shown in a SharePoint View.  We also have the opportunity to customize the rendering here as well:

image_thumb36


For the sake of this demo, I’m not actually showing the field value in the View. Instead, I show a JavaScript link that pops up a simple alert when clicked to show the field value:

image_thumb28

The Display Form

Again, for the sake of this demo, I’m customizing the presentation of our field on the Display form as well.  Instead of showing the actual value, I show it’s numeric equivalent:

image_thumb32

The Edit Form

The Edit form looks largely identical to the New form (internally, it’s actually rendered via the same code).  The only difference is that we have to make sure that the current value of the field shows as selected in the dropdown:

image_thumb34

Technical Walkthrough

Now that we’ve seen what we’re building, let’s dive into how to make it all work.  Once you’ve figured it all out, it’s actually pretty easy.  (Figuring it all out, though, that was a royal PITA, especially during a beta cycle).

The heart of everything we’re doing here is a new property on the out-of-the-box  SPField class (and all of it’s children) within the SharePoint server object model: JSLink (don’t  bother clicking on the link – there is NO documentation worth anything there right now – just a placeholder).  Similar to the JSLink property on SPView, SPField.JSLink gives us the opportunity to specify a custom JavaScript file that will be used to render our field.  Cool.

From our SharePoint 2013 App (or, really, any SharePoint 2013 solution), we add an attribute to the Elements file that defines our custom Field to specify the JSLink value:

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

  <Field

       ID="{23d7e8ae-29c3-4f05-ac4a-08bbf2bc2b1d}"

       Name="SiteColumn1"

       DisplayName="Site Column 1"

       Type="Text"

       Required="TRUE"

       JSLink="~site/Scripts/SampleJSField.js"

       Group="Custom Site Columns">

  </Field>

</Elements>

 

The SampleJSField.js file will now be used to render our field wherever it is used.  The full SampleField.js file is available at the end of this article for your reading pleasure..I’ve added some comments to explain what is going on, but the following sections spell out the highlights

IIFE

Because we are only specifying a JavaScript filename in our JSLink attribute, and not a particular method to be called, we need some way to actually execute our code.  We do this via an IIFE (Immediately Invoked Function Expression) declared right at the top of the file:

(function () {

    initFieldTypes();

    var r = new JSFieldText("SiteColumn1", viewFunc, editFunc, editFunc, displayFunc);

    r.initField()

})();

 

You could do this different ways, but this is the most concise and easiest.  Basically, in one shot, I’m declaring an anonymous JavaScript function and invoking it.  No magic inside the IIFE itself, it simply calls a function to set up our custom field objects (initFieldTypes), creates an instance of my custom JSFieldText object (passing in the field name and a couple of function objects – more on these later) and then initializes the field.

I’m not going to go into details on the whole initFieldTypes function here.  It’s in the full source listing and it’s a bunch of pretty funky JavaScript at this point.  I plan on cleaning this all up but there’s no sense in doing that until I’m working with RTM bits.  Eventually, I’d like to centralize all of this in a common JavaScript library that can be used by multiple fields, but that will come later.  For now, it was enough just to build out a POC to show that this all works.  A good chunk of the  code in the “Global Code” section of the full source listing is based on some code from http://www.ruzee.com/blog/2008/12/javascript-inheritance-via-prototypes-and-closures but I’m not sure whether I’ll stick with that.  It introduces some complexity and I’m not sure it gets me a lot.  In the short term, however, it filled a void and let me focus on more pressing things.

Registering Our Custom Rendering

I will, however, focus on a few key areas within the initFieldTypes function.  The first is where we actually override the default rendering and tell SharePoint to use our custom rendering.  This is done via the initField function on the JSFieldText object:

if (hasValue(this.get_fieldName())) {

      var newCtx = {};

 

      newCtx["Templates"] = {};

      newCtx.Templates["Fields"] = {};

      newCtx.Templates.Fields[this.get_fieldName()] = {};

      //Views are handled slightly differently because of the way they are called by SP

      newCtx.Templates.Fields[this.get_fieldName()]["View"] = hasValue(this.viewCallback) ? this.viewCallback : null;

      newCtx.Templates.Fields[this.get_fieldName()]["NewForm"] = this.renderForNew;

      newCtx.Templates.Fields[this.get_fieldName()]["EditForm"] = this.renderForEdit;

      newCtx.Templates.Fields[this.get_fieldName()]["DisplayForm"] = this.renderForDisplay;

 

      SPClientTemplates.TemplateManager.RegisterTemplateOverrides(newCtx);

}

 

This code sets up an object hierarchy in a manner prescribed by SharePoint 2013 and registers the new functions to render each of our possible views of this field:

  • Views
  • Display Form
  • Edit Form
  • New Form

The last line of the snippet is what actually registers our custom handlers with  SharePoint.

Views are handled slightly differently because of how they are called internally by SharePoint.  For Views, we simply pass the callback that was supplied in the constructor of our field. Note that we do check for null and undefined via some helper functions.  If we set the View or any of the Forms to a null or undefined value, SharePoint will use it’s default rendering.

The Forms all use a function on our JSFieldText object because we need to do a little processing before invoking the callback.

Once the callbacks are registered, they’ll be called by SharePoint instead of the default rendering mechanisms.

One of the things that you’ll notice about all of these callbacks is that we’re not dealing with HTML objects.  In each case, we need to return the actual HTML text to render our desired UI, so we’re doing a lot of string manipulation.  That’s just the way SharePoint expects things to be, so we just run with it.

Technical Details: Views

The View callback is a simple method that modifies the value written into the standard SharePoint View as we saw in the screenshots above.  Here’s the code for that:

/// Function called to render the field in a View

function viewFunc(renderCtx, field, listItem, listSchema) {

    var currentVal = '(null)';

    if (renderCtx != null && renderCtx.CurrentItem != null)

        currentVal = eval('renderCtx.CurrentItem.' + field.Name);

    return "<a href="javascript:alert('This field has a value of: " + currentVal + "')">Show Field Value</a>";

}

 

Notice that the name of our function (viewFunc in this case) was the value passed into our JSFieldText constructor earlier.  The other callbacks operate the same way.  Note also the use of the eval statement in there.  I’m not thrilled with that and would like to find a way around it but haven’t come up with anything yet.

Technical Details: Edit Form

The Edit Form callback is used to render the field on an Edit Form.  Here’s the code for the sample I built:

/// Function called to render the NewForm & EditForm view of the field

function editFunc(renderCtx) {

    var fieldHtml = '<select ';

    fieldHtml += 'id="myNiftySelect" onchange="moveValue('' + this.get_fieldId() + '')">';

    fieldHtml += getSelectOptions(this.get_fieldValue());

    fieldHtml += '"</select>';

    fieldHtml += getStandardInputHtml(this, "hidden");

    return fieldHtml;

}

 

This one is a little more complex than the View, but it is still just building up an HTML string to be returned to SharePoint and ultimately stuffed down the pipe to the client’s browser.  There are a couple of helper functions that you can review in the full source code listing.  In the listing above, all I’m rendering is the select box to present the choices.  The actual field used by SharePoint is handled in the getStandardInputHtml function.  Remember, it renders as a hidden field and I use a simple JavaScript function (moveValue, shown below) to copy the selected value from the dropdown list to the hidden field so it is available to SharePoint.

The moveValue function also handles my custom validation:

function moveValue(targetId) {

    var mySelect = document.getElementById('myNiftySelect')

    var hiddenField = document.getElementById(targetId);

 

    var selectedVal = mySelect.options[mySelect.selectedIndex].text

    if (customValidationPasses(selectedVal)) {

        hiddenField.value = selectedVal;

    }

    else {

        mySelect.selectedIndex = mySelect.selectedIndex - 1;

        selectedVal = mySelect.options[mySelect.selectedIndex].text

        hiddenField.value = selectedVal;

    }

}

 

function customValidationPasses(newValue) {

    if (newValue === "Four") {

        alert("Four is right out!  Counteth thou to THREE and then lobbeth thou the holy handgrenade of Antioch at thy foe, who, being naughty in my sight, shall snuff it.");

        return false;

    }

    return true;

}

There’s a fair amount going on in the editFunc function, but none of it is very complex.  This is another area I’d like to work on tweaking a bit.

As I said before, for the sake of this demo, I have hardcoded in an array to provide the choices for the dropdown:

//keeping it simple for the sake of this demo code - not really calling a service to get values

function getOptionsFromSimulatedWebServiceCall() {

    return ["One", "Two", "Three", "Four", "Five"];

}

 

If you needed to make this dynamic, simply change the code in that method (and probably its name, too) to do whatever you need.

Technical Details: New Form

The New Form rendering is actually handled by the editFunc function.  Notice back in the IIFE when we create the JSFieldText object that we pass editFunc in twice:

var r = new JSFieldText("SiteColumn1", viewFunc, editFunc, editFunc, displayFunc);

The first one is actually the New Form callback.  If you needed to render your field differently on the New Form, simply pass in a unique callback here.

Technical Details: Display Form

Last but not least is the Display Form.  Remember this shows the numeric representation of our field’s value (kind of lame, I know, but I wanted to show something different for each type of rendering and this was the best I could come up with).  The displayFunc function handles this for us:

/// Function called to render the DisplayForm view of the field

function displayFunc(renderCtx) {

    if (renderCtx != null && renderCtx.CurrentFieldValue != null) {

        var fieldVal = renderCtx.CurrentFieldValue.toString();

        switch(fieldVal)

        {

            case "One":

                return "1";

                break;

            case "Two":

                return "2";

                break;

            case "Three":

                return "3";

                break;

            case "Four":

                return "4";

                break;

            default:

                return "5";

        }

    }

    return '';

}

 

The Future’s So Bright…

I’m quite excited about the possibilities being opened up for developers with changes like the JSLink property in SharePoint 2013.  While a number of folks are bemoaning the move to the cloud and the changes that brings, I’m quite bullish on the whole thing.  Sure, there are some things I don’t like, but all in all, as a developer, I’m happy.  At least in the 2013 release, I don’t really lose anything very important for my on-premises deployments and I pick up significant ground in my cloud implementations.  A win all around.

Specifically for custom field types, I see this capability as incredibly powerful.  A nice, easy, standard (and supported) way of customizing the end user experience to be more efficient and friendly opens up a lot of possibilities.  I predict a small segment of the app store will be based around custom fields utilizing this capability.

Conclusion

That’s all there is to this.  As I said at the beginning, with it all laid out and explained, there’s not a lot to this and it is pretty easy.  I think that bodes well for this type of customization in the future.  I plan on spending a lot more time on this once the RTM bits are available.  Once I get it all working and cleaned up, I’ll integrate it into my JavaScript series and probably into a SharePoint 2013 version of the CKS:ScriptLibrary project as well.

Comments and ideas for additional functionality are welcome.  I do realize that a lot of the code in this needs to be cleaned up and like I said, I’ll get to that with the RTM bits.  If you have specific comments about something that doesn’t work, or could be refactored to make this better, I’d specifically like to hear those.

Source File: SampleJSField.js.zip

CKS:API update and AOP

CKS:API is still moving along. It’s a little behind schedule due to work constraints.  Two new developers have joined the project and I’m looking forward to some additional eyeballs on the code to help tighten it up.  I’m also looking into Aspect-Oriented Programming (AOP)  to overcome one of the big hurdles in CKS:API – littering all of that logging code throughout your codebase.  I’m hoping that AOP will work as advertised (I’m using PostSharp, which seems to be the standard for AOP in .Net) and if it does, then parts of CKS:API will be refactored to make this an option.  PostSharp has a free “community” edition so it won’t necessarily shut anyone out.  You’ll still have the option of manually inserting the logging code on your own, so this is not a show-stopper requirement for using CKS:API if we do go that way.

Stay tuned…more details to come…

CKS:API Beta 3 Release Notes

CKS Beta 3 launched this week to go along with my session at the SharePoint Conference.  I really wanted this to be a production-ready 1.0 release and I think it’s close, but I’d like to have feedback from more folks to make sure I haven’t overlooked things.  There’s still some tightening up I’d like to do and a few rough spots in the code but nothing too bad.  I’ll get them cleaned up soon, too.  I’d really like some feedback, though, so please kick the tires and let me know what you think.

What is CKS:API?

CKS:API is a library for use by developers to address the cross-cutting concerns of logging, instrumentation, exception handling and code contract support.  It is a library for use, not a standalone, fully-baked product.  Full source code is available on the Codeplex site: cksapi.codeplex.com

New Functionality

Using CKS:API hasn’t changed much since the beta 2 release.  There have been a few additions that I’ll cover here.  For information on other functionality, please see the beta 2 release notes.  I’ll also include a detailed usage walkthrough here to help you test things out.  But first, the new stuff:

  1. Logging functionality – a couple of new methods have been added to the logging classes:
    • DumpVariablesInDebug/DumpVariablesInRelease: Two similar methods, any calls to the former get removed by the compiler when you compile a Release build so they are not included in your production code.  Feel free to use it liberally.  Calls to the latter are not removed from your production code so they will execute and could slow things down if overused.  Just be careful.  In a nutshell, these two calls allow you to write information about your variables to your log (farm or sandbox) at any point in your code.  See below for a usage example.
    • WriteElapsedTimeStart/WriteElapsedTimeStop: another pair of related methods.  They allow you to log timings for arbitrary events in your code.  You call the first at the beginning of something you want to time and pass in a descriptive name.  You get back an ID.  call the second at the event of the event you want timed and pass in the ID.  The timing information will be written out to the log.
    • Monitor: This new method is related to the above two.  It gives you that ability to record timing information to the log.  The difference is that in Farm solutions, this will use SPMonitoredScope whereas in Sandbox Solutions, this will use the above two methods, since SPMonitoredScope is not available in the Sandbox.  I would expect that this would be used more often, with the above two coming into play only when you need more control or there isn’t an appropriate delegate for your needs). 
    • Sandbox Logging Configuration: You can now control the amount of information written to the sandbox log by setting a property called “CKSAPI_LogLevel” on the RootFolder of the SandboxLoggingList.  The SandBoxLogger checks this property to determine whether to add each entry to the log.  The SandboxTest project includes a rudimentary webpart that allows you to set this value.  I’d like to clean this area up a bit before the final release. It is critically important to use this efficiently to avoid using too many resources in your sandbox solutions.
  2. SPDisposeCheck Integration: I was running SPDisposeCheck against the code previously to check for Dispose problems, but now its fully integrated and I’m using the SPDisposeCheckIgnore attribute as appropriate to avoid false positives.
  3. Office365/SharePoint Online: For the first time with this release I started testing against Office 365.  Previously I was testing only in my local development sandbox.  I started using the Office 365 FxCop tools from Codeplex (http://o365fxcoprules.codeplex.com/) to validate that my code would run in Office 365 and found that there were a few items I needed to change in the code.  I came across a couple of additional situations where Office 365 would choke on the code and I’m working with Kimmo Forss (the author of the rules project) to get my updates included in the Codeplex project.
  4. NotifyAdministrators – it is now possible to create an entry in a separate SharePoint list for events that happen in your processes.  Combine this with SharePoint’s support for alerts/notifications and you now have an easy way to notify administrators (or really anyone) of an event happening in your code that they may need to know about.

Other than that, there was more cleanup and tightening of the code.  As I mentioned, there’s still more to go here.

CKS:API Usage Walkthrough

To begin working with CKS:API there are a couple of steps that you need to take.  I’ve tried to keep these as few as possible. 

  1. Include the CKS:API assemblies in your package so that they get deployed.  The CKSAPI assembly is required for all projects, you’ll also need either CKS.FarmInstrumentation.dll or CKS.SandboxInstrumentation.dll

    image

  2. Add References to the appropriate DLLs in Visual Studio
  3. Now we need to add code to initialize our logging environment.  For all projects, add code similar to the following to a Site Collection scoped Feature:

     image

  4. For Farm Solutions only, add code similar to the following to a Farm-scoped Feature:

    image

  5. Add the following using statements to your code:
    • image 
  6. Now you can start using CKS:API in your code.  See the sections below for details on the various pieces of functionality and how you can use them.

Simple Logging

Writing to the logs for either Sandbox or Farm solutions is simply a matter of making a call to either of the Write overrides:

image

The former is obviously quicker – all you need to do is specify the actual message to be written.  It will written to the log with a category of “General” and a severity of “Information”.

The latter override allows you to specify a category and a severity.  The CKSLoggingCategory enumeration defines 58 different categories currently and you can add more if the ones I’ve provided don’t meet your needs.  Examine the CKSLoggingCategory.cs file for the existing values.  (By adding new items to the enumeration, they will be included in the Central Administration “Manage Diagnostic Logging” facility – more on that later). 

The LoggingSeverity enumeration defines 5 possible values: Information, Timings, Warning, Error, Critical Error.  They are used to control when information is written to logs, according to how the logging is configured in your environment.

Farm logging writes to either the ULS or the WIndows Event Log. Sandbox logging writes to a standard SharePoint list created in the root of the site collection.

Logging in the Sandbox

If you’re working in the Farm, there’s nothing you need to do to prepare for logging.  The above will suffice.  Sandbox logging is a bit different, though.  In order to maintain performance and reduce the Resource impact of running this code in the Sandbox, we batch the sandbox log entries in a List<string> variable and flush them out to the SharePoint list.  In order to support this, we need to tell the logger to begin and end our batch.  We do this with calls to <SandboxLogger>.BeginScope() and <SandboxLogger>.EndScope().  My recommendation is to put these calls in your page/control lifecycle events as opposed to putting them in each method:

image

Instrumentation

Instrumentation sits on top of logging.  Logging is simply a facility for recording data.  Instrumentation is the capturing of data that will be meaningful when analyzing or debugging your code.  CKS:API provides several facilities for supporting instrumentation:

Dumping Variables

When debugging your application, it is often useful to know the values of some variables when an exception happened.  The two methods DumpVariablesInDebug and DumpVariablesInRelease allow us to do this.  See the beginning of this post for the difference between these tow methods.  Using them works exactly the same, though:

image

You make the call to the DumpVariablesInxxx method and pass in a collection of CKSVariableWrapper objects.  The CKSVariableWrapper object allows you to specify:

  • the name of the variable (
  • the current value of the variable
  • (optionally) a string collection of property names on an object variable that you want to dump.

In the code snippet above, we’re dumping three variables: AN SPList, a string and an Int.  For the SPList, we’re explicitly stating that we want to dump out the values of the Title, ItemCount and CanReceiveEMail properties.  For the string and int variables, there are no properties to dump, so we simply dump out the values of these variables.  The end result of this call is:

image

Timings

Another common need when debugging is to know how long certain pieces of my code are taking to run.  While most of the time, we would want to do this with our full Load Tests (and we all do load testing, right?), there are still times when we want to see some basic timing information in regular runs of our code.  CKS:API provides for this.  Begin timing by creating a GUID variable and calling the logger.WriteElapsedTimeStart method.  You pass in a string value that uniquely identifies the particular event/events you want to time.  You get back a unique identifier that identifies this timing instance.  Ending a timing requires you to call logger.WriteElapsedTimeEnd and pass in the GUID you got back previously.  CKS:API will now record the elapsed time between your start call and your end call.

Here’s the code:

image

And here’s the end result in my logger (the ULS log is shown, the sandbox log would be similar):

image

Debug Logging

We’re interested in different information when we’re actively coding and debugging our code than when we’re running that code in production.  We potentially want to see a lot more detail about our running processes than what we want to have logged in production.  However, we don’t want to have to go through and rip out all of that extra logging before compiling a Release build.  Instead, we take advantage of Visual Studio’s conditional compilation functionality to have the code excluded when we compile in Release mode. The following methods make use of this:

  1. Logging Method details: WriteDebugMethodStart and WriteDebugMethodEnd work in conjunction to log when we entered and exited a method.  Using them is simple:

    image

    And results in logging entries like these:

    image

  2. Logging Debug messages: The WriteDebug method allows you to add messages to the log in a Debug build but the call is stripped out in Release build so the code never executes:

    image

One comment about all of the debug methods – it is possible to use the normal Debug.Write calls in Visual Studio to achieve a similar end.  The reason this functionality exists in CKS:API is that it allows you to have all of your logging in one place, along with the out of the box SharePoint log entries (in the case of the Farm logger).  I find that a little easier than having some information in my log and some in the Visual Studio debug window.

Exception Handling

The Exception Handling in CKS:API hasn’t changed at its core, but the approach developers take to it has changed a bit in this release.  Before looking at the developer experience, here’s a quick refresher on the user experience:

Users will either see this:

image

or this:

image

depending on what the developer does.  In the background, a much more detailed error message is written to the logs.

New in this release is that developers can now override the color of the status bar and the text that shows up on the status bar.  If they don’t provide values for them, defaults are used.

Developers can make use of the Exception library in CKS:API as follows:

image

They can catch any type of Exception and process it via this mechanism.  In the initialization code for the CKSExceptionDetails object, the developer can specify:

  • The Display (shown): can be Dialog, StatusBar or None
  • The control that threw the exception
  • The category with which to classify the error – using the CKSLoggingCategory enumeration discussed above
  • The severity of the exception – using the LoggingSeverity enumeration discussed above
  • The StatusBarColor – using the CKSStatusBarColor enumeration
  • The User Text – override the default friendly error message shown to the user.

Code Contracts

CKS:API includes a rudimentary implementation of code contracts. It is not nearly as robust as what is available in .NET4, but it will help get you to start thinking that way.  The implementation of Code Contracts didn’t change in this release.  One thing I would like to do before releasing a 1.0 release is to use the Code Contracts more throughout CKS:API.  Right now, usage is a little spotty.

Code Contracts allow you to explicitly state what your software requires in order to operate properly. For CKS:API, this integrates with the Exception handling functionality to throw a specific error if the contract requirements are not met. This is implemented as a control class along with a bunch of validations, which are implemented as extension methods on various objects in the .Net framework.

In general, using a code contract consists of calling the RequiresThat method of the CodeContract class and supplying a condition to be checked. For example, the following code will ensure that the variable pageName is not null or an empty string:

Contract.RequiresThat(pageName.ValidateHasAValue());

    The comparison is functionally equivalent to

    string.IsNullOrEmpty(pageName)

    but by using the code contract, we also get the exception handling built in as well as opportunities for additional logging if we so desire. Preliminary performance testing indicates that the first usage of a code contract is marginally slower than the equivalent code (due to the loading of the additional assembly?) but subsequent usage in a request incurs no performance hit.

    If the contract is not satisfied, we will get a log entry similar to the following (in a Farm Solution):

    image

    (You would get a similar log entry in a Sandbox solution.) Because we’re using the exception framework in CKS:API, the user sees a nice user-friendly message as we saw previously.

    Currently, the following validations are supported as extensions to specific objects:

    String Double & Float Int
    ValidateHasAValue ValidateIsGreaterThanOrEqualTo ValidateIsOdd
    ValidateIsShorterThanOrEqualTo ValidateIsLessThanOrEqualTo ValidateIsEven
    ValidateIsLongerThanOrEqualTo ValidateIsGreaterThan ValidateIsGreaterThanOrEqualTo
    ValidateIsLongerThan ValidateIsLessThan ValidateIsLessThanOrEqualTo
    ValidateDoesNotContain ValidateIsEqualTo ValidateIsGreaterThan
    ValidateContains ValidateIsNotEqualTo ValidateIsLessThan
    ValidateDoesNotEndWith   ValidateIsEqualTo
    ValidateEndsWith Object ValidateIsNotEqualTo
    ValidateDoesNotBeginWith ValidateIsNotType<T>  
    ValidateBeginsWith ValidateIsType<T> IEnumerable
    ValidateIsExactLength ValidateIsNull ValidateAllAreNotNull
    ValidateIsShorterThan ValidateIsEqualTo ValidateAnyAreNull
    ValidateIsNotExactLength ValidateIsNotEqualTo  
         
    Guid    
    ValidateIsNotEmptyGuid    
    ValidateIsEmptyGuid    

    Question: Each validation currently begins with the prefix “Validation” which makes them easily discoverable, but personally I don’t like what it does to the code readability – it makes the code stilted. What do you think – keep the prefix or drop it?

    There is also a related piece of functionality in the Code Contract part of CKS:API – the ability to simply perform a check of a validation without throwing the error:

    Check.ThatAllAreNotNull(SPContext.Current, myVar, myVar2)

    This makes use of the same contract framework, but instead of throwing an error, it simply returns a boolean true if the check passes, or false if it fails. All of the same validations are supported.

     

    That pretty much closes out the CKS:API Beta 3 Release notes.  I would like to publish a 1.0 production-ready release by the end of October, so please give it a whirl and let me know any feedback – good or bad.

    Feedback

    Remember that this is a beta, but please post any issues to the Issue Tracker on Codeplex, or any questions to the Discussion forum

    Acknowledgements

    Various pieces of the CKS:API functionality would not have been possible if various members of the SharePoint community had not shared their work.  Thanks to the following folks for their help, it really helped me to finalize a couple of the tricky bits, especially related to some of the intricacies of the SPDiagnosticsServiceBase:

    1. Andrew Connell

    2. Todd Carter

    4. Jürgen Bäurle

    5. Andy Burns

    I need to dig up the links to their blogs/articles and will get them posted here in a quick edit soon (I’m trying to get this post pushed out before my SPC session so I’m a little short on time Sad smile ).

    CKS:API Beta 2 Release Notes

    CKS:API Beta 2 is live on codeplex: cksapi.codeplex.com.  This post will serve as the release notes for this release.

    As with the last release, this project is still in BETA.  It is not ready for production use, but it’s getting closer.  This release is *nearly* fully functional, but there’s a lot of cleanup and performance tweaking that still needs to happen.  The plan is to have that all complete and released by early October.

    Call to Action

    If you are interested, I would appreciate some feedback.  Please see the Functionality section below for more information, and please consider downloading the bits from Codeplex and testing things out.  If you come across any bugs, please log them to the Issues list on Codeplex – I’ve added some known bugs already.  If you have questions or ideas, please start a Discussion on Codeplex. 

    If you are interested in helping out, I’ll be ready for assistance after I get this to a v1 release in a few weeks.  Until that time, it would be harder to bring someone else on board and still hit that deadline.  But please feel free to contact me via Codeplex and give me some ideas of where you would like to help out.

     

    Functional Areas

    CKS:API currently consists of the following functionality:

    1. Exception Handling and user-friendly display
    2. Logging (Farm & Sandbox)
    3. Code Contracts

    Each of these will be detailed below.

    CKS:API Design Goals

    One of the primary design goals of CKS:API is to be an example of SharePoint development best practices.  It’s not quite there yet, unfortunately.  One of the drawbacks of “side projects” is that there’s a lot of starting and stopping and not a lot of up-front design.  This project has been refactored MANY times and so there are still some ghosts in the machine waiting to be cleared out.

    Other design goals include:

    1. Simplicity.  If a utility library doesn’t make things easier/better then why bother using it?  CKS:API is intended to make things easier for developers to write high quality applications.  This does not mean that it is simple internally, but it must be simple to use – at least simpler than writing the code manually.  For example, validating that a series of objects are not null could be written as:
      if (null == exception || null == display || null == throwingControl)
      {
           //throw an error
      }

      However, using CKS:API allows you to write this instead:

      Contract.RequiresThat(new List<object>() { exception, display, throwingControl }.ValidateAllAreNotNull());

      Not only is this easier as the number of checks increases, it also gives some context and intention to the code – we’re enforcing a software contract.  The mechanics of throwing the error and maintaining a friendly user experience are hidden from us as there’s no reason for us to have to deal with them every time we want to enforce a contract.

    2. Ease of Use.  If a library places too many requirements on developers before they can even start using it then it is not worth the hassle.  Using CKS:API was  designed to place the smallest number of requirements on the developer as possible.  More details on this are in the Using CKS:API section, but basically it consists of adding the assemblies to your project and your Solution Package and making one method call to prepare the environment.  That’s it.  You’re now ready to start using CKS:API in your projects.
    3. Best Practices.  Yes, I fully realize that this term is so over used as to be almost meaningless, but it is a design goal anyway.  As I mentioned previously, it is not quite there yet, but it is getting there.  What I mean by best practices is simply that the code makes an effort to:
      • be of high quality – there was some thought that went into the code and it wasn’t just tossed together randomly.  This doesn’t mean that every single line is perfect as there are always trade-offs for one thing or another.  It simply means that the code is intentional and the best possible code considering all known situations and trade-offs
      • be consistent – this was a biggie, especially when trying to reconcile sandbox logging and farm logging.  It was important that the experience between the two be as consistent as possible to make things easier for developers.  Sometimes this meant that the implementation details were a bit contrived internally, but the experience for developers is nearly identical whether they are logging to the ULS or to a list (in the case of the sandbox)

    Using CKS:API

    CKS:API is a utility library to be used in other projects. It is not something to be installed to your SharePoint environment by itself. To that end, it does not consist of typical SharePoint Solutions and Features. Why is this? Simple. You don’t install a utility library just for the sake of it – it is just included as part of whatever “real” application you are installing so why should you have to activate a Feature in SharePoint just to make a utility library available?

    Here’s how you would use CKS:API in one of your projects:

    1. Add a reference to the library assemblies in Visual Studio.  There are three assemblies that make up CKS:API:
      1. CKSAPI.dll – (required for all projects).  This is the core library
      2. FarmInstrumentation.dll – required in farm projects
      3. SandboxInstrumentation.dll – required in sandbox projects
    2. Add the assemblies as Additional Assemblies in Package Explorer.
    3. To use logging, instantiate either the CKSFarmInstrumentor or the CKSSandboxInstrumentor object and call it’s InitializeEnvironment method (this should typically be done in your feature receiver)

    That’s it.  You can now start using CKS:API in your projects.  For details on what is available and how to use it, see the Functionality section below.

    The source code includes 2 simple sample projects that can be used as the basis for testing – one for Sandbox and one for Farm.

    Functionality

    There are three main areas of functionality for CKS:API: Exception Handling and user-friendly display, Logging (Farm & Sandbox) and Code Contracts.  Details on each of these are provided here.

    Code Contracts

    First, this is not functionality that is intended to replace or even be compared to what is available in .Net 4.  Conceptually they are similar, but I fully expect to tear this section out of CKS:API once SharePoint can use .Net 4.  In that sense, it is just a stopgap measure to improve the general quality of our code in the short term.

    Code Contracts allow you to explicitly state what your software requires in order to operate properly.  For CKS:API, this integrates with the Exception handling functionality to throw a specific error if the contract requirements are not met.  This is implemented as a control class along with a bunch of validations, which are implemented as extension methods on various objects in the .Net framework. 

    In general, using a code contract consists of calling the RequiresThat method of the CodeContract class and supplying a condition to be checked.  For example, the following code will ensure that the variable pageName is not null or an empty string:

    Contract.RequiresThat(pageName.ValidateHasAValue());

      The comparison is functionally equivalent to

      string.IsNullOrEmpty(pageName)

      but by using the code contract, we also get the exception handling built in as well as opportunities for additional logging if we so desire.  Preliminary performance testing indicates that the first usage of a code contract is marginally slower than the equivalent code (due to the loading of the additional assembly?) but subsequent usage in a request incurs no performance hit.

      If the contract is not satisfied, we will get a log entry similar to the following (in a Farm Solution):

      image

      (You would get a similar log entry in a Sandbox solution.)  Note that there is currently an open issue getting the name of the parameter that failed validation, which is why it shows up as “Unknown.”  Because we’re using the exception framework in CKS:API, the user sees a nice user-friendly message  – more on that later.

      Currently, the following validations are supported as extensions to specific objects:

      String Double & Float Int
      ValidateHasAValue ValidateIsGreaterThanOrEqualTo ValidateIsOdd
      ValidateIsShorterThanOrEqualTo ValidateIsLessThanOrEqualTo ValidateIsEven
      ValidateIsLongerThanOrEqualTo ValidateIsGreaterThan ValidateIsGreaterThanOrEqualTo
      ValidateIsLongerThan ValidateIsLessThan ValidateIsLessThanOrEqualTo
      ValidateDoesNotContain ValidateIsEqualTo ValidateIsGreaterThan
      ValidateContains ValidateIsNotEqualTo ValidateIsLessThan
      ValidateDoesNotEndWith   ValidateIsEqualTo
      ValidateEndsWith Object ValidateIsNotEqualTo
      ValidateDoesNotBeginWith ValidateIsNotType<T>  
      ValidateBeginsWith ValidateIsType<T> IEnumerable
      ValidateIsExactLength ValidateIsNull ValidateAllAreNotNull
      ValidateIsShorterThan ValidateIsEqualTo ValidateAnyAreNull
      ValidateIsNotExactLength ValidateIsNotEqualTo  
           
      Guid    
      ValidateIsNotEmptyGuid    
      ValidateIsEmptyGuid    

      Question: Each validation currently begins with the prefix “Validation” which makes them easily discoverable, but personally I don’t like what it does to the code readability – it makes the code stilted.  What do you think – keep the prefix or drop it?

      There is also a related piece of functionality in the Code Contract part of CKS:API – the ability to simply perform a check of a validation without throwing the error:

      Check.ThatAllAreNotNull(SPContext.Current, myVar, myVar2)

      This makes use of the same contract framework, but instead of throwing an error, it simply returns a boolean.  All of the same validations are supported.

      Exceptions

      CKS:API provides a couple of standard custom errors currently and there are plans to define more.  Right now it supports:

      • CKSException – the base class for all CKS:API exceptions
      • CKSContractException : when a contract is violated
      • CKSInvalidOperationException: when an invalid operation happens
      • CKSValidationException: when a condition check fails validation
      • CKSWrapperException: used to wrap a standard .Net exception to provide a consisten logging and end user experience even when the standard .Net exception classes are used.  This also allows us to support the processing of unhandled exceptions.

      The goal behind the exception handling is to provide detailed information to the administrators and developers while showing a consistent, friendly error message to the end users.

      Depending on how the developer uses the framework, the user will see either a StatusBar message:

      or a dialog box:

      image

      [NOTE: The contents of this user error page are currently hardcoded into CKS:API and are not functional.  I’m not sure that CKS:API will ever implement this and it will likely be left up to anyone using the product to define the error page they want their users to see.]

      In some cases (notably when an unhandled exception occurs, the user sees the same dialog page but in the full browser window instead of the modal dialog box.  If the user click the “Help” link in the StatusBar, they will be shown the dialog box.

      From the developers perspective, things couldn’t be easier:

       try
      {
          throw new CKSInvalidOperationException("oops...something bad happened");
      }
      catch (Exception ex)
      {
          instrumentor.HandleException(ex, ErrorDisplayType.StatusBar, this);
      }

      (instrumentor, in this example, is an instance of a CKSFarmInstrumentor object). 

      Detailed logging information is either written to the ULS log for Farm solutions (as seen above for the Contract) or to a SharePoint list, for Sandbox solutions:

      image

      Notice that the sandbox logger makes use of append-only fields and batches the information written into groups to reduce the number of writes to the SharePoint DB, and therefore the number of resources used.  See below for more details on each logger.

      Handling standard .Net exceptions is identical to handling CKS exceptions – simply call HandleException on your instrumentor and pass in the exception, how you want the information displayed (choices are StatusBar, DialogBox or None) and a reference to the object that threw the error (this).  CKS:API takes over from there and handles it all for you.

      The last piece of functionality in the Exception framework is the handling of otherwise unhandled errors.  If an error happens anywhere in the processing of your page that you do not catch and deal with, instead of seeing a standard error message, the users will be shown the dialog box page (not inside the modal dialog box though).  Note that there are currently a few bugs in this section:

      1. The exception information is not currently logged for unhandled exceptions
      2. Sandbox solutions are not shown any error message.  They simply see their page with no indication that anything happened.  This is better than the standard “an error has occurred in the target of an invocation”  message that users love so much, but not ideal.  Hopefully this will get resolved in the next release.

      Logging

      The last piece of functionality included in CKS:API is a logging framework.  The goal of this piece is to provide a consistent, highly functional logging solution regardless of whether the code is running in the sandbox or in a farm.  To that end, CKS:API provide the following methods:

      • LogError
      • LogInformation
      • LogWarning
      • WriteToDeveloperDashboard
      • LogDebug
      • LogMethodStart
      • LogMethodEnd

      The first three are fairly obvious in what they do.  The last four might need a little explanation:

      • WriteToDeveloperDashboard: writes a message to the Developer Dashboard (duh) in a somewhat more simplified way than what you get out of the box.  In addition to supporting the standard SPMonitoredScope approach (currently only one implementation is included), it also provides the ability to write arbitrary messages to the Dashboard.  This all works for a Farm environment just fine.  What I’m hoping to do is extend the same (or at least similar) functionality to Sandbox solutions as well, something not generally considered possible.  I’ve got a few ideas that I hope to get in place in the next release.
      • LogDebug: Gives the developer the option of writing messages to the log that will only execute when the assembly is compiled as a DEBUG build.  When they compile their project in a RELEASE build, the calls to this method are automatically stripped out.  This means that the developer can go crazy writing debug information into the log while they are developing their code and not have to worry about stripping them out before doing a Release build.  The compiler does it for them by means of the conditional compilation directives available in Visual Studio.  There is exactly zero performance impact to that extra logging because the calls are simply not included in the Release build.
      • LogMethodStart/LogMethodEnd: This is part of that “going crazy” writing debug information into the logs I mentioned earlier.  Adding this call to the beginning/end of your methods will automatically create a log entry with the name of the method and the time.  This can be useful for tracing through your code to uncover nasty little Heisenbugs.  These both make use of the same conditional compilation as LogDebug so there’s no reason to remove these calls from your source code before compiling a RELEASE build. 

      Closing

      That about wraps up the information for beta 2 of CKS:API.  Please take it for a spin and let me know what you think.  Just remember the standard developer disclaimer – this is still a work in progress so no laughing at my code   Smile

      Feedback

      Remember that this is a beta, but please post any issues to the Issue Tracker on Codeplex, or any questions to the Discussion forum

      Future Releases

      I am currently planning the following release schedule:

      • Production-ready 1.0 – October 2011.
      • Bug Fixes 1.1 – 1.9 as needed.

      -Dave

      CKS:API Beta 1 Release Notes

      CKS:API Beta 1 is live on Codeplex: cksapi.codeplex.com.  This post will serve as the Release Notes for the Beta 1 release.

      First and foremost, this is a BETA release.  The project changed considerably between Alpha and Beta and while I don’t expect future releases to include such a massive internal change, there will absolutely be changes to the structure of things.  Furthermore, this is a BETA, it is not ready for prime time.  If you have a few minutes to test it out on your DEV environment and offer some feedback, that would be great.

      Design Goals of CKS:API

      CKS:API is in a large way, a utility library.  It is not something to be installed to your SharePoint environment by itself.  To that end, it does not consist of typical SharePoint Solutions and Features.  It is a collection of assemblies to be included in other projects.  Why is this?  Simple.  It is a utility library at heart and you don’t install anything for utility libraries – they are just included as part of whatever “real” application you are installing.

      This brings me to one of the primary design goals of CKS:API – it does not place requirements upon you as a developer, other than a few simple method calls.  Using CKS:API is as simple as:

      1. Including the assemblies alongside your code – typically this means adding the CKS:API assemblies as “Additional Assemblies” in your Package Explorer:

      package explorer

      2. Make a call to the static Initialize method in CKSAPIUtilities.  (Technically, even this is not required as the code will just process with some defaults, but it is recommended)

      3. Use the functionality of CKS:API as you need.  See the Usage section later in this post for additional information about using CKS:API.

      Another design goal of CKS:API is to demonstrate best practices for SharePoint development, however, it is definitely not there yet.  I have a lot of code cleanup to do.

      Functionality

      For Wave 1, CKS:API consists of the following functionality: logging, exception handling/display and code contracts/validation.

      Logging

      This is basic logging right now.  It will eventually be expanded to include the Event Log, but for now it simply logs to the ULS.  The CKSFarmLoggingService includes the following methods for logging:

      • LogError – write to the logs with a category of “Error”
      • LogInformation– write to the logs with a category of “Information”
      • LogWarning– write to the logs with a category of “Warning”
      • LogCustom – write to the logs with a custom category
      • LogDebug – write to the logs with a category of “Debug.”  Also, this method makes use of Visual Studio’s conditional compilation feature so that any calls to the LogDebug methods are automatically stripped out when you compile a Release build of your project.  This means you can use these methods extensively in your code and not have to worry about them polluting your production code with unnecessary logging or having to go in and remove them all before compiling a release build.

      There is also some preliminary functionality for writing a message to the Developer Dashboard: WriteToDevDash.  This method will change in future releases, it’s really just something I was playing around with for now.  It gives you the ability to write a message to the Developer Dashboard without wrapping your code in a monitored scope.  You don’t get the monitoring capabilities currently, it is literally just a way to write some text out.  I’ll be expanding upon this to add more functionality in future releases.

      Exception Handling/Display

      Exception handling and display is arguably the biggest part of this wave of CKS:API.  The idea behind it is to make it really, really easy for developers to handle exceptions in their code and serve two audiences:

      1. Administrators or other developers, who need detailed error information to be able to troubleshoot
      2. Users, who don’t care about all that detail, they just want to be able to get their jobs done without having to jump through a lot of hoops.

      To this end, CKS:API includes a small collection of custom Exception classes (I’ll add more in the next release, I’m just keeping it small while I work out all the kinks).  Developers can make use of these in a typical try/catch paradigm:

      try
      {
          throw new CKSInvalidOperationException("oops");
      }
      catch (CKSException ex)
      {
          CKSApiUtilities.HandleException(ex, SandboxUtilities.IsInSandbox, ErrorDisplayType.Dialog);
      }

      The end result of this is detailed information being written to the logs:

      image

      but a nice use friendly error being shown to the users:

      image

      A few things to note:

      1. Currently only Farm Solutions are supported, but I anticipate achieving close to full feature parity for Sandbox Solutions
      2. The contents of the dialog box is currently hard coded and non functional.  I’m just trying to show the type of help that can pretty easily be shown to users.  I’m not sure how far the CKS:API project will take this side of things.  I may leave it as simply a framework for developers to extend as they need to.
      3. Notice in the screenshot from the ULS Log Viewer above, that the logging message automatically includes the name of the class and the name of the method that triggered the error.  When I add the Event Log integration, this is what will be written to the Event Log.  I’ll likely add a full stack trace to the ULS at that point.
      4. The last parameter in the HandleException method determines how the error is shown to users, either as a dialog box, as shown above, or simply an entry on the status bar:

      image

      If the user clicks the “Help” link on the Status Bar, they will be shown the dialog box.

      There is some capability to handle non-CKS exceptions in a similar manner.  In other words, the following code would deliver similar results, even though we are not throwing an exception derived from our base CKSException class:

      try
      {
          throw new Exception("Standard .Net Exception");
      }
      catch (Exception ex)
      {
          CKSApiUtilities.HandleException(ex, SandboxUtilities.IsInSandbox);
      }

      Finally, this release includes preliminary support for handling uncaught exceptions.  Adding the following code typically to the Load event of your page or control:

      CKSApiUtilities.CatchUnhandledExceptions();

      will result in, once again, a similar experience.  For example, this code:

      using (SPSite site = new SPSite("http://Invalid.Url"))
      {
          //Do Something
      }

      will still result in the following, even though the error happens outside our code (when SharePoint tries to instantiate an invalid site collection) and is not wrapped in a try/catch:

      image

      Contracts/Validation

      Last but not least is a rudimentary validation framework, which can also be used for something similar to code contracts in .Net.  This is likely best described with some sample code:

      CodeContract.RequiresThat(throwingPage, Validate.IsNotEqualTo, null);
      CodeContract.RequiresThat(myInt, Validate.IsLessThan, 0);
      CodeContract.RequiresThat(myObject, Validate.IsType, SPListItem);
      CodeContract.RequiresThat(myString, Validate.IsExactLength, 17);

      or if not used to ensure method parameters, simply validation:

       Validate.That(head, Validate.IsNotEqualTo, null);

      If any of these fail, then an exception is thrown by the contract/validation framework and handled as outlined above in Exception Handling/Display.  There are two specific exception types that are thrown, either a CKSContractException or a CKSValidationException.

      Usage

      Understanding usage of CKS:API is a bit of a shot in the dark for now.  I plan on addressing that with better test projects in a future release.  For now, you can review this post in more detail, take a look at the source code (specifically the simple web part in the CKSInstrumentationFarmTest project), or post a question on the Codeplex discussion forum for the project.  I monitor the discussions there and will respond as quickly as I can.

      Feedback

      Remember that this is a beta, but please post any issues to the Issue Tracker on Codeplex, or any questions to the Discussion forum

      Future Releases

      I am currently planning the following release schedule:

      Beta 2 (including bug fixes and Sandbox functionality) – early September 2011

      Production-ready 1.0 – October 2011.

      -Dave

      Announcing CKS:API

      Yet another Community Kit for SharePoint project is born…

      This time around we’re focusing on building out a library of functions and frameworks to help standardize and streamline SharePoint development.  The first area we’re covering will be Logging and an Exception Library.  More information will be coming in the next few days and the alpha code release will be posted this weekend, but just to give you an idea of where we’re headed…

      1. Sandbox and Farm logging

      2. Custom exception handling, i.e instead of this:

      image

      making it easy to produce this:

      image

      Stay tuned for more information…