3M Technology Changing Medicine

Some of the cool stuff we are doing at 3M in software are some of the industry’s best kept secrets.  One example is our Littmann 3200 Bluetooth Stethoscope.  My team worked with the division to create this system.  This telemedicine technology is some really cool stuff.  Here’s a link to a great video about this project.  Also, it’s getting some great press from healthcare leaders, highlighted by a great post coming out of Microsoft.

We’ve got several more examples of great software technology coming out of 3M.  Stay tuned as I intend to share more about what we are doing!

Congratulations, Lyle!

I just got my hands on Delivering Mobile-Friendly Websites with MVC4, authored by my colleague and friend Lyle Luppes (blog). I am really happy for him and this accomplishment.

I am not a software engineer, so I would not get much personal value in reading this book. However, I would not hesitate recommending this work to any software engineer interested in this topic. I have worked with Lyle for many years, on many projects, and I know his work to be thorough. Great job, Lyle! Congratulations on this accomplishment!

Book Review: 12 Seconds to Project Management Greatness

Last night I finished 12 Seconds to Project Management Greatness.  Mr. Everett is a former colleague of mine, and we have fought the good fight together some years ago.  I can say with great certainty and experience that the concepts discussed in the book are well rooted in reality, and any project manager could benefit from reading this book.

I appreciated the approach Mr. Everett took in creating this work, as it read more like a screenplay or novel which made what is a pretty dry topic a lot more interesting.  I enjoyed meeting the Master Project Managers in the respective locations around the world and hearing some of the well-crafted stories.  There were a few nuggets I took from the book that I can apply to my daily work, as well as a few reminders of things I instinctively knew, but haven’t practiced effectively for some time.

I agree wholeheartedly that if one was to master each of the Project Management Imperatives written in this book that they would be a great Project Manager.   As the book concluded, our hero Alex is suddenly transformed into a great Project Manager, and his world is made right almost immediately.   It made for a great story, but as the story was winding down, I couldn’t help but being reminded of a recent encounter with one of Minnesota’s great baseball heroes, Tony Oliva.

I was with my son at a Twins baseball game, and we had the rare opportunity to have an extended conversation with Mr. Oliva as we were introduced by a mutual acquaintance.  My 11 year old son asked him, “what is the secret to hitting?”  Mr. Oliva responded with two thoughts.  The first comment was very simple, “Practice.”  The second piece of advice regarding practice came a few seconds later, “When you practice, don’t try to be perfect, just make better” (broken English intended).  That’s good advice to young  baseball players and Project Managers alike regarding development – it is important to view development as a journey.

The tools found in the back serve effectively as a roadmap to go on that journey, and I recommend any Project Manager take the time to leverage those tools for their own development.  For me, that was a key value of the book.

Congratulations to Mr. Everett on a fine piece of work, and I look forward to the continuing story of Alex Pilgrim.

At the Epicenter of Big Data Research


I am wiped out as I am on the plane home from my most recent experience at MIT.  This week the topic was Big Data.  Big Data is a big topic around the water cooler these days, so I thought it would be important to learn more about it.  The title of the course was Big Data: Making Complex Things Simpler.  This was a 2 day Executive Education course designed to brief managers and executives on this exploding field.

First of all, if you are interested in this topic I highly recommend making the investment of time and money to attend a future offering.  Professors Erik Brynjolfsson and Sandy Pentland, leading researchers in Big Data present a well-crafted curriculum that connects a great deal of their research around how Big Data now provides the technology framework to do, very quickly, what researchers have done for years – create hypotheses, design experiments and analyze results.  Because of Big Data technologies, organizations can become more data-driven in their operations and/or product development.  Key issues including data privacy and data ownership are discussed as well, but this landscape is changing very rapidly, so it was challenging to go into too much depth.

If you are looking to better understand Big Data technologies, this is not the course to take.  However, if you are looking to spend a few days better understanding the ramifications of Big Data and how they impact organizations, I highly recommend making the investment.  The participants in the class contributed greatly to the discourse, which I appreciated as well. Plus, it was a great place to network and find out what is happening in other industries related to Big Data.

