Thursday, August 5, 2010

Book Review: Microsoft SharePoint 2010 – Building Solutions

 sp2010 The full title of this book by Sahil Malik is Microsoft SharePoint 2010 – Building Solutions for SharePoint 2010, and it was recently published by Apress.  I love Apress books, and have 6 others on various .NET related topics on my shelf.  SharePoint 2010 is something I needed to get up to speed on really quickly for a new project at work, as in I had less than a week to make sure I knew what I was talking about.

The book is 367 pages, and covers a wide variety of topics in SharePoint 2010.  It demos a few techniques and tools, and identifies some of the differences between SharePoint 2007 and SharePoint 2010, so even if you know SharePoint 2007, it will really help you to identify what is different about 2010. 

I’ve barely worked in SharePoint in the past.  I tried a little bit of SharePoint 2003, and dabbled in 2007, but frankly, after seeing how painful it was to work in either of those environments, I wanted nothing to do with it.  SharePoint was where good developers went to watch their career die.  Once you knew it, you were guaranteed to get every crappy job out there, and because you were so valuable to the execs and their TPS reports, there was no way you were ever going to get out without quitting your job.  And then, of course, you were so pigeonholed as a SharePoint developer, you could never get out from under it.  Even if I knew SharePoint 2007, I would never put it on my resume.  Career suicide.

SharePoint 2010 seems to be a little different.  With the advent of Windows Identity Foundation and the advanced made in PowerPivot Services, there are definitely things that can be done in 2010 that would take forever in a typical ASP.NET application.  And Linq to SharePoint is a godsend.

Malik covers all these topics with a few quick examples so that at least you know what is there, and how to use it.  Each topic is probably worthy of a book of its own.  I don’t have that kind of spare time, so I needed something at this level so I at least can speak the language and help to architect where these features can be used.  Some features I will deep dive into in the future.  Some features I will leave for others on my team to get familiar with.  You can’t know them all.

I do have a very big gripe with this book.  It does not appear as if it was ever professionally edited by a real copy editor.  There are grammar and spelling mistakes on just about every page.  As a fellow author, I know how hard it is to produce clean copy by yourself.  A second or third set of eyes is always necessary.  So I don’t blame the author for this, I blame the publishing company, Apress.  I really hope this is not a sign of things to come.  I know things are changing in the publishing world, and time to market on these books is critical and compressed.  But in the two or three dozen technical books I’ve read in the last few years, and the dozens of fiction books I’ve read, I can only remember a few typos.  This book had hundreds, and it drove me batty.  I had to reread entire sentences to try to make sense out of them because words were transposed, missing or extras added in and never removed.

Also, the print on this book, and the line spacing is small.  It really felt like they were trying to save paper by eliminating paragraph breaks.  If the book was a fast action thriller, that may not be a problem, but in a technical book, I expect proper formatting.  It helps to convey information and give your brain a break; an indication that the topic or idea is changing.  Without a break, it gets really hard to read. A lot of the graphics are blurry or too dark to read, though that could have been my eyes as I was reading late in the evening.  At one point, it was so bad, I wanted to hurl the book across the room.

I’m going to recommend this book, but I really hope they do another edit on it.  Architects should read it.  SharePoint 2007 devs should read it to get up to speed on the changes.  New devs for SharePoint 2010?  Not sure.  It does give a good introduction to SharePoint Development, but you’ll probably end up buying another book as well to get into the nitty-gritty.

SharePoint 2010 seems to have come a very long way from it predecessors, but it still feels like it is behind the times, and a little kludgy.  I’m worried that there are difficulties hidden in the practicalities of working with it that are glossed over by this book – things that you could spend a week trying to figure out, only to be frustrated by some weird case where you have to use I before E except after C when the word is in French and followed by an apostrophe.  SharePoint 2010 is to SharePoint 2007 as .NET 2.0 was to .NET 1.1.  The next version should be like .NET 3.5, infinitely better and more stable.  2010 is usable, but just not quite there yet.

But it no longer seems like career suicide to know it.  You’ll probably just need to make sure it is not the first item you list on your resume.

Wednesday, August 4, 2010

Book Review: Programming Windows Azure

