Maarten Balliauw {blog}

ASP.NET MVC, Microsoft Azure, PHP, web development ...

NAVIGATION - SEARCH

Book review: ASP.NET 3.5 Social Networking

image Last week, I found another book from Packt in my letterbox. This time, the title is ASP.NET 3.5 Social Networking, written by Andrew Siemer.

On the back cover, I read that this book shows you how to create a scalable, maintainable social network that can support hundreds of thousands of users, multimedia features and stuff like that. The words scalable and maintainable seem to have triggered me: I started reading ASAP. The first chapter talks about what a social network is and proposes a new social network: Fisharoo.com, a web site for salt water aquarium fanatics, complete with blogs, forums, personal web sites, …

The book starts by building a framework containing several features such as logging, mail sending, …, all backed-up by a dependency injection framework to enable fast replacement of several components. Afterwards, each feature of the Fisharoo.com site is described in a separate chapter: what is the feature, how will we store data, what do we need to do in our application to make it work?

A good thing about this book is that it demonstrates several concepts in application design using a sample application that anyone who has used a site like Facebook is familiar with. The concepts demonstrated are some that any application can benefit from: Domain Driven Design, Test Driven Design (TDD), Dependency Injection, Model-View-Presenter, … Next to this, some third-party components like Lucene.NET are demonstrated. This all is very readable and understandable, really a must-read for anyone interested in these concepts!

Bottom line of the story: it has been a while since I was enthousiast about a book, and this one clearly made me enthousiast. Sure, it describes stuff about building a social network, but I think that is only a cover for what this book is really about: building good software that is easy to maintain, test and extend.

Checking username availability with jQuery (screencast)

A new screencast has just been uploaded to the MSDN Belgium Chopsticks page. Don't forget to rate the video!

Checking username availability with jQuery

Abstract: "This screencast explains how to use jQuery and the ASP.NET MVC framework to quickly add a username availability checker to a user registration page."

kick it on DotNetKicks.com

Verifying code and testing with Pex

Pex, Automated White box testing for .NET

Earlier this week, Katrien posted an update on the list of Belgian TechDays 2009 speakers. This post featured a summary on all sessions, of which one was titled “Pex – Automated White Box Testing for .NET”. Here’s the abstract:

“Pex is an automated white box testing tool for .NET. Pex systematically tries to cover every reachable branch in a program by monitoring execution traces, and using a constraint solver to produce new test cases with different behavior. Pex can be applied to any existing .NET assembly without any pre-existing test suite. Pex will try to find counterexamples for all assertion statements in the code. Pex can be guided by hand-written parameterized unit tests, which are API usage scenarios with assertions. The result of the analysis is a test suite which can be persisted as unit tests in source code. The generated unit tests integrate with Visual Studio Team Test as well as other test frameworks. By construction, Pex produces small unit test suites with high code and assertion coverage, and reported failures always come with a test case that reproduces the issue. At Microsoft, this technique has proven highly effective in testing even an extremely well-tested component.”

After reading the second sentence in this abstract, I was thinking: “SWEET! Let’s try!”. So here goes…

Getting started

First of all, download the academic release of Pex at http://research.microsoft.com/en-us/projects/Pex/. After installing this, Visual Studio 2008 (or 2010 if you are mr. or mrs. Cool), some context menus should be added. We will explore these later on in this post.

What we will do next is analyzing a piece of code in a fictive library of string extension methods. The following method is intended to mimic VB6’s Left method.