The New iPad Is Here…The New iPad is Here!

At last, the new iPad has arrived.  This post will capture my very early impressions.  I will have more to say after I have gotten to work with it a bit more.

First, the setup was smooth and was done using a backup I had stored in the iCloud.  That was really neat, and it saved a lot of time — I was done in less than 5 minutes.  I was up and running in just a few minutes.  After the initial setup was done, I went back in and changed some sync preferences since this iPad had a little more space so I could carry some movies with me now.

The display is absolutely amazing.  The HD clarity is a big improvement over the iPad 2.  The dictation feature seems to work well also.  The device itself looks almost identical to the predecessor.  If I had to say anything, it might be a tad heavier, but if it is actually it can’t be by much.

More to come later as I use the device a little more.  At this point, I say “well done, Apple!”

Mobile Web Apps Fast

We’ve been doing a lot of work on mobile web lately, in addition to our work on native mobile platforms (e.g. iOS, Android, Win 7).  The author of this text, Lyle Luppes, works on my team and has come up with a way to quickly create a mobile web site that can be easily customized by a non-technical expert, like me.  Lyle and I have collaborated for years, and he consistently delivers what I need, which is often not what I ask for in the first place.  Here’s what Lyle has to say:

I’ve been doing a lot of work lately on websites that are configured to work nicely in smartphones and mobile devices. In the past, it’s been pretty tricky to create a site that changes nicely from a PC format into a mobile format. You’ll see lots of sites that use m.mysite.com or mobile.mysite.com, etc. The technique I’ve been developing here is simpler than that and automatically decides what format to serve up based on the browser type. This concept was inspired by a column from Scott Hanselmann. He had some great sample code posted, but it wasn’t completely fleshed out, so I’ve been working on a site that’s actually using these concepts.

Start with the MVC Framework

The framework that I have been using is based on the MVC3 template from Microsoft. If you haven’t looked at it, you should. It combines the best of the new ASP.NET functionality with the old classic ASP programming simplicity. (I really miss programming in Classic ASP sometimes – it was very simple and straightforward!) The new Razor syntax is great and I’ve been very impressed with what you can do with it.

I start with a standard MVC3 Internet package (File-New-ASP.Net MVC3 Web Application-Internet Application(Razor)), and then I add in a couple of secret ingredients to spice up the recipe.

