Wednesday, February 13, 2008
I have to say SharePoint just continues to underwhelm me (as a developer, I don't mind the product itself I should probably make that clear)...

A couple of quick examples:

Configuration over Convention

Regional settings and dates are a prime example - for instance you get a <SharePoint:DateTimeControl /> which brings with it a common look and feel for date pickers in SharePoint... and on the various pre-canned forms etc. everything appears to display with the current user/sites regional settings. 

However whenever you use this control you end up resorting to code along the lines of:

SPRegionalSettings regionalSettings = SPContext.Current.Web.CurrentUser.RegionalSettings ?? SPContext.Current.Web.RegionalSettings;

myDatePickerControl.LocaleId = (int)regionalSettings.LocaleId;


Or extending your control yourself to do the same... why on earth would I not want the control to default to the current regional settings?

Again the lack of convention rears it's ugly head when working with SharePoint's SPGridView - if it's going to a render a date, why doesn't it render it with the current user's Locale in mind (which I've talked about in this hack last year) - shouldn't these controls be taking that burden of responsibility away from me?

Useless Extensions Points

When something is extensible in SharePoint, then generally:

  1. It's not documented (except by the community)
  2. It doesn't really work for the most common scenario.

Take the SPGridView and SPDataSource combo - with this you can setup a grid to feed from a CAML query pretty easily ... and it's smart enough to add the required <OrderBy/> to the underlying CAML query when you sort on a column... so far so good.

But what if you want to sort on more then one column?

Well, you could try specifying more then one column in the grid's SortExpression - but this causes the SPDataSource to spit the dummy... so obviously the first question is why doesn't that work, when it works for other data sources, and would have been trivial to implement.

But not all hope is lost after opening reflector and perusing the code (which thankfully wasn't obfuscated in this case, though quite a bit of it is) you see that in fact you can specify additional sort columns in the original query and the SPDataSource is smart enough to keep them and insert the new field references into the existing <OrderBy/>... a handy way for extending your query to have a number of default sort columns.

But there's a catch, it sticks the entries in the wrong position, so it will sort by the fixed columns first - rather then last - making it all but useless in most cases (users expect to click on a column and see the results sorted by the selected column first) .. And to be honest this still wouldn't worry me if I was given at least one virtual method to override allowing me to mutate the CAML query appropriately.

posted @ Tuesday, February 12, 2008 8:28:02 PM (New Zealand Daylight Time, UTC+13:00)    Comments [2] | Trackback |
 Tuesday, November 20, 2007
I've had a few people trying to use the replacement New/Edit list form hack I posted a week or two ago, and struggling to get the correct set of fields to display so I've written a couple of followup wiki entries:
Hopefully these will prove useful for anyone trying to make use of these hacks, and provide enough hints to implement something functional with the code snippets.




posted @ Monday, November 19, 2007 7:36:08 PM (New Zealand Daylight Time, UTC+13:00)    Comments [0] | Trackback |
 Monday, November 12, 2007
So first off... for those who don't know SharePoint... CAML is a bit of swiss army knife... if you understand it, can stand it, and know where to stick it you can pull off some interesting and useful results with SharePoint... I'm no expert however, having only touched it for querying and tweaking it here and there for some custom views. Though I think I can confidently say CAML is a wonderful example of XML Abuse :)

At any rate, one aspect of CAML is being able to write CAML queries to query data sources i.e. SharePoint Lists.... I'm against constructing strings for querying data sources, because they're ugly - and difficult to mutate with code, so I decided to give CAML.Net a try (and ended up using it, albeit reluctantly) - here's an example query in CAML:

<Where>

    <Or>

        <Eq>

            <FieldRef Name="ContentType" />

            <Value Type="Text">My Content Type</Value>

        </Eq>

        <IsNull>

            <FieldRef Name="Description" />

        </IsNull>

    </Or>

</Where>


And then in CAML.Net - at first glance it looks ok:

Console.WriteLine(CAML.Where(

                      CAML.Or(

                          CAML.Eq(

                              CAML.FieldRef("ContentType"),

                              CAML.Value("My Content Type")),

                          CAML.IsNull(

                              CAML.FieldRef("Description")))));


But of course then you look a little closer and see that CAML.Where, CAML.Or, CAML.Eq etc. all return strings... so your not actually building a model of your query - which to me immediately removes a large part of the value for this solution.

Looking around the blog-sphere I see lots of people using CAML.Net, and yet nobody seems to have a problem with the way it works?... it puzzles me... At any rate.. let's dive into why I don't like this approach... with another example:

Console.WriteLine(CAML.Where(

                      CAML.Or(

                          CAML.Eq(

                              CAML.FieldRef("Title"),

                              CAML.Value("My Title")),

                          CAML.Or(

                              CAML.Eq(

                                  CAML.FieldRef("ContentType"),

                                  CAML.Value("My Content Type")),

                              CAML.IsNull(

                                  CAML.FieldRef("Description"))))));


And here's the CAML for that:

<Where>

    <Or>

        <Eq>

            <FieldRef Name="Title" />

            <Value Type="Text">My Title</Value>

        </Eq>

        <Or>

            <Eq>

                <FieldRef Name="ContentType" />

                <Value Type="Text">My Content Type</Value>

            </Eq>

            <IsNull>

                <FieldRef Name="Description" />

            </IsNull>

        </Or>

    </Or>

</Where>


Notice the Or inside an Or... this is direct feedback from the CAML query language itself - notably that you can't construct a query with multiple root-level criteria, so your left to construct a tree of Or and And's as required to represent your query - which is ugly, and ultimately confusing - it doesn't express intent well... So my first problem with the CAML.Net approach is it makes me aware of the problems in CAML, when they could've been abstracted away for me... now let's look at a reasonably dynamic CAML query.

string title = "My Title";

string contentType = "My Content Type";

 

List<string> orFragments = new List<string>();

 

if (!string.IsNullOrEmpty(title))

{

    orFragments.Add(CAML.Eq(

                        CAML.FieldRef("Title"),

                        CAML.Value(title)));

}

 

if (!string.IsNullOrEmpty(contentType))

{

    orFragments.Add(CAML.Eq(

                        CAML.FieldRef("ContentType"),

                        CAML.Value(contentType)));

}

 

orFragments.Add(CAML.IsNull(CAML.FieldRef("Description")));

 

string query = CAML.Where(

    OrCamlRange(orFragments.ToArray()));


And suddenly I'm forced into a world of pain - having to manage the various criteria myself, and strings no less - in this case I'm only using Or's - so I can use a little function to stitch everything into a valid query:

private static string OrCamlRange(string[] items)

{

    if ((items == null) || (items.Length < 1)) throw new ArgumentNullException("items");

    if (items.Length == 1) return items[0];

 

    string[] remainingItems = new string[items.Length - 1];

    Array.Copy(items, 1, remainingItems, 0, remainingItems.Length);

 

    return CAML.Or(items[0], OrCamlRange(remainingItems));

}


But I can't help feeling that an opportunity for CAML.Net to really shine has been tarnished by an initial design choice of returning strings, instead of models.  At least for my use cases, I would've been much happier with something that returned a model which I could post-parse - to smarten up the experience so I could identify misspelled fields, mutate the query based on user choices etc.

Finally, just to be clear - this is not a dig at John Holliday - CAML.Net's author, he's a smart guy who knows a lot more then I ever will about SharePoint!  It's merely an opinion/observation on the negatives of query building approaches which don't embrace an intermediate model which can be parsed or mutated.



posted @ Sunday, November 11, 2007 9:40:34 PM (New Zealand Daylight Time, UTC+13:00)    Comments [0] | Trackback |
 Saturday, November 10, 2007

Here are some more SharePoint hacks (continuing on from my last post here)

First off some hacks for the SPGridView which is actually a pretty useful control, but fails to do a few things, like displaying attachment columns as-per SharePoint's default List views (with a little paper-clip symbol), and the second (and much more annoying) it doesn't use the current users regional settings / timezone for formatting DateTime values.

The hacks:
And finally support for a ListForm replacement web part - after trying to customize the ListForm to suit a customers requirements by creating a CustomListForm in SharePoint designer I gave up in disgust because it's just too limited in what it lets you achieve, and worst of all, it breaks attachments support!  So I wrote a small web part to replace it, which allows for fine-grained control of visibility and editability (if that's even a word) of each field, and as an added bonus it doesn't break the attachments functionality.  I also wanted to add additional links/buttons to the form which triggered a save including validation etc. - so I did a little hack to implement that as well.
I might have a few more to post before the end of the project - but it's almost wrapped up, so these may be the last for a while.

Hopefully someone out there finds them useful.
posted @ Friday, November 09, 2007 9:38:26 PM (New Zealand Daylight Time, UTC+13:00)    Comments [8] | Trackback |
 Wednesday, November 07, 2007
I've been working with SharePoint lately, it's a technology of highs and lows... the highs are when you've finally got something to work that should've worked in the first place, the lows are well... all the times in between.

Ok, so that sounds cynical - SharePoint is actually quite a cool product - there's a lot of good in there... stuff that would take you a while to write yourself... but it just tends to drive you a bit crazy, things that look easy from a distance become hard to achieve because of poor documentation, lack of extension points and the difficulty in building testable code.

At any rate, while on this project I've been compiling a list of hacks that other people may find useful, which I used to solve a few of the problems I was hitting while developing... here are the first few:
There are some more coming shortly.
posted @ Wednesday, November 07, 2007 12:04:46 AM (New Zealand Daylight Time, UTC+13:00)    Comments [2] | Trackback |
Search
FeedCount

Tags...
Who am I?
Alex Henderson
Alex Henderson
Auckland, New Zealand
Managing Director at Dev|Defined Limited

"Self Confessed Coding Junky for 15 years"
View Alex Henderson's profile on LinkedIn
 
Mobile: +64-21-402-969
Email: bittercoder 'at' gmail 'dot' com
MSN: bittercoder_nz@hotmail
Skype: alex.devdefined
Navigation