[code:c#]

/// <summary>
/// Return leftmost characters from string for a certain length
/// </summary>
/// <param name="current">Current string</param>
/// <param name="length">Length to take</param>
/// <returns>Leftmost characters from string</returns>
public static string Left(this string current, int length)
{
    if (length < 0)
    {
        throw new ArgumentOutOfRangeException("length", "Length should be >= 0");
    }

    return current.Substring(0, length);
}

[/code]

Great coding! I even throw an ArgumentOutOfRangeException if I receive a faulty length parameter.

Pexify this!

Analyzing this with Pex can be done in 2 manners: by running Pex Explorations, which will open a new add-in in Visual Studio and show me some results, or by generating a unit test for this method. Since I know this is good code, unit tests are not needed. I’ll pick the first option: right-click the above method and pick “Run Pex Explorations”.

Run Pex Explorations

A new add-in window opens in Visual Studio, showing me the output of calling my method with 4 different parameter combinations:

Pex Exploration Results

Frustrated, I scream: “WHAT?!? I did write good code! Pex schmex!” According to Pex, I didn’t. And actually, it is right. Pex explored all code execution paths in my Left method, of which two paths are not returning the correct results. For example, calling Substring(0, 2) on an empty string will throw an uncaught ArgumentOutOfRangeException. Luckily, Pex is also there to help.

When I right-click the first failing exploration, I can choose from some menu options. For example, I could assign this as a task to someone in Team Foundation Server.

Pex Exploration Options In this case, I’ll just pick “Add precondition”. This will actually show me a window of code which might help avoiding this uncaught exception.

Preview and Apply updates

Nice! It actually avoids the uncaught exception and provides the user of my code with a new ArgumentException thrown at the right location and with the right reason. After doing this for both failing explorations, my code looks like this:

[code:c#]

/// <summary>
/// Return leftmost characters from string for a certain length
/// </summary>
/// <param name="current">Current string</param>
/// <param name="length">Length to take</param>
/// <returns>Leftmost characters from string</returns>
public static string Left(this string current, int length)
{
    // <pex>
    if (current == (string)null)
        throw new ArgumentNullException("current");
    if (length < 0 || current.Length < length)
        throw new ArgumentException("length < 0 || current.Length < length");
    // </pex>

    return current.Substring(0, length);
}

[/code]

Great! This should work for any input now, returning a clear exception message when someone does provide faulty parameters.

Note that I could also run these explorations as a unit test. If someone introduces a new error, Pex will let me know.

More information

More information on Pex can be found on http://research.microsoft.com/en-us/projects/Pex/.

kick it on DotNetKicks.com

Book review: ASP.NET 3.5 Application Architecture and Design

image The people at Packt asked it again: “Do you want to review this book?” Sure I do! The book I’m reviewing this time is ASP.NET 3.5 Application Architecture and Design, written by Vivek Thakur.

Application Architecture is always an interesting topic to read on. Different people have different opinions, there is no one perfect solution to a problem, … This book covers application architecture, applied to ASP.NET, although these concepts can be applied in any application. Questions like “What are tiers?” and “How do you structure an application?” are dug into in the first few chapters. The next chapters focus on more specific areas of application architecture: the domain model, UML, creating an ER diagram, SOA, the ASP.NET MVC framework, … Each of these concepts is explained using a single project example, which makes it easy to see the differences, pro’s and con’s of a certain solution.

To be honest, I don’t think this book is something for experienced architects or lead developers. More experienced architects will probably remain a little bit hungry because large, complex, real-world architectures are not covered or illustrated. The book covers all concepts of application architecture using a simple example, which makes them clear to any developer who is interested in architecture but has always been affraid of all these concepts.

If you are familiar with the words “N-Tier”, “domain model” and other architectural concepts, I think this book might not be covering architecture deep enough. Are you a developer wanting to release some open-source software? Unaware of the concepts mentioned? Then read this book as it is a great starter book.

CarTrackr on Windows Azure - Part 5 - Deploying in the cloud

This post is part 5 (and the final part) of my series on Windows Azure, in which I'll try to convert my ASP.NET MVC application into a cloud application. The current post is all about deploying CarTrackr in the cloud after all modifications done in previous posts.

Other parts:

Deploying CarTrackr on Azure

Deploying CarTrackr is done using the Azure developer portal. I'm creating a hosted service named "CarTrackr", which will host the cloud version of CarTrackr. I'm also creating a second storage acocunt project, used for TableStorage of all data in CarTrackr.

CarTrackr projects on Azure

To create a deployment package, the documentation states to right-click the Azure project in the CarTrackr solution, selecting "Publish...". I really hoped this would be easy. Unfortunately, this was some sort of a PITA... Great to see an Exception in the output window. Fortunately, someone had the same issue: Packaging Azure project manually when the 'Publish' action fails. The Exception seems to be thrown because the CarTrackr project is too big for the packaging system. *sigh* Starting an Azure SDK command-line and invoking the cspack.exe seemed to do the trick.

Anyway, on to uploading the generated package to Azure: the package, service configuration and deployment name should be given, after which an upload takes place.

Azure Services Developer Portal

Time to run! After browsing to http://cartrackr.cloudapp.net, I'm expecting to see CarTrackr!

CarTrackr running... NOT!

But no, Error 403 - Forbidden - Access is denied... What is wrong? My quest to host CarTrackr on Azure seems to be full of obstacles...

Deploying again!

After some hours of re-packing, re-building, re-deploying and starting to get annoyed, the solution was to change my call to cspack.exe... Not only the /bin folder should be packaged, but also all other content. My bad! Invoking C:\Users\Maarten\Desktop\CarTrackr>cspack "./CarTrackr_Azure/ServiceDefinition.csdef" /out:"./CarTrackr_Azure/CarTrackr_Azure.cspkg" /role:"Web;./CarTrackr"  was the right thing to do.

A deployment later, CarTrackr seemed to work smoothly!

CarTrackr on Azure!

And again...

Yes, again. I wrote this blog post about a week ago and decided to add Google Analytics in the live version of CarTrackr. While deploying, I decided to upload the latest version to the staging environment, and swap it with the production environment... Bad idea :-) Deployment totally killed my data storage (it seemed) and was throwing strange errors on the production URL.

Some hours later (that is: 2 hours of build, deploy, check, ..., a night sleep and some more build, deploy, check, ...), I had the strange idea of putting my production ServiceConfiguration data in the package itself. This should not be necessary, but you never know. And it is what I did with the first working production deployment. And yes, this indeed seemed to be the solution!

Check it out!

Checkout http://cartrackr.cloudapp.net for the live version. No need to sign up, only to sign in. Note: when entering a refuelling, enter the date in US English format... 

It is likely that you are going to download and play with my source code. When doing that, check out the TableStorage membership, role and session providers in the Azure SDK, which you can use in CarTrackr if you want. More on this can be found on http://blogs.msdn.com/jnak/archive/2008/11/10/asp-net-mvc-on-windows-azure-with-providers.aspx.

Looking for the Azure CarTrackr sources? CarTrackr_Azure.zip (654.98 kb)
Looking for the original CarTrackr sources? Checkout CodePlex.

Conclusion on Azure

It took me quite some hours to actually convert an existing application into something that was ready for deployment on Azure. The toughest parts were rewriting my repository code for TableStorage and getting the CarTrackr package deployed. With what I know know, I think writing an Azure application should not be more difficult than writing any other web application. The SDK provides everything you need, remember to check the samples directory for some useful portions of code.

I do have some notes though, which I hope will be used for future CTP's of Azure...

  • Your application is running fine on the development fabric?
    There's no 100% guarantee that the Azure web fabric will serve your application correctly when it runs smoothly on the development fabric. Just deploy and pray :-)
  • Viewing log files from the web fabric from the Azure Services Developer Portal would be a real time saver!
    Currently, you can copy the server logs to blob storage and then fetch the data from there, but a handy web-tool would really save some time when something goes wrong after deployment. Same story goes for TableStorage: it would be useful to have an interface to look at your data.
  • Packaging? Great, but... what if I only wanted to update one file in the application?
    I've uploaded my package about 10 times during deployment testing, which required 10 times... the full package size in bandwith! And all I wanted to do was modifying web.config...

Sidenote: funny to see that they are using OPC (Open Packaging Convention) for creating deployment packages. It shows how easy it is to create a custom file format with OPC, just like Julien Chable did for a photo viewer.

Overall, Microsoft is doing a good job with Azure. The platform itself seems reliable and stable, the concept is good. Perhaps they should consider selling the hosting platform itself to hosting firms around the globe, setting a standard for hosting platforms. Think of switching your hosting provider by simply uploading the package to another company's web fabric and modifying some simple configuration entries. Another idea: why not allow the packages developed for Azure to be deployed on any IIS server farm? 

kick it on DotNetKicks.com

CarTrackr on Windows Azure - Part 4 - Membership and authentication

This post is part 4 of my series on Windows Azure, in which I'll try to convert my ASP.NET MVC application into a cloud application. The current post is all about implementing authentication in CarTrackr.

Other parts:

Picking a solution...

In my opening post on this series, I defined some tasks which I would probably have to do prior to being able to run CarTrackr on Azure. For membership and authentication, I defined 2 solutions:  Cloudship or Windows Live ID.

At first, Cloudship looked really nice as it is just an implementation of ASP.NET's provider model based on Azure. Some thinking cycles later, this did not feel right for CarTrackr... For CarTrackr, authentication only would be enough, membership would be real overkill.

The solution I'll be using in CarTrackr is Windows Live ID. Luckily, there's some ASP.NET MVC code for that in an older release of the MVC Membership Starter Kit.

Adding Live ID to CarTrackr

First of all, add the WindowsLiveLogin.cs class from the MVC Membership Starter Kit. Also ,ake sure it can configure itself by adding the Live ID settings in web.config:

[code:c#]

<appSettings>
    <!-- See: http://msdn2.microsoft.com/en-us/library/bb676633.aspx and https://msm.live.com/app/default.aspx -->
    <add key="wll_appid" value="001600008000AF26"/>
    <add key="wll_secret" value="mvcmembershipstarterkit"/>
    <add key="wll_securityalgorithm" value="wsignin1.0"/>
</appSettings>

[/code]

Now, I always like removing code. Actually, a lot of methods can be removed from the AuthenticationController due to the fact that Live ID will take care of lost password e-mails and stuff like that. After these stripping actions, my AccountController looks like the following:

[code:c#]

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using System.Web.UI;
using CarTrackr.Core;
using CarTrackr.Repository;
using CarTrackr.Models;
using CarTrackr.Filters;

namespace CarTrackr.Controllers
{

    [HandleError]
    [OutputCache(Location = OutputCacheLocation.None)]
    [LiveLogin]
    public class AccountController : Controller
    {
        private IUserRepository UserRepository;

        public AccountController()
            : this(null, null)
        {
        }

        public AccountController(IFormsAuthentication formsAuth, IUserRepository userRepository)
        {
            FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
            UserRepository = userRepository;
        }

        public IFormsAuthentication FormsAuth
        {
            get;
            private set;
        }

        [Authorize]
        public ActionResult Index()
        {
            return RedirectToAction("Login");
        }

        public ActionResult Login()
        {
            return View("Login");
        }

        public ActionResult Logout()
        {
            FormsAuth.SignOut();

            // Windows Live ID logout...
            HttpCookie loginCookie = new HttpCookie( "webauthtoken" );
            loginCookie.Expires = DateTime.Now.AddYears( -10 );
            Response.Cookies.Add( loginCookie );

            return RedirectToAction("Index", "Home");
        }

        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.User.Identity is WindowsIdentity)
            {
                throw new InvalidOperationException("Windows authentication is not supported.");
            }
        }

        #region Live ID

        public ActionResult WindowsLiveAuthenticate()
        {
            // initialize the WindowsLiveLogin module.
            WindowsLiveLogin wll = new WindowsLiveLogin(true);

            // communication channels
            HttpRequestBase request = this.HttpContext.Request;
            HttpResponseBase response = this.HttpContext.Response;

            // extract the 'action' parameter from the request, if any.
            string action = request["action"] ?? "";

            /*
              If action is 'logout', clear the login cookie and redirect
              to the logout page.

              If action is 'clearcookie', clear the login cookie and
              return a GIF as response to signify success.

              By default, try to process a login. If login was
              successful, cache the user token in a cookie and redirect
              to the site's main page.  If login failed, clear the cookie
              and redirect to the main page.
            */
            if (action == "logout")
            {
                return RedirectToAction("Logout");
            }
            else if (action == "clearcookie")
            {

                HttpCookie loginCookie = new HttpCookie("webauthtoken");
                loginCookie.Expires = DateTime.Now.AddYears(-10);
                response.Cookies.Add(loginCookie);

                string type;
                byte[] content;
                wll.GetClearCookieResponse(out type, out content);
                response.ContentType = type;
                response.BinaryWrite(content);
                response.End();
                return new EmptyResult();

            }
            else
            {
                WindowsLiveLogin.User wllUser = wll.ProcessLogin(request.Form);

                HttpCookie loginCookie = new HttpCookie("webauthtoken");
                if (wllUser != null)
                {
                    loginCookie.Value = wllUser.Token;

                    if (wllUser.UsePersistentCookie)
                    {
                        loginCookie.Expires = DateTime.Now.AddYears(10);
                    }
                }
                else
                {
                    loginCookie.Expires = DateTime.Now.AddYears(-10);
                }

                // check for user in repository
                CarTrackr.Domain.User user = UserRepository.RetrieveByUserName(wllUser.Id);
                if (user == null)
                {
                    user = new CarTrackr.Domain.User();
                    user.UserName = wllUser.Id;
                    UserRepository.Add(user);
                }

                // log user in
                response.Cookies.Add(loginCookie);
                FormsAuthentication.SetAuthCookie(user.UserName, false);

                return RedirectToAction("Login");
            }
        }

        #endregion
    }

    // The FormsAuthentication type is sealed and contains static members, so it is difficult to
    // unit test code that calls its members. The interface and helper class below demonstrate
    // how to create an abstract wrapper around such a type in order to make the AccountController
    // code unit testable.

    public interface IFormsAuthentication
    {
        void SetAuthCookie(string userName, bool createPersistentCookie);
        void SignOut();
    }

    public class FormsAuthenticationWrapper : IFormsAuthentication
    {
        public void SetAuthCookie(string userName, bool createPersistentCookie)
        {
            FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
        }
        public void SignOut()
        {
            FormsAuthentication.SignOut();
        }
    }
}

[/code]

Yes, that's almost no code left compared to the original! Remember, Live ID will take care of all user-account-related stuff for me. The only thing I'm doing here is accepting the authentication ticket Live ID provides to CarTrackr. Yes, I'm actually registering the user on my cloud storage too, because I want to track how much users actually use CarTrackr...

One thing to notice: I've created an action filter attribute (hence the [LiveLogin] attribute on the AccountController class). The LiveLogin action filter looks like the following:

[code:c#]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using CarTrackr.Core;
using CarTrackr.Models;

namespace CarTrackr.Filters
{
    public class LiveLogin : ActionFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            WindowsLiveLogin wll = new WindowsLiveLogin(true);

            SignInViewData viewData = new SignInViewData
            {
                AppId = wll.AppId,
                UserId = GetUserId(wll, filterContext.HttpContext.Request)
            };

            filterContext.Controller.ViewData["WindowsLiveLogin"] = viewData;
        }

        public static string GetUserId(WindowsLiveLogin wll, HttpRequestBase request)
        {
            HttpCookie loginCookie = request.Cookies["webauthtoken"];

            if (loginCookie != null)
            {
                string token = loginCookie.Value;

                if (!string.IsNullOrEmpty(token))
                {
                    WindowsLiveLogin.User user = wll.ProcessToken(token);

                    if (user != null)
                    {
                        return user.Id;
                    }
                }
            }

            return null;
        }
    }
}

