I’ve long advocated using JSON when building mobile and cloud applications. If nothing else, the payload size makes it extremely efficient when transferred over the wire – take a look at the size of the same information formatted as OData, REST-XML, and lastly JSON:

JSON versus OData versus REST-XML

Pretty compelling.

Despite the use of JSON – and great frameworks like JSON.NET and SimpleJson – I always struggled with creating my C# classes when working with an existing web service that returned JSON. It can take a long time to create these C# classes correctly, and often time I’d take a lazy approach and either use the JObject or an IDictionary such that I didn’t have to have a C# class – something like:

var json = (IDictionary<string, object>)SimpleJson.DeserializeObject(data);

Yesterday I stumbled upon a tool that makes this SO amazingly easy. In many ways I’m bothered by the fact that it’s taken me so long to find it – has this been one of the best kept secrets on the Internet or did I just miss it?

http://json2csharp.com/

This website is as simple as it is powerful. Simply paste your JSON into the textbox, click Generate, and voilà you have C# objects!

Take a look. Here’s some JSON returned back from the Untappd API:

{
  "meta": {
    "code": 200,
    "response_time": {
      "time": 0.109,
      "measure": "seconds"
    }
  },
  "notifications": [],
  "response": {
    "pagination": {
      "next_url": "http://api.untappd.com/v4/thepub?max_id=11697698",
      "max_id": 11697698,
      "since_url": "http://api.untappd.com/v4/thepub?min_id=11697724"
    },
    "checkins": {
      "count": 2,
      "items": [
        {
          "checkin_id": 11697724,
          "created_at": "Wed, 22 Aug 2012 12:56:41 +0000",
          "checkin_comment": "",
          "user": {
            "uid": 205218,
            "user_name": "asiahobo",
            "first_name": "Bum",
            "last_name": "",
            "location": "",
            "url": "0",
            "relationship": null,
            "bio": "0",
            "user_avatar": "https://untappd.s3.amazonaws.com/profile/7d21ba831edb33341b98f86e09795ed7_thumb.jpg",
            "contact": {
              "twitter": "asiahobo",
              "foursquare": 31652652
            }
          },
          "beer": {
            "bid": 9652,
            "beer_name": "Maredsous 8° Brune",
            "beer_label": "https://untappd.s3.amazonaws.com/site/beer_logos/beer-maredsous.jpg",
            "beer_style": "Belgian Dubbel",
            "auth_rating": 0,
            "wish_list": false
          },
          "brewery": {
            "brewery_id": 6,
            "brewery_name": "Abbaye de Maredsous (Duvel Moortgat)",
            "brewery_label": "https://untappd.s3.amazonaws.com/site/brewery_logos/brewery-AbbayedeMaredsousDuvelMoortgat_6.jpeg",
            "country_name": "Belgium",
            "contact": {
              "twitter": "",
              "facebook": "www.facebook.com/pages/Abbaye-De-Maredsous/208016262548587fine",
              "url": "www.maredsous.be/"
            },
            "location": {
              "brewery_city": "",
              "brewery_state": "Denée",
              "lat": 50.3044,
              "lng": 4.77149
            }
          },
          "venue": [],
          "comments": {
            "count": 0,
            "items": []
          },
          "toasts": {
            "count": 0,
            "auth_toast": null,
            "items": []
          },
          "media": {
            "count": 0,
            "items": []
          }
        },
        {
          "checkin_id": 11697723,
          "created_at": "Wed, 22 Aug 2012 12:56:35 +0000",
          "checkin_comment": "",
          "user": {
            "uid": 137722,
            "user_name": "Mjoepp",
            "first_name": "Christoffer",
            "last_name": "",
            "location": "Linköping",
            "url": "",
            "relationship": null,
            "bio": "",
            "user_avatar": "http://gravatar.com/avatar/f1672535a7caa3bd686267257d33c588?size=100&d=https%3A%2F%2Funtappd.s3.amazonaws.com%2Fsite%2Fassets%2Fimages%2Fdefault_avatar.jpg",
            "contact": {
              "foursquare": 25958771
            }
          },
          "beer": {
            "bid": 12145,
            "beer_name": "Chocolate",
            "beer_label": "https://untappd.s3.amazonaws.com/site/beer_logos/beer-ChocolatePorter_12145.jpeg",
            "beer_style": "English Porter",
            "auth_rating": 0,
            "wish_list": false
          },
          "brewery": {
            "brewery_id": 844,
            "brewery_name": "Meantime Brewing Company",
            "brewery_label": "https://untappd.s3.amazonaws.com/site/brewery_logos/brewery-MeantimeBrewingCompanyLimited_844.jpeg",
            "country_name": "England",
            "contact": {
              "twitter": "MeantimeBrewing",
              "facebook": "http://www.facebook.com/meantimebrewing",
              "url": "http://www.meantimebrewing.com"
            },
            "location": {
              "brewery_city": "London",
              "brewery_state": "",
              "lat": 51.5081,
              "lng": -0.128005
            }
          },
          "venue": [],
          "comments": {
            "count": 0,
            "items": []
          },
          "toasts": {
            "count": 0,
            "auth_toast": null,
            "items": []
          },
          "media": {
            "count": 0,
            "items": []
          }
        }
      ]
    }
  }
}