I meant to review Sriram Krishnan’s Programming Windows Azure book a few weeks ago, but I have been slacking.  It wasn’t until last night, when I was halfway through my next technical book (which I will review soon), that I realized that I had neglected to do the obligatory blog post.

I’ve been working with Windows Azure since the day after the CTP Launch.  I was in the Early Adopter program.  I corresponded regularly via email or via the forums with various members of the Azure Team for about 8 months between December 2008 and July 2009.  I’ve led three major projects in the Azure world, and at PDC last year, members of the Azure team were finally able to put a face to the name of the guy that kept asking the questions that kept them working a lot of hours.  Most of them didn’t hold that against me.

I give that background because when I bought this book I didn’t think I, of all people, would get much out of it.  It was going to be another trophy on my shelf, a book read, a subject I thought I knew well enough to make this what I would consider a ‘light read’.

I was in for a shock.  A refreshing one.  This book taught me something new, or closed a gap in my knowledge base, on just about every page.  While I had worked with Windows Azure, it was in the context of delivering a specific product, and my focus was on using Windows Azure as a tool to allow the product to launch, and a lot of the details had be bypassed.

This is a great book – one of the top 3 or 4 technical books I’ve read in the past 3 years.  Every developer working on Azure must read this book.  Must.  Nothing beats the experience of working on a new platform, but this book will sure make it easier, and teach you the benefits and the pitfalls of this environment.

The biggest downfall of this book is that Chapters 1 (Cloud Computing) and 2 (Under The Hood) will lose a lot of developers who have no interest in the internals of Azure or the history of cloud computing.  These are both necessary and interesting chapters, but for the non-architect or truly technical geek, most will skim them or skip them.

Also, the scope of the book is limited to the Azure Platform itself, and it does not cover things like the AppFabric or the role of Windows Identity Foundation in Azure.  I’m looking for a good book on those as well, since I have yet to deep dive into the Service Bus, and haven’t worked with WIF since it was still called Geneva.

The rest of the book is superb, and like I said, I learned something on every page.  Every Azure developer should have this trophy on their shelf.

Microsoft Word 2010 Bug

I spend a lot of time in Microsoft Word 2010 writing my novels.  I most often am working on my ACER 1420P laptop while doing it, and honestly, this is the only place I have seen this bug, but it annoys the crap out of me.

Here’s what happens:

  1. Open a new or existing document
  2. Start typing
  3. Let you mouse cursor drift up over the tool bar (like the one for text formatting). 
  4. Keep typing.
  5. Eventually, characters will start repeating.  First you’ll see three ‘c’ characters (or whatever character that falls victim to this bug on that given day).  If you see this start to happen, sometimes moving the mouse will stop the next phase from happening, but if you miss it because you watch your fingers and not the screen (which I am prone to do), phase 2 of the bug will soon kick in.
  6. Phase 2 involves Satan taking over your computer.  If you just happen to hit the backspace key or a cursor key, it will start repeating indefinitely.  Next thing you know, your whole document is gone or you are sitting at the top or bottom of your document, and you still can’t get control back.

The only thing that I have ever found that works is to pull up task manager, and kill Word.  But at least it will ask you if you want to save your changes before it closes.  If the repeating character is a cursor movement, no problem.  If it was the backspace key, you are SOL.

I find that the bug shows up most often if the cursor seems caught between tool bar buttons.  It looks like a Windows event has gotten into an infinite loop, and as a developer, I would not want to be the one who has to try to figure this one out.

That said, I really hope this gets fixed soon.  It happens to me at least once a week, and more than once has cost me work.  I save early and save often because this one could strike at any moment.

Monday, July 5, 2010

Gradients, CSS and Overflow

