<CharlieDigital/> Programming, Politics, and uhh…pineapples

26Feb/10Off

SharePoint 2010 Mobile Rendering (And Device Emulator Fun!)

Posted by Charles Chen

I was recently tasked with taking an exploratory look at the mobile rendering capabilities of SharePoint 2010 to get a feel for it.  The short of it is that it's sad to say that in 2010 (the year, that is), we are still doing not much better than 3-4 years ago.  Of course, this raises the question of whether it's an issue with the browser or an issue with the software (SharePoint 2010).  Based on my early experience, I have to say it's an issue with 2010 - it seems like the SharePoint team simply took the easy way out.

If you've ever used the Gmail web page from a mobile browser (like Opera), you'll see that there is a "mobile" version and a "basic HTML" version available (links on the bottom).  For all intents and purposes, the "basic HTML" version looks and works pretty much like the full web version (minus the fancy drag/drop stuff, chat, etc.) and loads fine on my nearly two year old HTC Touch Pro.  This is what we should expect from a company as big as Microsoft with vast resources at their disposal.  This is what we should expect from them given that it's 2010 and the mobile space is an increasingly bigger piece of the pie. 

What's worse is that there's no apparent way from the browser client to access the "full view".  What happens when more capable mobile browsers are deployed that can match the capabilities of the current desktop browsers?  Seems like you'll have to make configuration changes on the server to enable proper browser detection but it would be much easier to simply have the option, like on mobile Amazon.com, to load the full view in lieu of Microsoft actually offering a more usable "basic HTML" view.

Alas, instead, we get neutered functionality and weak rendering to mobile browsers for a product that's supposed to carry us to 2013 or 2014.

The following screenshots are taken using my desktop IE8, Microsoft's Windows Mobile 6.1.4 emulator, and RIM's Blackberry 9630 emulator:

Landing Page

List View

Calendar View

New Event

In analysis, I think what makes matters worse is that they've dramatically increased the capabilities of the desktop browser version, but neglected to carry forward some of the basic functionality that seems like it wouldn't be too had to implement like the ratings or tagging functionality.  This discrepancy makes the shortcomings of the mobile offering all the more apparent.

Certainly, I'm not expecting that the desktop experience to be fully emulated on a mobile device, knowing the limitations of the small screens and limited resources and capabilities of mobile browsers.  That said, I would expect a more worthy effort than this.  I would expect something similar to Gmail's "basic HTML" option and a link to the full version.  It's an embarassment, especially the new event screen; at the least, the developers could have aligned the fields (it's pretty offensive).

It's just sloppy and lazy all around and I suggest Microsoft spend some time with the mobile browsers from their competitors.  People are accustomed to a certain level of mobile browser capabilities these days and it's nowhere near as low as Microsoft would like to believe.

For comparison's sake, here's Gmail's rendering in "mobile" and "basic HTML" mode:

Gmail desktop browser, "mobile", and "basic HTML" rendering

This is much more usable and a much more congruous experience across platforms.  Come on Microsoft, stop being lazy!  As Mark Jackson would say "You're better than that!"

On a side note, working with the emulators was a bit challenging.  If you'd like to try it out for yourself, here are some resources:

Mobile IE 6

Blackberry Devices

My experience is that working with the Blackberry emulator is extremely frustrating because you'll want to click on the screen with your mouse but then you remember that the devices don't support touch so it would only be logical that the emulator doesn't either.  However, this logic leads to a hair-pulling experience when working with the emulator.

19Feb/10Off

FluentNHibernate And NHibernate.Linq

Posted by Charles Chen

Just a little blurb on FluentNHibernate and NHibernate.Linq.

I've been working through the samples for FNH and decided to try out some different query scenarios to see how the queries would be generated. I stumbled a bit on the first rather simple scenario: selecting an item based on the total count of related items. In this case, from the FNH demo, I wanted to select "all stores with more than 2 employees". Seems like a simple enough query, right?

You can see from the full code that this should return "Bargain Basement". However, in going through the documentation, it wasn't exactly apparent how this could be done; it seemed a lot more convoluted than necessary using criteria queries and it simply wasn't working. Via Google, I came across a blog post that mentioned using either DetachedCriteria or HQL. Quite frankly, neither was very appealing.

So I figured I'd download NHibernate.Linq and see if it would be better. Not knowing what I would get, SQL-wise, I wrote the following query:

using (session.BeginTransaction())
{
    IQueryable<Store> stores = from s in session.Linq<Store>()
                               where s.Staff.Count > 2
                               select s;
 
    foreach (Store store in stores)
    {
        Console.WriteLine("STORE: {0}", store.Name);
    }
}

Of course, the interesting question is whether the the Staff list would be loaded to perform the count and to my pleasant surprise, it was not. Here's the query in profiler (reformatted for legibility):

exec sp_executesql N'
    SELECT 
        this_.Id as Id1_0_, 
        this_.Name as Name1_0_ 
    FROM 
        [Store] this_ 
    WHERE 
        @p0 <   (
                SELECT 
                    count(staff1_.Id) as y0_ 
                FROM [Store] this_0_ 
                    left outer join [Employee] staff1_ 
                        on this_0_.Id=staff1_.Store_id 
                WHERE 
                    this_.Id = this_0_.Id
                )',N'@p0 int',@p0=2

Sweet! The framework correctly builds a sub-select query to count the staff members.

I guess I'm just easy to impress :-) but I'm digging it.

I think what I like about FluentNHibernate the most is that I can stop building database applications. What I mean by this is an application built from the database up. The main issue this raises is complexity with regards to mapping to a data layer and of course continuously having to synchronize your DDL and SQL with your class files. The following code configures the database, including dropping and creating the tables based on mapping classes in my assemblies:

private static ISessionFactory CreateSessionFactory()
{
    return Fluently.Configure()
        .Database(
        MsSqlConfiguration.MsSql2008.ConnectionString(
            @"Data Source=SCOOBY;Initial Catalog=FluentNHDemo;
            Integrated Security=SSPI;Application Name='FNHDemo'"))
        .Mappings(m =>
                  m.FluentMappings.AddFromAssemblyOf<Store>())
        .ExposeConfiguration(BuildSchema)
        .BuildSessionFactory();
}
 

private static void BuildSchema(Configuration config)
{
    // this NHibernate tool takes a configuration (with mapping info in)
    // and exports a database schema from it
    SchemaExport schema = new SchemaExport(config);

    schema.Drop(false, true); // Drops the tables only.
    schema.Create(false, true);
}

With no mapping files to speak of, persistence plumbing becomes trivial and I can work entirely within Visual Studio. Of course, for complex queries and queries that need to be highly performant, you may still be better off writing stored procedures (as I've advocated in the past), but the productivity gains to be had can't be ignored and I find the compile-time validation of the queries eases some of my indifference towards dynamic SQL.

Filed under: .Net, Dev 1 Comment
16Feb/10Off

Cloud Hype Rant

Posted by Charles Chen

A few years ago, I read an excellent article in Wired magazine titled "The Thin Pill":

"FOR PATIENTS, disease puts a name to an affliction. It answers that question we all face at one time or another: What's the matter with me? If there is a clear and precise explanation for what's wrong, then surely there is an equally clear way to get better."

"Cunningham is among the first wave of Americans to be diagnosed with metabolic syndrome, a condition that, though only concretely defined five years ago, is now said to afflict as many as 75 million Americans...Metabolic syndrome is, in fact, almost indistinguishable from obesity – at least 85 percent of those who have the syndrome are obese or overweight.
"The tidiness of that correlation makes it tempting to view metabolic syndrome not as an emerging fact of medicine, but as a fiction, wholly devised and disseminated by the pharmaceutical industry. After all, drug companies have long eyed obesity as the ultimate growth market -- and they just happen to have an arsenal of pills poised to target it."

I see some parallels in all of this cloud hype: The diagnosis is that your enterprise is spending too much on capital outlays for hardware; the cure is to pay a subscription fee to us services providers instead!

In an InfoWorld article, David Linthicum has a great bit from Miko Matumura:

Miko is referring to the fact that "cloud," as a term and a symbol, has long referred to portions of the architecture you didn't want to explain. As Miko says, "Basically whenever someone didn't feel like drawing all of the network entities, they would just draw a puffy white cloud. In essence the puffy white cloud is shorthand for 'don't worry your pretty little head about this stuff.'" He's right about that, and also the fact that many considered "clouds" to be where the "miracle" occurs in the architecture. That was a running joke for years.

While it's told as a joke, I find this to be incredibly reflective of what I encounter when it comes to the cloud and non-techies: it's supposed to be some miracle pill that fixes all of our problems; don't worry about the composition, just take it and trust us, you'll feel better.  And it is exactly this foggy perspective that is cluttering this space with hype.

(With Matumura's anecdote in mind it's hard to ignore the parallels of the hype of this movement with the hype and mass shift towards outsourcing a few years ago: take your development and technical resources and make it an abstract, "puffy white cloud"...that's a topic for another rant.)

What makes the matter all the worse is that the term cloud computing is as nebulous as the name implies.  Jon Brodkin at NetworkWorld.com writes:

I just performed a quick search of the archives on PRNewswire, and found 204 press releases mentioning the word “cloud” from the past 30 days. My e-mail inbox is full of cloud pitches, some of them useful, some of them not. A company called 3tera claims on the front page of its Web site to offer “the industry’s only cloud computing platform.” Really? It’s the only one?

Other vendors are trying to confuse the definitions of the various types of cloud computing. The phrase “private cloud” seemed strange at first, but by now most people agree that it refers to some kind of highly virtualized, internal network with lots of self-service attributes, essentially an Amazon-like cloud designed by a business for its own users.
One of the key attributes of a private cloud is that it’s run within your network – it’s not outsourced. But that didn’t stop Rackspace from claiming that it now offers “private clouds,” hosted in the Rackspace infrastructure. In other words, Rackspace is offering hosted data center services, similar to what they have always offered, and are now using the phrase “private cloud” to make them seem different and new.

Quite honestly, I'm sick of the hype and the excessive overusage of the term "cloud".  Are there tangible benefits to cloud-style application architecture?  Sure, you bet.  But I think it's important to sit back with a healthy dose of skepticism and evaluate how much of what's out there is hype and how much of what's out there is actually useful and cost effective.

With specific regards to Microsoft's Azure, the time I spent with it was anything but pleasant: the documentation was lacking, the account and service management web interfaces were horrible and clunky, and the community knowledge is simply a void (but admittedly, this was early in the beta).  As I've seen with SharePoint, Microsoft has a habit of over-selling and under-delivering.  With two successive clients, I've found a consistent pattern of being sold a capability as "out-of-the-box" only to find that while you could do it, out-of-the-box, it would hardly be a productive or friendly user experience to do it that way.  My perspective is that as the current state of the platform comes into focus, it'll play out much the same way and we'll find that business folks, sales folks, CEOs, and CTOs will have to face the reality of an immature platform that's not yet worthy of the hype.

At least from my perspective, it's always better to under-sell and over-deliver; whether it's the fault of the vendors or not, the current hype is leading us down the opposite path, at least in the near term.

Filed under: Rants No Comments
12Feb/10Off

My Grapefruit Addiction

Posted by Charles Chen

Ever since I discovered that I could actually cut out grapefruit wedges (I lived for some 25 years before I discovered this fact!), I've been addicted to the tangy, juicy globes of goodness.  Half the fun is playing with sharp knives; half the fun is the tasty, tasty reward.  As a bonus, eating grapefruit allows you to bask in your manly skills.

Here's a guide to help you get your grapefruit addiction on:

Step 1: Take off the rind with a sharp knife

Step 2: Cut out the wedges (hat and scarf optional; happy face: mandatory!)

Step 2a: Check out that skill and precision!

Step 3: Squeeze the juice from the membranes (only manly men need apply)

Step 4: Squeeze the juice from the rinds

Step 5: Victory!

Did you know that Texas is one of the largest producers of Ruby Red grapefruits?  As a grapefruit loving Liberal, I'm highly conflicted by this!  Well, at least they're good for something; we can't let them secede just yet!

11Feb/10Off

Google Buzz > Facebook

Posted by Charles Chen

Well, at least for me (and I suspect many others).


I caught Pete Cashmore's analysis:



There are arguably better video sites than YouTube and better photo hosts than Photobucket, but network effects tend to trump technical prowess in the social networking realm.


Google Buzz certainly isn't groundbreaking, but it will achieve critical mass virtually overnight. Thanks to integration with Gmail, the new tool is in the eye-line of the millions of users who obsessively check their inboxes for new mail. ComScore pegged Gmail at 176.5 million unique visitors in December.


But I think he just narrowly missed the mark, at least for me.  One critical difference is that because Buzz relies on your Gmail contacts, it creates a more focused social network; in other words, these are people that you actually communicate with already and thus content in Buzz seems to be much more relevant and interesting than Facebook.


Consider someone like my sister.  She has 643 friends in Facebook.  The question is what % of those people does she actually communicate with on a daily or even weekly basis?  How many of those people are just incidental contacts?  How many of those people are just sort of there? How many of those people does she actually care about?  How many of those people would invite her to their wedding?  I would guess that it's somewhere around 10-20%.


By integrating with Gmail, Google's big win is that your network is based on people that you actually communicate with.  In my opinion, this makes the social network more valuable and the information much more relevant.  Integration with a mail client will help the adoption rates for sure, but I think that the big win that will carry it forward as a success -- at least for users like me, who don't use Facebook as a network building or discovery tool -- is that the quality of content is much improved over Facebook.

5Feb/10Off

Paging With SPListItemCollectionPosition

Posted by Charles Chen

Update: see this post for how to use paging to improve retrieval of large data sets.

Let it be known that Microsoft's terrible design of list paging is inexecusable and to make matters worse, the documentation is practically non-existent. You would think that paging with a SPQuery would be a piece of cake! I mean, I write paged data queries all the time.

NOT!

Colby Africa has a good overview of the issues and some basics that gave me some good insight into the core issues. Of course, the difficulty with the SPQuery and paging isn't really with going forward, it's with going backwards. One MSDN poster suggested storing the previous pages (see the last post here), which when you think about it, isn't a really good solution given the amount of paging strings you'd have to store (you can't just store the last navigation since going "Previous" twice requires going back twice).

Since going forward is the easy part, I won't get into that. With regards to paging to previous pages, I hacked around a bit and spent a good 2-3 hours trying to deduce how the paging query string worked before I finally figured it out.

The algorithm works like so:

  1. When paging FORWARD, capture the ID <AND SORT FIELD VALUE> of the first item on the newly retrieved result collection.
  2. When paging BACKWARDS, use the previously captured ID <AND SORT FIELD VALUE> of the first item on the current result collection to generate the paging string.
  3. Once paged BACKWARDS, capture the ID <AND SORT FIELD VALUE> of the first item on the loaded page for the next BACKWARDS operation (just leave this off of the input query if going forwards again).

By capture, I mean to store the data and persist the data somehow (perhaps in the ViewState or SessionState).

And there you have it: three simple steps :-D

As an example, consider the following data set, sorted by Title:

ID		TITLE
---------------------------PAGE 1
17		Apple
21		Banana
18		Currant
---------------------------PAGE 2
19		Durian
5		Elderberry
1		Fig
---------------------------PAGE 3
7		Guava
10		Honey Dew
12		Indian Gooseberry

Consider a scenario where we're building a web application. After the result set for page 3 of the data is loaded, I want to capture three pieces of data if I want to be able to load the previous page:

  1. The value of the ID of the FIRST item on the page
  2. The value of the TITLE of the FIRST item on the page (or whatever field you are sorting on)
  3. The PagingInfo string after the query is executed

The PagingInfo is already set for paging foward again. When I page backwards, I will need to generate a new query using the PagingInfo. To do so, I will need to:

  1. Replace the p_ID and set it to p_ID=7
  2. Replace the p_Title and set it to p_Title=Guava (replace p_Title with the static name of your sort field)
  3. Add two parameters:
    1. PagedPrev=TRUE
    2. PageLastRow=6 (last index of the second page, where we're going - this is easily calculated if you know your page size and your current page (keep these in the ViewState))

I used the following two regular expression patterns:

Regex _pidPattern = new Regex("p_ID=(?'pid'\\d+)");
Regex _pTitlePattern = new Regex("p_Title=[^&]+");

To replace the values in the string like so:

pagingInfo = _pidPattern.Replace(pagingInfo,
	string.Format("p_ID={0}", firstItemId));
pagingInfo = _pTitlePattern.Replace(pagingInfo,
	string.Format("p_Title={0}", firstTitle));

In this case, if I'm on page 3, the string for going back to page 2 should be:

Paged=TRUE&PagedPrev=TRUE&p_ID=7&p_Title=Guava&PageLastRow=6

And once I'm on page 2, the string required to go back to page 1 should be:

Paged=TRUE&PagedPrev=TRUE&p_ID=19&p_Title=Durian&PageLastRow=3

Well, actually, you don't need the string to go back to page 1; but this is just to give you the general idea. In summary, the trick is pretty simple: you always need to store the PageInfo string for paging SharePoint queries and when you retrieve a resultset, you want to capture the ID and sort field of the first item. When you go forward, the PageInfo string is enough. When you go backwards, you need to use the captured pieces of info.

Hope that this has shed some light on the otherwise nebulous paging functionality with SharePoint list queries!

Filed under: .Net, Dev, SharePoint 2 Comments