I’m sad to admit that, in the past, I’d like create my C# objects by hand and then either conform to the JSON or map between the two. It requires a TON of time and is extremely error prone. With http://json2csharp.com/ all I do is paste this into the textbox and click Generate. I’ll get the following output:

public class ResponseTime
{
    public double time { get; set; }
    public string measure { get; set; }
}

public class Meta
{
    public int code { get; set; }
    public ResponseTime response_time { get; set; }
}

public class Pagination
{
    public string next_url { get; set; }
    public int max_id { get; set; }
    public string since_url { get; set; }
}

public class Contact
{
    public string twitter { get; set; }
    public int foursquare { get; set; }
}

public class User
{
    public int uid { get; set; }
    public string user_name { get; set; }
    public string first_name { get; set; }
    public string last_name { get; set; }
    public string location { get; set; }
    public string url { get; set; }
    public object relationship { get; set; }
    public string bio { get; set; }
    public string user_avatar { get; set; }
    public Contact contact { get; set; }
}

public class Beer
{
    public int bid { get; set; }
    public string beer_name { get; set; }
    public string beer_label { get; set; }
    public string beer_style { get; set; }
    public int auth_rating { get; set; }
    public bool wish_list { get; set; }
}

public class Contact2
{
    public string twitter { get; set; }
    public string facebook { get; set; }
    public string url { get; set; }
}

public class Location
{
    public string brewery_city { get; set; }
    public string brewery_state { get; set; }
    public double lat { get; set; }
    public double lng { get; set; }
}

public class Brewery
{
    public int brewery_id { get; set; }
    public string brewery_name { get; set; }
    public string brewery_label { get; set; }
    public string country_name { get; set; }
    public Contact2 contact { get; set; }
    public Location location { get; set; }
}

public class Comments
{
    public int count { get; set; }
    public List<object> items { get; set; }
}

public class Toasts
{
    public int count { get; set; }
    public object auth_toast { get; set; }
    public List<object> items { get; set; }
}

public class Media
{
    public int count { get; set; }
    public List<object> items { get; set; }
}

public class Item
{
    public int checkin_id { get; set; }
    public string created_at { get; set; }
    public string checkin_comment { get; set; }
    public User user { get; set; }
    public Beer beer { get; set; }
    public Brewery brewery { get; set; }
    public List<object> venue { get; set; }
    public Comments comments { get; set; }
    public Toasts toasts { get; set; }
    public Media media { get; set; }
}

public class Checkins
{
    public int count { get; set; }
    public List<Item> items { get; set; }
}

public class Response
{
    public Pagination pagination { get; set; }
    public Checkins checkins { get; set; }
}

public class RootObject
{
    public Meta meta { get; set; }
    public List<object> notifications { get; set; }
    public Response response { get; set; }
}

Pretty amazing! Now, note that it’s not perfect – there’s both a Contact and Contact2 class, but that’s easy to fix by merging the two and updating references. I’ll gladly perform this little bit of cleanup given the hours this tool just saved me.

Now that I have these classes, it’s really easy to use JSON.NET to load them with data.

RootObject publicFeed = new RootObject();

using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
    data = reader.ReadToEnd();

    publicFeed = JsonConvert.DeserializeObject<RootObject>(data);
}

Now it’s a simple matter of using my RootObject within my applications.

I feel like I may be the last person to have heard of this tool, in which case I’m both embarrassed and bitter – couldn’t you all have told me about this years ago? Smile

I hope this helps!

Earlier this week we released the Windows Azure SDK 1.6, which includes a lot of great updates to the emulators, tools for Visual Studio, and libraries. One of my favorite additions is a new way to get a management certificate installed into Windows Azure and onto your machine. You can now browse to https://windows.azure.com/download/publishprofile.aspx and login with your Live ID; this process will do two things:

  1. Generate a management certificate that is installed into Windows Azures on your behalf.
  2. Prompts you to download a .publishsettings file which includes an encoded version of your certificate and all of your subscription IDs.