Last year, I built a website (http://www.joebeernink.com) to handle aspect of my burgeoning writing career.  I also used it to learn ASP.NET MVC.

I had a designer do the styles and the graphics, but I did all the HTML work.  When I originally laid everything out, the content all fit nicely on a single 800px long div which exactly matched the length of the repeating vertical gradient the designer put together for me for the outer background. 

Once the content got too long, the repeating style left a lot to be desired.  It not only repeated across the X axis, but the Y axis as well, which meant starting at pixel 801, I had this nasty black line across the bottom of the screen, and then the gradient began again.  Yuck.

So instead of that, I set overflow = auto on all my inner divs, which for a while meant that the one page that had too much content had an inner scroll bar.  I was kind of okay with that (I shouldn’t have been), but CSS has never been something I’ve worked with a lot, so I ignored it.

Lately, as I’ve been upgrading my site for an upcoming conference, every page began to have the scroll bar, and it was killing me.  I talked to my designer at work and they shook their heads and said, “Dude, that’s like one line of CSS to fix.  Don’t be such a loser.”  Okay they didn’t say that, but they should have.  They said it was pretty easy, and could be done in a single line of CSS.  They were going to send me that line of CSS, but must have forgot.  So yesterday, knowing that a single line solution existed, I got ready to do some CSS spelunking, and eventually came up with the solution.

Out with the old CSS Classes

.page
{
    background-image: url("../../Content/beernink_pagebkgd.jpg");
    margin-left: auto;
    margin-right: auto;
    background-repeat: repeat;
}

#main
{
    margin-left: auto;
    margin-right: auto;
    padding: 20px 30px 20px 30px;
    background-image: url("../../Content/beernink_insideBkgd.jpg");
    background-repeat: repeat;
    margin-bottom: 5px;
    width: 740px;
    _height: 1px; /* only IE6 applies CSS properties starting with an underscrore */
    overflow: auto;
    height: 500px;
}

And in with the new

.page
{
    background: #252E33 url("../../Content/beernink_pagebkgd.jpg");
    margin-left: auto;
    margin-right: auto;
    background-repeat: repeat-x;
}

#main
{
    margin-left: auto;
    margin-right: auto;
    padding: 20px 30px 20px 30px;
    background-image: url("../../Content/beernink_insideBkgd.jpg");
    background-repeat: repeat;
    margin-bottom: 5px;
    width: 740px;
    _height: 1px; /* only IE6 applies CSS properties starting with an underscrore */
    /* overflow: auto;
    height: 500px; */
}

The #252E33 is the color at the bottom of the gradient. The color nicely fills the page beyond the 800px line, and looks great. 

There are probably better ways to do this, but this was simple and allowed me to say the site was ‘done-done’ for the conference later this month.

Of course, now I want to find a real blogging engine in ASP.NET MVC that I can deploy with my site.  Any recommendations?

Friday, May 7, 2010

Silverlight + Azure Shared Access Policy Issue

We’ve been working with Shared Access Policies in Azure for the last week or so, and for the most part it was working.  But it would only work for a while, then it would stop.  Then it would start working again.   It took some help from Steve Marx and Jai Haridas on the Azure Team to figure out what was going on.

This first piece of code is part of our storage manager that retrieves the Uri for the blob from Azure Blob Storage, and creates a Shared Access Policy for that blob so that our Silverlight Video Player can directly access the blob without going through a very slow web service call.

   1: /// <summary>



   2:         /// Get the Uri for a specified video blob



   3:         /// </summary>



   4:         /// <param name="videoId">The unique identifier of the video</param>



   5:         /// <returns>A Uri ponting to the Video</returns>



   6:         public Uri GetVideoBlobUri(Guid videoId)



   7:         {



   8:             var log = Log4NetHelper.GetLogger();



   9:             log.DebugFormat("Getting Video for video id {0}", videoId);



  10:  



  11:             try



  12:             {



  13:                 CloudBlobContainer container = GetContainer("VideoContainerName");



  14:  



  15:                 CloudBlockBlob cloudBlockBlob = container.GetBlockBlobReference(string.Format(CultureInfo.InvariantCulture, "{0}", videoId));



  16:                 



  17:                 var readPolicy = new SharedAccessPolicy



  18:                 {



  19:                     Permissions = SharedAccessPermissions.Read,



  20:                     SharedAccessExpiryTime = DateTime.UtcNow + TimeSpan.FromMinutes(10)



  21:                 };



  22:  



  23:                 var blobUri = new Uri(cloudBlockBlob.Uri.AbsoluteUri + cloudBlockBlob.GetSharedAccessSignature(readPolicy));



  24:  



  25:                 log.DebugFormat("GetVideoBlobUri successfully retrieved for video id {0}", videoId);



  26:  



  27:                 return blobUri;



  28:             }



  29:             catch (StorageClientException ex)



  30:             {



  31:                 // If the blob was not found, return null



  32:                 if (ex.ErrorCode == StorageErrorCode.BlobNotFound)



  33:                     return null;



  34:                 // Rethrow the exception in all other cases



  35:                 throw;



  36:             }



  37:             catch (Exception ex)



  38:             {



  39:                 log.ErrorFormat("Error while retrieving video blob {0}", ex.Message);



  40:                 throw;



  41:             }            



  42:         }




In our Silverlight Web Service, we call this manager class and return the Uri embedded in an XElement.  Originally we did this to allow us to return other information with the Uri, but at this point, the Uri is all we are passing through.





   1: /// <summary>



   2: /// Get video URI.



   3: /// </summary>



   4: /// <param name="videoId">ID of the given video.</param>



   5: /// <returns>Status</returns>



   6: public XElement DemoVideoUri(string videoId)



   7: {



   8:     var blobManager = UnityFactory.Current.Resolve<IBlobManager>();



   9:     var blobUri = blobManager.GetVideoBlobUri(new Guid(videoId));



  10:  



  11:     string xml = string.Format("<VideoUri>{0}</VideoUri>", HttpUtility.HtmlEncode(blobUri.AbsoluteUri));



  12:     var sr = new StringReader(xml);



  13:     return XElement.Load(sr);



  14: }




On the Silverlight side, we take make a call to this web service, extract the Url from the XElement, and pass the Url into the MediaPlayer like so





   1: var client = new WebClient();



   2:  



   3: var videoUri = GetVideoUri();



   4:  



   5: client.DownloadStringCompleted += (x, y) =>



   6:                                Dispatcher.BeginInvoke(



   7:                                    () =>



   8:                                    {



   9:                                        var xdoc = XDocument.Parse(y.Result);



  10:                                        var query = from b in xdoc.Descendants()



  11:                                                    select b.Value;



  12:                                        HostedVideoUri = new Uri(HttpUtility.HtmlDecode(query.First()), UriKind.Absolute);



  13:                                        mediaPlayer.Source = HostedVideoUri;



  14:                                        Log(string.Format("HostedVideoUrl = {0}", HostedVideoUri.AbsoluteUri));



  15:                                    }



  16:                                    );



  17:  



  18: client.DownloadStringAsync(new Uri(videoUri, UriKind.Absolute));



  19:  



  20:  



  21: private static string GetDemoVideoUri()



  22: {



  23:     var host = HtmlPage.Window.Eval("window.location.hostname;") as string;



  24:     var path = HtmlPage.Window.Eval("window.location.pathname;") as string;



  25:     var refererUri = host + path;



  26:     var url = string.Format("http://{0}/xxxx.Svc/DemoVideoUri/{1}", GetHost(), VideoId);



  27:     return url;



  28: }






This is all pretty simple code (and the above code works, by the way).



Where we ran into problems was in the Web Service, when populating the xml string.  Originally, we used blobUri.ToString() instead of blobUri.AbsoluteUri.   This caused big issues (403 errors returned from the Azure Storage Service), when the Video Player tried to retrieve the blob because the Url returned from the Shared Access Policy generator can have spaces in it.  And Uri.ToString and Uri.AbsoluteUri work very differently when handling spaces.  I did not know this until last night.  Uri.ToString unescapes the Uri before returning it.







So why did it work sometimes, and not all the time?  Simple.  Sometimes the Uri from the Shared Access Policy Generator has spaces, and sometimes it does not.  The former did not work, while the latter did.  We were looking for a pattern in the number of times we called the web service, or the interval between calls, and the size of the video blob.  But it was as simple as a single space.



I think we spent at least 8 hours over the last two days trying to track down this bug.  Hopefully this saves someone else some grief.



This post is cross posted on http://www.palador.com/blog/Blog/Silverlight--Azure-Shared-Access-Policy-Issue intentionally.