By default the project registers one view engine (the Razor engine), but to enable the “VVVV” part of this concept, I’m going to add a few more options. The code looks at UserAgent (see line 62 below) and and then creates a Razor view engine with a slightly modified path. I’ll implement this by adding a CustomMobileViewEngine.cs file to the root of the project, which contains this code:

   1: using System;
   2: using System.Web.Mvc;
   4: namespace YourProject
   5: {
   6:   public class CustomMobileViewEngine : IViewEngine
   7:   {
   8:     public IViewEngine BaseViewEngine { get; private set; }
   9:     public Func<ControllerContext, bool> IsTheRightDevice { get; private set; }
  10:     public string PathToSearch { get; private set; }
  11:     public CustomMobileViewEngine(Func<ControllerContext, bool> isTheRightDevice, string pathToSearch, IViewEngine baseViewEngine)
  12:     {
  13:       BaseViewEngine = baseViewEngine;
  14:       IsTheRightDevice = isTheRightDevice;
  15:       PathToSearch = pathToSearch;
  16:     }
  17:     public ViewEngineResult FindPartialView(ControllerContext context, string viewName, bool useCache)
  18:     {
  19:       if (IsTheRightDevice(context))
  20:       {
  21:         return BaseViewEngine.FindPartialView(context, PathToSearch + "/" + viewName, useCache);
  22:       }
  23:       return new ViewEngineResult(new string[] { }); //we found nothing and we pretend we looked nowhere
  24:     }
  25:     public ViewEngineResult FindView(ControllerContext context, string viewName, string masterName, bool useCache)
  26:     {
  27:       if (IsTheRightDevice(context))
  28:       {
  29:         return BaseViewEngine.FindView(context, PathToSearch + "/" + viewName, masterName, useCache);
  30:       }
  31:       return new ViewEngineResult(new string[] { }); //we found nothing and we pretend we looked nowhere
  32:     }
  33:     public void ReleaseView(ControllerContext controllerContext, IView view)
  34:     {
  35:       throw new NotImplementedException();
  36:     }
  37:   }
  39:   public static class MobileHelpers
  40:   {
  41:     public static bool UserAgentContains(this ControllerContext c, string agentToFind)
  42:     {
  43:       return (c.HttpContext.Request.UserAgent.IndexOf(agentToFind, StringComparison.OrdinalIgnoreCase) > 0);
  44:     }
  45:     public static bool IsMobileDevice(this ControllerContext c)
  46:     {
  47:       return c.HttpContext.Request.Browser.IsMobileDevice;
  48:     }
  49:     public static void AddMobile<T>(this ViewEngineCollection ves, Func<ControllerContext, bool> isTheRightDevice, string pathToSearch)
  50:         where T : IViewEngine, new()
  51:     {
  52:       ves.Add(new CustomMobileViewEngine(isTheRightDevice, pathToSearch, new T()));
  53:     }
  54:     public static void AddMobile<T>(this ViewEngineCollection ves, string userAgentSubstring, string pathToSearch)
  55:         where T : IViewEngine, new()
  56:     {
  57:       ves.Add(new CustomMobileViewEngine(c => c.UserAgentContains(userAgentSubstring), pathToSearch, new T()));
  58:     }
  59:     public static void AddIPhone<T>(this ViewEngineCollection ves)
  60:         where T : IViewEngine, new()
  61:     {
  62:       ves.Add(new CustomMobileViewEngine(c => c.UserAgentContains("iPhone") || c.UserAgentContains("iPod"), "Mobile/iPhone", new T()));
  63:     }
  64:     public static void AddIPad<T>(this ViewEngineCollection ves)
  65:         where T : IViewEngine, new()
  66:     {
  67:       ves.Add(new CustomMobileViewEngine(c => c.UserAgentContains("iPad"), "Mobile/iPad", new T()));
  68:     }
  69:     public static void AddDroid<T>(this ViewEngineCollection ves)
  70:         where T : IViewEngine, new()
  71:     {
  72:       ves.Add(new CustomMobileViewEngine(c => c.UserAgentContains("Droid"), "Mobile/Android", new T()));
  73:     }
  74:     public static void AddBlackberry<T>(this ViewEngineCollection ves)
  75:         where T : IViewEngine, new()
  76:     {
  77:       ves.Add(new CustomMobileViewEngine(c => c.UserAgentContains("Blackberry"), "Mobile/Blackberry", new T()));
  78:     }
  79:     public static void AddGenericMobile<T>(this ViewEngineCollection ves)
  80:         where T : IViewEngine, new()
  81:     {
  82:       ves.Add(new CustomMobileViewEngine(c => c.IsMobileDevice(), "Mobile", new T()));
  83:     }
  84:   }
  85: }

In the Global.asax file, I add in code to register those engines:

   1: protected void Application_Start()
   2: {
   3:   AreaRegistration.RegisterAllAreas();
   4:   RegisterGlobalFilters(GlobalFilters.Filters);
   5:   RegisterRoutes(RouteTable.Routes);
   7:   ViewEngines.Engines.Clear();
   8:   ViewEngines.Engines.AddIPhone<RazorViewEngine>();
   9:   ViewEngines.Engines.AddIPad<RazorViewEngine>();
  10:   ViewEngines.Engines.AddDroid<RazorViewEngine>();
  11:   ViewEngines.Engines.AddBlackberry<RazorViewEngine>();
  12:   ViewEngines.Engines.AddGenericMobile<RazorViewEngine>();
  14:   ViewEngines.Engines.Add(new RazorViewEngine());
  15: }