The new tools for Visual Studio let you easily important this file and immediately start working with your subscriptions from within Visual Studio. It’s a much simpler experience than in the past. In fact, on this weeks episode of the Cloud Cover Show (not yet published) Steve and I cover how to use this file from within your own code. While Steve beat me to it and published a great blog post showing some of the things you can do, I thought I’d take this a slightly different way and show you a couple different things:

  • How to install the certificate into your personal certificate store (which is exactly what Visual Studio is doing).
  • How to use the certificate from your person certificate store to make calls to the Service Management API.

The code is very similar. Take a look:

    var publishSettingsFile = 
        @"C:\\temp\\CORP DPE Account-11-16-2011-credentials.publishsettings";
    
    XDocument xdoc = XDocument.Load(publishSettingsFile);
    
    var managementCertbase64string =
        xdoc.Descendants("PublishProfile").Single().Attribute("ManagementCertificate").Value;
    
    var importedCert = new X509Certificate2(
        Convert.FromBase64String(managementCertbase64string));

Now that we’ve imported the certificate, we can extract some information. I’ll grab the certificate thumbprint, which uniquely identifies the certificate—we’ll use it later in the post.

    string thumbprint = importedCert.Thumbprint;

Additionally, I can grab my subscription ID from the .publishsettings file – this we will also use later.

    string subscriptionId = xdoc.Descendants("Subscription").First().Attribute("Id").Value;

Now, we can take our X509Certificate2 and install it directly into our certificate store.

    X509Store store = new X509Store(StoreName.My);
    store.Open(OpenFlags.ReadWrite);
    store.Add(importedCert);
    store.Close();

After running this code, you can see that the certificate has been installed into my personal certificate store.

CertMgr

If you select the certificate you’ll see that it’s the same certificate with the same thumbprint.

certificate

Since the certificate is now loaded into the certificate store I can delete the .publishsettings file – I no longer need it. (It’s also a credential that I don’t want to let anyone else get their hands on.)

Now I have the following resources available to me:

  • My X509 certificate loaded in my personal certificate store.
  • The thumbprint for the certificate (which we’ll use to identify the right certificate).
  • My Windows Azure subscription ID.

With this information we can do the exact same thing Steve shows in his post except without the .publishsettings file.

    X509Store store = new X509Store(StoreName.My);
    store.Open(OpenFlags.ReadWrite);
    X509Certificate2 managementCert = 
        store.Certificates.Find(X509FindType.FindByThumbprint, thumbrprint, false)[0];
    
    var req = (HttpWebRequest)WebRequest.Create(
        string.Format("https://management.core.windows.net/{0}/services/hostedservices", 
        subscriptionId));
    
    req.Headers["x-ms-version"] = "2011-10-01";
    req.ClientCertificates.Add(managementCert);
    
    XNamespace xmlns = "http://schemas.microsoft.com/windowsazure";
    
    Console.WriteLine(string.Join("\n",
        XDocument.Load(req.GetResponse().GetResponseStream())
        .Descendants(xmlns + "ServiceName").Select(n => n.Value).ToArray()));

Essentially, we can grab the certificate out of the certificate store using the thumbprint and then make the exact same call to the service management API.

The console output below shows that I’m able to get a list of all my hosted services:

Console

It’s as simple as that!

I’m not sure that this post applies to everyone—in fact, most of you may find it boring or cryptic—but for those of you that are building content or tools you’ll probably find this a really simple way to automate a lot of the pieces. I know that my team plans to use these techniques in a lot of places to simply the experience of getting started with Windows Azure.

I hope this helps!

Now that we can get our hands on the Windows Developer Preview of Windows 8, I’m sure everyone is excited to start building applications! For many of us, this means that we’ll want to install all of the great Windows Azure tools on our Windows Developer Preview machine – especially if we plan to take advantage of the new Windows Azure Toolkit for Windows 8. However, there are a few things we’ll need to do in order to get things to work.

Quickly let me explain the three challenges you’ll run into:

  1. The current Windows Azure Tools for Visual Studio do not yet support Dev11 – you’ll have to install Visual Studio 2010.
  2. There are a few quirks getting dependencies for IIS installed on Windows 8 using the Web Platform Installer.
  3. After Visual Studio 2010 and the Windows Azure Tools for Visual Studio are installed on a machine with Dev11, the Windows Azure tools will grab an environmental path variable that points to 11.0 instead of 10.0.

