Interesting iPhone Application

image The mobile team here at Slalom has developed a really cool iPad application that combines virtual reality augmentation w/ offline capability to provide what may be the best New York subway finder and routing app available today.

Here’s the site describing the app in more detail: http://www.nycstationfinder.com/.

I don’t have any Apple products so I can’t test it out myself, but it looks pretty cool. I’m hoping they port it over to Android soon.

</end>

Subscribe to my blog.

Follow me on Twitter at http://www.twitter.com/pagalvin

MVP Again

Microsoft re-awarded me with SharePoint MVP on July 1st this year and it’s no less exciting than it was the first time four years ago.

The SharePoint community is just an amazing place.  I remember when I was first introduced to SharePoint by my old employer, Conchango.  I was not happy about it Smile.  I had been living in a BizTalk world for a year or two leading up to my job there and before that, worked in another insular world of people and companies that made a living off of Progress Software.  I say “insular” because the SharePoint world is anything but!

I’m continually glad and excited to be part of this bizarre online community of people that feel strangely compelled to blog endlessly, give up their Saturdays for free conferences, haunt online forums, build all kinds of whacked out free products to put up on CodePlex and a myriad of other community efforts of all shapes and sizes. 

I don’t know what it is about this product that inspires such volunteerism and immersion, but I hope it never changes.

</end>

Subscribe to my blog.

Follow me on Twitter at http://www.twitter.com/pagalvin

Let Shining Examples Lead the Way to Increased SharePoint Adoption

My first “pure” BrightStarr blog entry was published today.  Here’s a teaser:

There’s been a lot of conversation on the Internets of late on the topic of SharePoint adoption and especially the lack thereof. No one wants to go to all the trouble of designing a farm and security infrastructure, participating in workshops, putting together a snazzy look and feel, working out a rock solid information architecture that can withstand the vicissitudes of company re-orgs and finally, a fanfare-filled rollout just to discover three months post go-live that less than 50% of the company employees are using SharePoint and most of them are using it to replace the old network file servers ("the S:\ drive").

No silver bullet (or single blog post) is going to solve that problem. However, there are lot of things you can do to reduce the risk of an anemic SharePoint portal. One such technique is the "Shining Example Pattern."

I’d love to know about other SharePoint adoption strategies that you care to share.  If you do share, please leave as a comment on the BrightStarr blog.

Read the whole thing here: http://www.brightstarr.com/US/Pages/blog-view.aspx?BlogID=52

</end>

Subscribe to my blog.

Follow me on Twitter at http://www.twitter.com/pagalvin

“Access Denied” to Default.aspx on a SharePoint 2010 Sub Site

One of my clients went live with their SharePoint 2010 environment today.  We discovered that a certain group of users couldn’t access their default home page.  SharePoint responded with “Access Denied” and the usual “sign in as another user” or “request access” response. 

When we used the nifty “Check Access” function it confirmed that the end users really did have access.  Yet, they could not get to the page.

I followed a lot of roads to various dead ends until I decided to compare the web parts on the broken page against a similar working page.  I did that by putting the page in maintenance mode by adding “?contents=1” to the page. So, it looked like “http://server/subsite/subsite/default.aspx?contents=1”. 

This showed me two web parts named “Error” with a description like “Error” on the broken page.  I didn’t think to take a screen cap at the time.

I removed them and that solved the problem.

I’ve seen a question like this come up on the forums in the past and I was extremely skeptical about the poster’s insistence that he had security set up properly.  I *know* I had security set up right Smile  Next time, I’ll be more open and less skeptical.

</end>

Subscribe to my blog.

Follow me on Twitter at http://www.twitter.com/pagalvin

XSLT and jQuery Samples

I have been doing a lot of of XSLT and jQuery and thought I’d share a few snippets that others may find useful in future.

Example 1: Emit simple JavaScript / jQuery in XSLT:

<xsl:template match="something" xml:space="preserve">

  <!– Blank out the query friendly filters hidden field –>
  <script type="text/javascript">
    $(document).ready(function(){
      $("#QueryFriendlyFilters").val("empty");
    });
  </script>

</xsl:template>

That bit emits some JavaScript that waits for the page to finish loading (because of the $(document).ready(…)) and then sets the value of a hidden field named QueryFriendlyFilters to the literal value “empty”.