That’s really the magic that drives this whole process. The rest is just simple MVC programming techniques. You can use whatever other background things you want like LINQ to SQL or Entity Framework, etc. – it doesn’t really matter for purposes of this discussion.

Build Out Your Mobile Views

From this point, you go about building your MVC website just like you did before. Once you build out a view, you’ll create a series of Mobile folders within each view folder. In the example below, I’ve added in Mobile folders for the Home view. You’ll want the folders to match the custom view engines that you registered in the CustomMobileViewEngine.cs file above. This keeps your mobile views right along-side of your normal views in your projects.

Since most of my mobile devices will behave almost exactly the same with only minor styling differences, I’m going to create shared partial views (the _Index.cshtml and _Details.cshtml) that will contain the guts of my pages, and then each actual mobile device file will simply set the layout file the device will use and then load in the partial view that contains the real contents of the page. If you don’t use this technique, you’ll end up replicating all your pages multiple times, which creates a maintenance nightmare. This way for each view you’ll have one file to maintain for rich browsers like a PC and one file to maintain for mobile browsers that is light and fast.

Here’s the Home/Mobile/Android/Index.cshtml.

   1: @{
   2: Layout = "../../../Shared/Mobile/Android/_Layout.cshtml";
   3: }
   4: @Html.Partial("../_Index")

and the Home/Mobile/Android/Details.cshtml.

   1: @{
   2: Layout = "../../../Shared/Mobile/Android/_PartialPage.cshtml";
   3: }
   4: @Html.Partial("../_Details")

Now Make Those Mobile Views Fit Look Nice

If you want to make your site look like a native mobile app, the easiest way I’ve found is to use an open source project called IUI. IUI makes your page look and behave like an iPhone type of interface. It’s based on the WebKit browser standards, so it will work on IOS and Android devices, but not all Blackberry devices. I include the IUI folder under the Content/Mobile folder, and have a slightly different themed CSS style file for Android pages and the iPhone pages.

Of course, there are a few things to watch out for here, the biggest of which has to do with how you set your layout pages. IUI will convert any links that you make into Ajax calls and fetch the HTML and load it right into a div in your document. It will automatically keep track of the stack and put titles on the page and back buttons in the toolbar. The thing to keep in mind is that any subsequent page after that first one should NOT load in the javascript and stylesheets. If you use the standard layout page with everything on it, it will get ugly and you’ll start seeing two or three or more title bars on one screen. Therefore, in the Shared Views folder, I’ve created a _Layout.cshtml and a _PartialLayout.cshtml. The first page I load (i.e. Home/Index) uses the _Layout.cshtml, but the other child pages use only the _PartialLayout.cshtml.

Here’s my Shared/Mobile/iPhone/_Layout.cshtml:

   1: <!DOCTYPE html>
   2: <html>
   3: <head>
   4:   <title>@ViewBag.Title</title>
   5:   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
   6:   <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
   7:   <link href="@Url.Content("~/Content/Mobile/iui/iui.css")" rel="stylesheet" type="text/css" media="screen" />
   8:   <link href="@Url.Content("~/Content/Mobile/iui/theme/default/default-theme.css")" rel="stylesheet" type="text/css" media="screen" />
   9:   <script src="@Url.Content("~/Content/Mobile/iui/iui.js")" type="text/javascript"></script>
  11:   <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=3.0;" />
  12:   <meta name="apple-touch-fullscreen" content="YES" />
  13:   <meta name="apple-mobile-web-app-capable" content="yes" />
  14:   <link rel="apple-touch-icon" href="@Url.Content("~/Content/Mobile/iPhone/apple-touch-icon.png")" />
  15:   <link rel="apple-touch-startup-image" href="@Url.Content("~/Content/Mobile/iPhone/iPhone_Startup.png")" />
  17:   <link rel="shortcut icon" href="http://www.yourdomain.com/favicon.ico" type="image/x-icon" />
  18:   <link rel="icon" href="http://www.yourdomain.com/favicon.ico" type="image/x-icon" />
  19: </head>
  20: <body>
  21:   <div>
  22:     <a id="backButton" href="#"></a>
  23:     <h1 id="pageTitle">@ViewBag.Title</h1>
  24:   </div>
  25:   @RenderBody()
  26: </body>
  27: </html>