Fortunately, these things are pretty easy to resolve and will certainly get addressed in later builds.

Here’s what you’ll have to do to get the tools and SDK working with the Windows Developer Preview:

  1. Install Microsoft .NET Framework 3.5.1. Easiest way is to type “Windows Features”, select Settings, and select Turn Windows features on or off. Then simply check the checkbox. Click OK to install.
    Step 1 - .NET 3.5.1
  2. Next we need to correctly configure IIS. Typically we’d do this through the Web Platform Installer, but this doesn’t work correctly on Windows 8. From Turn Windows features on or off you’ll need to do the following, then click OK to install.
    • Check Internet Information Services.
    • Expand Internet Information Services and World Wide Web Services.
    • Expand Application Development Features and check ASP.NET 2.0, ASP.NET 4.5, and CGI.
    • Expand Common HTTP Features and check HTTP Redirection.
    • Expand Health and Diagnostics and check Logging Tools, Request Monitor, and Tracing.
  3. Install the Web Platform Installer (WebPI).
  4. Install Visual Web Developer 2010 Express through WebPI. (You can use a different version of Visual Studio 2010, so long as it’s supported by the Windows Azure Tools for Visual Studio.)
  5. Install Windows Azure Tools for Microsoft Visual Studio 2010 – September 2011 through WebPI.

Okay, now you have everything installed. However, before you trying running Visual Studio, you have to create a script to launch Visual Studio 2010. This is because the Windows Azure tools use an environmental variable that’s incorrectly pointing to version 11.0, and we’ll need to change it right before we launch to version 10.0 (for Visual Studio 2010).

@ECHO OFF

SET VisualStudioVersion=10.0

SET VisualStudioPath="%ProgramFiles(x86)%\Microsoft Visual Studio 10.0\Common7\IDE"
IF NOT EXIST %WINDIR%\SysWow64 SET VisualStudioPath="%ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE"

CD /D %VisualStudioPath%

VWDExpress.exe

As you can see, the script changes the VisualStudioVersion to 10.0 then launches Visual Web Developer Express (there’s a little extra code to set the path correctly regardless of 32- or 64-bit versions of Windows).

Save the above script as a CMD file (i.e. OpenVisualStudio2010.cmd) and then make sure to right-click and Run as administrator! If you forget to run the script as administrator then Visual Studio won’t have the permissions needed to run the Windows Azure tools correctly.

Running Instance

Look, it’s working!

NOTE: I found myself having to reboot Windows 8 in order to resolve a problem where the debugger wouldn’t attach. Not sure if this occurs every time, but in case you have a similar issue just try rebooting.

I hope this helps!

Yesterday Steve Marx and I covered the new Windows Azure Tools for Visual Studio 1.4 release on the Cloud Cover Show (will publish on Friday, 8/5). Since the tools shipped the same day as the show we literally only had an hour or so before the show to pull together a demonstration of some of the new capabilities. I think we did a reasonably good job, but I’d like to further clarify a few things in this post.

For a complete look at the updated tools, I recommend taking a look at posts by Technical Evangelists Nathan Totten and Nick Harris.  Additionally, you should review the release documentation on MSDN.

One of the items I demonstrated on the show was deploying the new MVC 3 template to Windows Azure.

Windows Azure ASP.NET MVC 3 Web Role

It’s great having this template built into the tools. No longer do I have to hit Steve Marx’s website to lookup the requisite MVC 3 assemblies.

Immediately after creating the projects I confirmed that my assemblies were all added and set to Copy Local = True by default (one of the nice aspects of having the template baked into the tools) and published to Windows Azure.  I was a bit surprised when suddenly I got the YSOD:

YSOD

Naturally, I updated my web.config file with <customErrors mode="Off" /> and redeployed to Windows Azure.

No SQL Express

In case you don’t want to click the image, the error is:

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified)"

In retrospect, I should have expected this error as I received validation warnings within Visual Studio (one of the other nice updates in the 1.4 tools):

Warning

I was quite baffled as to why MVC 3 suddenly would require SQL Express (or any flavor of SQL for that matter), until Anders Hauge—a PM on the Visual Studio team—clued me in on the fact that they have shipped the ASP.NET Universal Providers within the MVC 3 template.

For information on these providers, see Introducing System.Web.Providers – ASP.NET Universal Providers for Session, Membership, Roles and User Profile on SQL Compact and SQL Azure by Scott Hanselman for a great introduction.

It turns out that, by default, the template uses the default session state provider in ASP.NET Universal Providers as the ASP.NET session state provider, which in turn uses SQL Express (by default) to store session state.