Example 2: Use <xsl:if> to check “greater than”,  “less than”, etc.

<xsl:template match="something" xml:space="preserve">

  <div id="fdcAllFilters">
 
    <xsl:if test="@Count>0">
      <span class="fdcFilterLabel">Current filters:</span>
    </xsl:if>

    <!– more stuff happens here. –>

</xsl:template>

The above snippet checks to see if an attribute named “Count” of the “something” element is greater than zero.  The XML behind this would be something like:”

<something Count=”5” />

Example 3: Iterate through all elements, interspersing jQuery calls.

<!– Iterate through all the filters and display the correct  links. –>
<xsl:for-each select="UserFilter">

  <a class="FilterHref" href="javascript:mySubmitPage(‘RemoveUserFilter’,'{@ID}’)">[X]</a>

  <span class="fdcFilterLabel"><xsl:value-of select="@FilterValue"/></span>

  <script type="text/javascript">

    $(document).ready(function(){
        <xsl:text><![CDATA[$("#QueryFriendlyFilters").val( ($("#QueryFriendlyFilters").val() + " ]]></xsl:text>\"<xsl:value-of select="@FilterValue"/>\"<xsl:text><![CDATA["));]]></xsl:text>
    });

  </script>

</xsl:for-each>

The above snippet is the most complex and there may be easier ways to do it.

The XML behind this looks roughly like this:

<UserFilter ID=”123” FilterValue=”xyzzy” />

This snippet is iterating through <UserFilter> nodes. 

It first emits an anchor tag that when clicked invokes a JavaScript function that is already on the page, “mySubmitPage” and passes the value of an attribute on the <UserFilter> node named “ID”. 

It then emits some jQuery that waits for the page to load.  That jQuery updates a hidden field named “QueryFriendlyFilters” by adding the value of the FilterValue attribute.  Note all the crazy <xsl:text> and <![CDATA[ … ]]> stuff.

That’s it, hope it helps!

</end>

Subscribe to my blog.

Follow me on Twitter at http://www.twitter.com/pagalvin

PerformancePoint and Error 33494

One of my clients called today when their PerformancePoint environment (in SharePoint 2010) broke down.  One of the app servers in the farm was running low on disk space.  While addressing that, the client uninstalled “too much” and the PP stuff all stopped functioning.  Various web parts would show “An unexpected error occurred. Error 33494. Additional details have been logged for your administrator”:

image

I looked up the error and didn’t find anything specific to “Error 33494” but this MSDN forums posting was helpful: http://social.technet.microsoft.com/forums/en-us/sharepoint2010setup/thread/E1FE189D-7F89-455D-A98B-C1A12D8626AB

I found ADOMD.NET here as a component in the SQL Server 2008 Feature Pack: http://www.microsoft.com/downloads/en/details.aspx?FamilyId=228DE03F-3B5A-428A-923F-58A033D316E1&displaylang=en

image

(click to enlarge)

I download and installed that and it fixed everything.

I think this is a pretty oddball kind of error, but if you hit it, you at least you have an option.

</end>

Subscribe to my blog.

Follow me on Twitter at http://www.twitter.com/pagalvin

Lists.asmx, GetListItems and Folders

I was doing some research for someone today around the list.asmx web service provided as part of SharePoint 2010 (and earlier).  She was able to get the list items at the root folder (including the names of sub-folders), but couldn’t get items in sub-folders.  I did some looking around on the internets and it’s a surprisingly common question.  Yet, I couldn’t get a good answer to the simple question, “if I know the folder, how do I get the items in the folder?”  To be honest, I didn’t try all that hard since I’ve wanted to figure this one out on my own for a while Smile.

To set this up, I created a site named “Blogging Scenarios” and a custom list named “Custom List with Sub Folders”.  I then created folders named:

  • Year 2005
  • Year 2006
  • Year 2007

I added a few items to the folder “Year 2006”.  This is what it looks like:

image

My friend isn’t writing C# code but rather using Java, so the SOAP envelope was what she really needed.  To get that, I wrote a bit of jQuery and then used fiddler to get the actual HTTP conversation.

Here’s the relevant jQuery (I copied the code down below if you want to copy/paste):