And here’s my Shared/Mobile/iPhone/_PartialPage.cshtml:

   1: @RenderBody()

Pretty simple, huh?

Make Your Website Behave Like a Native Application

If you want your app to play nicely in the iPhone/iPad world and look like an app, it’s really not too difficult – you just need to add a few meta tags to your layout pages. The tags you are interested in are:

Desktop Icon:

Set “apple-touch-icon” to point to a PNG that is 57×57 pixels to look nice on an iPhone.

Mobile Web Application Behaviors:

Set “apple-touch-fullscreen” and “apple-mobile-web-app-capable” to “yes”. Adding the Mobile Web Capable meta tag does nothing for you when the user hits your site in the browser or when you test in a browser with UserAgent tags set to simulate an IOS device. However – if the user creates desktop shortcut, then you will see totally different behavior. When the user clicks on that desktop shortcut, it looks and behaves just like an installed app. Your app should start in a full-screen mode with a splash screen without the browser windows appearing. It’s really still using a browser window and running like a website, but it doesn’t look like it.

Full Width Screen and Pinch to Zoom:

Set “viewport” to “initial-scale=1.0; maximum-scale=3.0;”

Application Splash Screen:

Set “apple-touch-startup-image” to a PNG. The startup image for iPhone should be 320×460 pixels and the startup image for iPad should be 1004×768. You’ll be tempted to make them other sizes, but don’t do it. These devices are very picky and if you don’t make the startup images EXACTLY that size they simply won’t show up.


When I’m creating these websites, 90% of my testing is done on my PC, and then final testing is done on the devices. I use the Safari browser for most of my testing as it’s the closest thing to the IOS browsers. If you enable Developer mode in the browser, you should be able to go to the Developer menu and change the User Agent that the browser supplies. Since that’s what our Custom View Engine module looks at, the site will serve up the pages pretty much like an iPad or iPhone device would see them. It’s not perfect, but it is definitely close and makes it very simple to debug and test your site.

The biggest thing to watch out for is that you HAVE to test on a IOS mobile device if you want your desktop shortcut to behave like an application. (Android doesn’t matter because you’ll still open the shortcut in the browser) Some types of links will break out of that application mode, and the “application” that was running full screen app mode will suddenly open a new browser window, then you’ll be right back in the browser world, so you’ll have to test each page/link for that. The best solution I’ve found so far is to change those problem links from a simple HREF to a javascript call like “window.location.href=’mynewpage’”. If you do that, then it will keep it within the Mobile Web Application and not open a new browser window.

Wrapping It Up

That’s about it for this post – I’ve shown you the basics of how to create an MVC3 website that automatically morphs into a different mode when you browse to it with different devices. But this is really just the beginning – there are plenty of other topics you’ll want to explore to along these lines.

I created a VS2010 template file that encapsulates all of these ideas along with my standard base pages, stylesheets, images, etc., so that makes it very easy for me to create a new project with all of these things baked in. (Create your own by doing a File – Export Template when you’ve got a working project).

I’ve also been working on a code generator that does essentially what the MVC scaffolding engines do, but which also scaffolds all of the Mobile pages at the same time. I can simply point it at a database table, and it will generate the Model, Controller, and all the resulting views automatically.

With those two things in hand, I can have the code base for a full MVC mobile-enabled website spun up in a few minutes, and then I can spend my time customizing that site to solve my business problem instead of creating all of the repetitive behind the scenes plumbing that you normally have to do.


Scott Gu’s Blog announcing MVC 3


Scott Hanselman’s First Blog about MVC Mobile (Incomplete and updated later)


Scott Hanselman’s Second Blog about MVC Mobile (fixes problems with the first post, but still incomplete)


Good Walkthroughs/Tutorials for MVC3 and Razor




IUI Mobile Framework


Technorati Tags: MVC,Mobile,MVC3,Razor,iPhone,IUI,ASP.NET