<sessionState mode="Custom" customProvider="DefaultSessionProvider">
  <providers>
    <add name="DefaultSessionProvider" 
         type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
         connectionStringName="DefaultConnection" 
         applicationName="/" />
  </providers>
</sessionState>

Okay, so what’s the best way to get this to work?

Well, in my haste on the Cloud Cover Show, I simply uninstalled the ASP.NET Universal Provider package, which removed the custom session state provider.  Of course, once I deployed, I no longer saw the YSOD.  This is probably not the best way to go about fixing this, as the ASP.NET Universal Providers are really worth using. For a good analysis of the options, take a look at Nathan’s discussion on various ways to resolve this in his post Windows Azure Tools 1.4 Released.

In retrospect, I wish I had simply created a SQL Azure database and used it instead.  It’s pretty easy to do:

  1. In the Windows Azure Platform Management Portal, select Database and create a new database.  I called mine UniversalProviders.

    image

  2. Select the database and click the View … button to grab/copy your connection string. Note: you’ll need to remember your SQL login password.

    image

  3. In your solution, update the ApplicationServies and DefaultConnection connection strings using your SQL Azure connection string. Note: you must set MultipleActiveResultSets=True in the connection string, so be sure to add it back if you’ve copied the SQL Azure connection string from the portal.
    <connectionStrings>
      <add name="ApplicationServices" 
           connectionString="Server=tcp:YOURDB.database.windows.net,1433;Database=UniversalProviders;User ID=YOURLOGIN@YOURDB;Password=YOURPWD;Trusted_Connection=False;Encrypt=True;MultipleActiveResultSets=True;"
           providerName="System.Data.SqlClient" />
      <add name="DefaultConnection"
           connectionString="Server=tcp:YOURDB.database.windows.net,1433;Database=UniversalProviders;User ID=YOURLOGIN@YOURDB;Password=YOURPWD;Trusted_Connection=False;Encrypt=True;MultipleActiveResultSets=True;"
           providerName="System.Data.SqlClient" />
    </connectionStrings>
    
  4. Deploy to Windows Azure.

Now, when we run the applications, it works!

image

In fact, I recommend you use Database Manager from the portal …

 image

… to open up the database and see that, in fact, you now have a dbo.Sessions table in the database.

image

What’s more, if you then click Log On and setup a user, you’ll see all the membership & roles work within the MVC application in Windows Azure!

Picture

Wrapping up, apologies for not digging into this in greater depth on the show – hopefully this post helps to clarify a few things.

George Huey, when he's not writing code! Last month I blogged about the SQL Azure Migration Wizard created by George Huey.  This tool helps you to migrate your SQL Server database into SQL Azure and is available up on Codeplex.  To date, this tool has been downloaded almost a thousand times!

The number one request for the migration wizard was the ability to replicate your data up to SQL Azure (in addition to the SQL schema, which it already does).  Unfortunately, the original SQL Azure CTP didn’t support BCP, and the data migration process was very difficult and required an SSIS package to copy the data into SQL Azure.

With yesterday’s release of SQL Azure CTP 2, however, SQL Azure now supports BCP!

Minutes after CTP 2 went live, George published a new version of migration wizard that takes advantage of BCP to enable you to migrate not only your SQL Server 2005 / 2008 database objects but your data as well!  migration wizard allows you to turn on or off data migration via the application configuration file or during runtime via the options page.  When you select data migration, the export and import process can be quite lengthy.  migration wizard kicks off the export and import process on a back ground thread and will display the BCP results in the program window.  At any time during the process, you can hit the cancel button to cancel the background process.  As migration wizard processes information, it will display the results to the program window.

Here are the release notes for version 1.0 (and 1.1):

  • Added data migration via BCP. Note that when you specify your SQL Azure username, specify your user name as "username@server". Also note that data migration only works on the latest release of SQL Azure (Server Location: South Central US).
  • Modified App.Config to allow you to specify your Options. For example: If you do not want to migrate data, you can turn this off by modifying the App.Config file and changing ScriptData to false.
  • Added a cancel button so that you can cancel while processing.
  • Added a scroll toggle so that during processing you can keep the control from scrolling down to the bottom.
  • Fixed an error in BCP command to allow the passing of the SQL Server instance name.
  • Added color to the SQL results to better identify error messages.

If you’re using SQL Azure, go and grab the new version of the SQL Azure Migration Wizard!  For detailed instructions on how to use the wizard, take a look at the SQL Azure Migration Wizard whitepaper.