image

They first key is to include both a <queryOptions> and <QueryOptions> node.  The second key is that the <Folder> node is a URL to which the client has access.

There may be other ways to get this, but this worked well for me when using jQuery.

Here is the SOAP envelope for the above:

<soapenv:Envelope xmlns:soapenv=’http://schemas.xmlsoap.org/soap/envelope/’>                
  <soapenv:Body>
    <GetListItems xmlns=’
http://schemas.microsoft.com/sharepoint/soap/’>
      <listName>Custom List with Sub Folders</listName>
      <viewFields>  
        <ViewFields>
          <FieldRef Name=’Title’ />
          <FieldRef Name=’EncodedAbsUrl’ />
        </ViewFields>
      </viewFields>
      <queryOptions>
        <QueryOptions>
          <Folder>
http://demoserver1/Blogging Scenarios/lists/Custom List with Sub Folders/Year 2006</Folder>
        </QueryOptions>
      </queryOptions>
   
</GetListItems>
  </soapenv:Body>
</soapenv:Envelope>

A lot of examples and discussion around this led me to believe that all I need was <QueryOptions> and specify a folder name.  For me, I need to both wrap it inside <queryOptions> as well as specify a fully qualified URL for the <Folder> node.

Here’s the jQuery AJAX setup:

$(document).ready(function() {
       var soapEnv =
           "<soapenv:Envelope xmlns:soapenv=’http://schemas.xmlsoap.org/soap/envelope/’> \
               <soapenv:Body> \
                    <GetListItems xmlns=’http://schemas.microsoft.com/sharepoint/soap/’> \
                       <listName>Custom List with Sub Folders</listName> \
                       <viewFields> \
                           <ViewFields> \
                              <FieldRef Name=’Title’ /> \
                              <FieldRef Name=’EncodedAbsUrl’ /> \
                          </ViewFields> \
                       </viewFields> \
                       <queryOptions> \
                         <QueryOptions> \
                           <Folder>http://demoserver1/Blogging Scenarios/lists/Custom List with Sub Folders/Year 2006</Folder> \
                         </QueryOptions> \
                       </queryOptions> \
                   </GetListItems> \
               </soapenv:Body> \
           </soapenv:Envelope>";

</end>

Subscribe to my blog.

Follow me on Twitter at http://www.twitter.com/pagalvin

Lists.asmx, GetList and “Value cannot be null”

I discovered today that the GetList() method in lists.asmx web service has to be called very carefully or it’s prone to throw a mysterious “Value cannot be null” exception (and that’s assuming you can get past the even worse generic error message, “Exception of type ‘Microsoft.SharePoint.SoapServer.SoapServerException’ was thrown.”)  Specifically, I found that you can’t provide any kind of prefix on the GetList method.  The following jQuery snippet illustrates the point:

image

If you do that, the web service responds with “Value cannot be null” as per this fiddler-provided HTTP transcript:

<?xml version="1.0" encoding="utf-8"?>
  <soap:Envelope
     xmlns:soap="
http://schemas.xmlsoap.org/soap/envelope/"    
     xmlns:xsi=”
http://www.w3.org/2001/XMLSchema-instance
     xmlns:xsd="
http://www.w3.org/2001/XMLSchema">

  <soap:Body>
    <soap:Fault>
      <faultcode>soap:Server</faultcode>
      <faultstring>
        Exception of type ‘Microsoft.SharePoint.SoapServer.SoapServerException’ was thrown.
      </faultstring>
      <detail>
        <errorstring xmlns="
http://schemas.microsoft.com/sharepoint/soap/">
Value cannot be null.
        </errorstring>
      </detail>
    </soap:Fault>
  </soap:Body>
</soap:Envelope>

Of course, you probably wouldn’t add that “s0” prefix on your own, but some tools are prone to do it (like Eclipse).

This is all the more confusing / frustrating because other methods tolerate prefixes.  For instance, the GetListCollection method doesn’t mind if it’s been prefixed, even with nonsense prefixes like “xyzzy”:

image

This “value cannot be null” seems fairly common with lists.asmx so hopefully this will help someone out in future.

</end>

Subscribe to my blog.

Follow me on Twitter at http://www.twitter.com/pagalvin