[/code]

What hapens in this code is actually checking for the Live ID context we are in. This context can be used in any view of CarTrackr since it is stored in the ViewData dictionary by this action filter: ViewData["WindowsLiveLogin"]. This context is used by a simple LiveIdControl (code in download later on) to render the Live ID sign in / sign out link.

Reminder for deployment...

One reminder left when deploying this to Azure: I'll have to make sure that Live ID posts the authentication ticket to the correct URL in CarTrackr. This can be done later in the Azure project management interface:

Live ID settings in Azure

Conclusion

This was a quite easy task compared to configuring TableStorage. Thank's to the MVC Membership Starter Kit, the Live ID integration was easy.

Stay tuned for the final part: deployment on Azure! I'll also provide a download link and a live link to the project.

kick it on DotNetKicks.com

CarTrackr on Windows Azure - Part 3 - Data storage

This post is part 3 of my series on Windows Azure, in which I'll try to convert my ASP.NET MVC application into a cloud application. The current post is all about implementing cloud storage in CarTrackr.

Other parts:

Types of Azure storage

Windows Azure offers 3 types of cloud storage: blobs, tables and queues. Blob Storage stores sets of binary data, organized in containers of your storage account. Table Storage offers structured storage in the form of tables. The Queue service stores an unlimited number of messages, each of which can be up to 8 KB in size.

Windows Azure Storage Account

CarTrackr will use table storage to store cars and refuellings. Table Storage is one of the simplest way to store data in Azure. All tables are accessed using a Uri in the form of http://<applicationname>.tables.core.windows.net. You need to have a storage cccount if you want to use the table storage. Waiting for an invitation? The Azure SDK contains a development storage tool which simulates all cloud table storage features on your local host: http://127.0.0.1:10002

Each storage account has a Table containg an Entity. An Entity contains Columns. Entity can be considered to be the row and Columns as values. Each Entity always contains these properties: PartitionKey, RowKey and Timestamp . The PartitionKey and RowKey identify a row or an Entity. (source)

Implementing Azure TableStorage in CarTrackr

Configuring TableStorage

First of all, we have to specify we are going to use storage in the CarTrackr application. This can be achieved by adding some configuration to the CarTrackr_Azure's ServiceConfiguration.cscfg:

[code:c#]

<?xml version="1.0"?>
<ServiceConfiguration serviceName="CarTrackr_Azure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
  <Role name="Web">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="AccountName" value="devstoreaccount1"/>
      <Setting name="AccountSharedKey" value="Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="/>
      <Setting name="TableStorageEndpoint" value="http://127.0.0.1:10002"/>
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

[/code]

When deploying, we should of course change the TableStorageEndpoint to the Azure TableStorage endpoint. Account name and key should also be modified at that moment.

Development storage

Making sure all tables exist in TableStorage

To make sure all tables exist in TableStorage, a TableStorageDataServiceContext should be defined. This TableStorageDataServiceContext should contain some TableStorageEntity items. We can easily make all domain objects in CarTrackr of type TableStorageEntity. Make sure to build the samples in the Azure SDK folder and add a reference to the StorageClient.dll in that folder.

Creating a class that is TableStorage aware is easy now: inherit the Microsoft.Samples.ServiceHosting.StorageClient.Microsoft.Samples.ServiceHosting.StorageClient class, modify the constructor and you're done. I've also modified the domain classes, making RowKey the identifier for the current object.

[code:c#]

namespace CarTrackr.Domain
{
    public partial class Car : TableStorageEntity, IRuleEntity
    {
        public Car()
            : base()
        {
            PartitionKey = Guid.NewGuid().ToString();
            RowKey = Guid.NewGuid().ToString();
        }

        // ... other code ...
    }
}

[/code]

Also add the CarTrackrCloudContext class to the CarTrackr.Data namespace. This CarTrackrCloudContext class will implement a TableStorageDataServiceContext, defining which tables are in the TableStorage.

[code:c#]

using System.Data.Services.Client;
using CarTrackr.Domain;
using Microsoft.Samples.ServiceHosting.StorageClient;

namespace CarTrackr.Data
{
    public class CarTrackrCloudContext : TableStorageDataServiceContext
    {
        public DataServiceQuery<Car> Cars
        {
            get
            {
                return CreateQuery<Car>("Cars");
            }
        }

        public DataServiceQuery<Refuelling> Refuellings
        {
            get
            {
                return CreateQuery<Refuelling>("Refuellings");
            }
        }

        public DataServiceQuery<User> Users
        {
            get
            {
                return CreateQuery<User>("Users");
            }
        }
    }
}

[/code]

This CarTrackrCloudContext tells the application there are 3 types of tables, represented by 3 domain class types. Note that the class has been inherited from TableStorageDataServiceContext, which automatically connects to the TableStorage endpoint with the account information we stored previously in the Service Configuration file.

To make sure tables exist and are up to date when the application is started, add the following to CarTrackr's Global.asax:

[code:c#]

protected static bool tablesRegistered = false;
protected static object syncLock = "";

protected void Application_BeginRequest(object sender, EventArgs e)
{
    if (!tablesRegistered)
    {
        lock (syncLock)
        {
            if (!tablesRegistered)
            {
                try {
                    StorageAccountInfo account = StorageAccountInfo.GetDefaultTableStorageAccountFromConfiguration();
                    TableStorage.CreateTablesFromModel(typeof(CarTrackr.Data.CarTrackrCloudContext), account);
                    tablesRegistered = true;
                }
                catch { }
            }
        }
    }
}

[/code]

The TableStorage client will create all requried tables based on the CarTrackrCloudContext class's IQueryable properties. Note that I'm using double-check locking here to make sure tables are only created once (performance). 

Querying data

Luckily, my repository code is not subject to much changes. Linq queries just keep working on the Azure TableStorage. Only Insert, Update and Delete are a little bit different. The CarTrackrCloudContext class represents the runtime context of ADO.NET Data Services and enables to use AddObject(), DeleteObject(), UpdateObject(), followed by SaveChanges().

Here's an example on adding a Car (CarRepository):

[code:c#]

public void Add(Car car)
{
    if (car.OwnerId == Guid.Empty)
        car.OwnerId = User.UserId;

    car.EnsureValid();

    DataSource.DataContext.AddObject("Cars", car);
    DataSource.DataContext.SaveChanges();
}

[/code]

Storage conclusions

I have actually modified my Linq to SQL classes and repository code as TableStorage currently only supports Binary, Bool, DateTime, Double, Guid, Int, Long and String. No decimals and custom types anymore... There's also some other missing features regarding ordering of data and joins which required me to change a lot of repository code. But hey, it's still only the repository code I needed to change!

Next post will be about membership and authentication. Stay tuned!

kick it on DotNetKicks.com

CarTrackr on Windows Azure - Part 2 - Cloud-enabling CarTrackr

This post is part 2 of my series on Windows Azure, in which I'll try to convert my ASP.NET MVC application into a cloud application. The current post is all about enabling the CarTrackr Visual Studio Solution file for Windows Azure.

Other parts:

Adding CarTrackr_WebRole

For a blank Azure application, one would choose the Web Cloud Service type project (installed with teh Azure CTP), which brings up two projects in the solution: a <project> and <project>_WebRole. The first one is teh service definition, the latter is the actual application. Since CarTrackr is an existing project, let's add a new CarTrackr_Azure project containing the service definition.

Right-click the CarTrackr solution and add a new project. From the project templates, pick the "Cloud Service -> Blank Cloud Service" item and name it "CarTrackr_Azure". The CarTrackr_Azure project will contain all service definition data used by Windows Azure to determine the application's settings and environment.

 Creating CarTrackr_Azure

CarTrackr solution

Great! My solution explorer now contains 3 projects: CarTrackr, CarTrackr.Tests and the newly created CarTrackr_Azure. Next thing to do is actually defining the CarTrackr project in CarTrackr_Azure as the WebRole project. Right-click "Roles", "Add", and notice... we can not promote CarTrackr to a WebRole project. Sigh!

Edit the CarTrackr.csproj file using notepad and merge the differences in (ProjectTypeGuids, RoleType and ServiceHostingSDKInstallDir):

[code:xml]

<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>9.0.30729</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{E536FB25-134E-4819-9BAC-0D276D851FB8}</ProjectGuid>
    <ProjectTypeGuids>{603c0e0b-db56-11dc-be95-000d561079b0};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>CarTrackr</RootNamespace>
    <AssemblyName>CarTrackr</AssemblyName>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <RoleType>Web</RoleType>
    <ServiceHostingSDKInstallDir Condition=" '$(ServiceHostingSDKInstallDir)' == '' ">$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\ServiceHosting\v1.0@InstallPath)</ServiceHostingSDKInstallDir>

  </PropertyGroup>
  <!-- ... -->
</Project>

[/code]

Visual Studio will prompt to reload the project, allow this by clicking the "Reload" button. Now we can right-click "Roles", "Add", "Web Role Project in Solution" and pick CarTrackr. Note that the 2 files in CarTrackr_Azure now have been updated to reflect this.

ServiceDefinition.csdef now contains the following:

[code:xml]

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="CarTrackr_Azure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="Web">
    <InputEndpoints>
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
    </InputEndpoints>
  </WebRole>
</ServiceDefinition>

[/code]

This file will later instruct the Azure platform to run a website on a HTTP endpoint, port 80. Optionally, I can also add a HTTPS endpoint here if required. For now, this definition wil do.

ServiceConfiguration.csdef now contains the following:

[code:xml]

<?xml version="1.0"?>
<ServiceConfiguration serviceName="CarTrackr_Azure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
  <Role name="Web">
    <Instances count="1" />
    <ConfigurationSettings />
  </Role>
</ServiceConfiguration>

[/code]

This file will inform Azure of the required environment for CarTrackr. First of all, one instance will be hosted. If it becomes a popular site and more "servers" are needed, I can simply increase this number and have more power in the cloud. The ConfigurationSettings element can contain some other configuration settings, for example where data will be stored. I think I'll be needing this in a future blog post, but for now, this will do.

 

Service Configuration

It's in the cloud!

After doing all configuration steps, I can simply start the CarTrackr application in debug mode.

CarTrackr in the cloud!

Nothing fancy here, everything still works! I just can't help the feeling that Windows Azure will not know my local SQL server for data storage... Which will be the subject of a next blog post!

kick it on DotNetKicks.com

Track your car expenses in the cloud! CarTrackr on Windows Azure - Part 1 - Introduction

As you may see in the title, I will be starting a series on modifying my CarTrackr sample application to a cloud-based, Windows Azure application. At this point, I don't know if it's easy nor do I know what it takes to achieve this goal. I only have some assumtions on how CarTrackr can be converted to a cloud application.

This post is part 1 of the series, in which I'll describe the architecture of Windows Azure and what I think it takes to convert my ASP.NET MVC application into a cloud application.

Other parts:

Microsoft Azure

Azure Services PlatformAt Microsoft PDC 2008, the Azure Services Platform was announced in the opening keynote. Azure is the name for Microsoft’s Software + Services platform, an operating system in the cloud providing services for hosting, management, scalable storage with support for simple blobs, tables, and queues, as well as a management infrastructure for provisioning and geo-distribution of cloud-based services, and a development platform for the Azure Services layer.

You can currently download the Windows Azure SDK from www.azure.com and play with it on your local computer. Make sure to sign-up at the Azure site: you might get lucky and receive a key to test the real thing.

CarTrackr

From my previous blog post: "CarTrackr is a sample application for the ASP.NET MVC framework using the repository pattern and dependency injection using the Unity application block. It was written for various demos in presentations done by Maarten Balliauw. CarTrackr is an online software application designed to help you understand and track your fuel usage and kilometers driven."

CarTrackr, cloud version That being said: what will it take to port this onto the Azure platform? First of all, a new logo applies. I now want a logo with clouds in it. Since it's still no official release, I'll also keep the "beta" label in place. Looks nice, eh? :-)

Seriously, here's what I think needs to be done:

Concept Current implementation Azure implementation
Data store Repository pattern on top of Linq to SQL. Repository pattern (whew!) on top of Azure TableStorage.
Membership ASP.NET membership Windows Live ID or Cloudship

In addition to the above table, I'll also have to make the CarTrackr solution aware of Azure. Next thing: make Azure aware of ASP.NET MVC... I'll also have to deploy this application in the cloud at the end. Stay tuned!

kick it on DotNetKicks.com

New Entity Framework / LINQ blog!

Just a quick recommendation note: One of my colleagues, Julien Hanssens, has started blogging on his experiences with the Entity Framework and LINQ. Here are some links to get you started:

  • Entity Framework - ArgumentException on Connection
    "A common error while initialising an EntityModel from a WCF Service is the following message: ArgumentException was unhandled by user code - The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid. "
     
  • Entity Framework and Stored Procedures
    "SQL Server has a large fanbase of stored procedures enthusiasts. Including obviously DBA's, but also developers. The latter foremost considering that with storedprocs you can easily shovel responsibility at those who are responsible for maintaining data-integrity.

    Unfortunately, the ADO.NET Entity Framework in its current version has some limitations when working with stored procedures. How to cope with this?"
     
  • LINQ and Dynamic Query Expressions
    "By tradition it was always quite a challenge to create custom filtering on objects and dynamically query databases. Or to say least a lot of work. LINQ makes this type of querying in code much easier. In this article I wish to elaborate on the "how-to" and advantages of providing a dynamic and type-safe 'engine' for developers on which you can query any random property.

    We are going to demonstrate this by using an expression tree, available from the System.Linq.Expressions namespace, to easily achieve dynamic LINQ queries for usage in your code."

kick it on DotNetKicks.com