Wednesday 27 November 2013

Open source tools we use - addendum

I realised that in my previous post I forgot to mention log4net on the list of OSS that we use at DrDoctor.  This is probably because it's like Léon - does the job quietly, professionally and you barely notice it's there.  Until you it's really important that it's there.

So yeah, just a bit of love for log4net because it got overlooked because we don't have to think about it.

Saturday 23 November 2013

Open source tools we use

At DrDoctor we're on a .NET stack (and we're Bizspark members) but that doesn't mean we don't love open source tools - what we want is the right tools - and the .NET world is full of them. We've used a few and I thought it might be useful for people to see what choices we've made.  So here goes:

1) RabbitMQ.  Correct, it's not MS, but at no point did we ever consider using MSMQ.  It's an awesome messaging infrastructure with a great .NET client.  It works and it works well.
2) EasyNetQ Fantastic light-weight, open source Bus implementation on top of RabbitMQ.  It's actively developed, well documented and we got it working in about two days.  It's at a 0.x release at the moment, so breaking changes do happen, which means we've taken a cut of the code that we're happy with (I possibly managed to push a breaking change into our build before I realised this ;)  ).  Hopefully at some point we can contribute something back.
3) Topshelf Makes working with Windows Services a pleasure.  It's used by a lot of other projects (e.g. NServiceBus) because it's great. 
4) Castle Windsor Powerful IoC with a tonne of well written documentation.
5) Magnum library We only we use one thing from this library (the State Machine) but it's at the core of our business logic. Created by the same guys who brought you Topshelf (see above).  Almost non-existent documentation, but really handy utilities.
6) Simple Data Mark Rendle's rather excellent data access library (we use it on top of SQL Server).
7) NancyFX Nice light-weight web framework (an alternative to MS's WebAPI and MVC frameworks).

Of those six seven tools I'd say that easyNetQ, Topshelf, Magnum, NancyFX & Simple Data are all about developer productivity.  Simply put, they are tools that allow us as developers to work on business features rather than infrastructure.

RabbitMQ is a fundamental architectural choice.  DrDoctor is event driven by its very nature, so a messaging infrastructure fits perfectly.  It also leads to a clean separation of concerns with components that communicate via RabbitMQ in an asynchronous fashion.  This in turn leads to a much easier development and deployment cycle: if we're working on our appointment management logic and need to deploy an update it's one component that needs to come down, while our entire application remains up.  SOA baked in from the start.

NancyFX feels more like the Python/Rails world and doesn't carry all the kludge that comes with the .NET MVC/WebAPI frameworks.  Seriously, I don't need the Entity Framework stuff.  I really, really don't.

Which really just leaves Castle.  There are loads of IoC containers out there, I just happen to feel most comfortable with Castle. 

Saturday 9 November 2013

Changing the ways queues are named in EasyNetQ

Update: In the time it took me to make the change to our code and write the blog post below, EasyNetQ got updated, thus rendering this post obsolete.  I'll soon be doing a new version that uses the latest version.

At my current company (DrDoctor) we're using EasyNetQ as a lightweight bus implementation on top of RabbitMQ. EasyNetQ has a lot of very nice features, one of which is auto-creation of exchanges and queues. It uses the fully qualified name of the message type as its basis, but we have quite a deep hierarchy of messages, which makes sense in the tree-structure of our solution, but makes looking at the queues painful as we end up with long names.

Fortunately EasyNetQ is very extensible which allows you to change those conventions (and many others). The basis for this is taken from the documention: https://github.com/mikehadlow/EasyNetQ/wiki/Replacing-EasyNetQ-Components

The 'CreateBus' method has an overload that allows you to pass in your own services. When 'CreateBus' is called, if you pass in your own service (for instance IEasyNetQLogger from the example in the documention), your service gets registered first and so the default service registration doesn't happen (take a look at DefaultServiceProvider.Register for details).

In our case we wanted to alter the way queues and exchanges are named, which is slightly more complex because there isn't a separate service for each of those, instead there is a 'Conventions' service which sets these. However, that service is itself easy to poke from the outside. Here's some code:
 IConventions conventions = new Conventions();
conventions.QueueNamingConvention = (messageType, subscriptionId) =>
{
    var queuePrefix = EasyNetQNamingConvention.GetNameFromType(messageType);
    return string.Format("{0}:{1}", queuePrefix, subscriptionId);
};

conventions.ExchangeNamingConvention = EasyNetQNamingConvention.GetNameFromType;            
RabbitHutch.CreateBus(connectionString.ConnectionString, serviceRegister => serviceRegister.Register(provider => conventions));


The method 'GetNameFromType' is a static method that returns a string, based on the type passed in.
public static string GetNameFromType(Type type)
{
 if (type.GetInterface("IMyMessage") == null)
  throw new ArgumentException("Type must implement IMyMessage");

 string category = null;

 foreach (var attr in type.GetCustomAttributes(false).OfType<MessageCategoryAttribute>())
 {
  category = attr.Category;
 }

 if (category == null)
  throw new ArgumentException("Implementation must be marked with MessageCategoryAttribute");

 return category + "_" + type.Name;
}
This suits our needs as it means we can (and indeed have to) mark up our messages with an attribute that categorises them.

There is a bit of gotcha with this, however. We have effectively replaced the use of the EasyNetQ method 'TypeNameSerializer.Serialize' for our exchanges and message queue names, which is fine, but this method is used elsewhere that could cause a problem. There is another service that is registered
.Register<SerializeType>(x => TypeNameSerializer.Serialize)
, and SerializeType is used in DefaultMessageValidationStrategy.

Again though the solution is simple, substitute in your own implementation:

RabbitHutch.CreateBus(connectionString.ConnectionString, serviceRegister =>
 {
  serviceRegister.Register(provider => conventions);
  serviceRegister.Register<SerializeType>(provider => EasyNetQNamingConvention.GetEasyNetQNameFromType);
 });
);

Sunday 1 September 2013

Wire up a chain of responsibility with Castle Windsor

As part of the greenfield project I'm currently working on I decided that I'd use the chain of responsibility design pattern, but it took me a little while to work out how to set up Castle Windsor to support this.  It's pretty simple, but the stuff I found on the interwebs all seemed to be slightly out of date, so I thought I'd explain it here.

The short version is you can use the 'DependsOn' and 'Dependency.OnComponent<T, U>' methods when registering your components to do this pretty easily.  You can use an installer that looks something like this:
public class ChainOfResponsibilityInstaller : IWindsorInstaller
{
 public void Install(IWindsorContainer container, IConfigurationStore store)
 {
  container.Register(Component.For<IChainItem>()
         .ImplementedBy<ChainItemOne>()
         .DependsOn(Dependency.OnComponent<IChainItem,ChainItemTwo>()),
         Component.For<IChainItem>()
          .ImplementedBy<ChainItemTwo>()
          .DependsOn(Dependency.OnComponent<IChainItem, ChainItemThree>()),
         Component.For<IChainItem>()
           .ImplementedBy<ChainItemThree>());
 }
}

I've put a very basic project up on GitHub - https://github.com/StephenFriend/ChainOfResponsibility-with-Castle - to demonstrate an actual working solution.

Monday 24 June 2013

Replacing Forms Authentication with the Session Authentication Module

In this post I'm going to run through how to use the SessionAuthenticationModule (SAM) (part of Windows Identity Foundation (WIF) in .Net 4.5) for authentication and authorization in a simple MVC application, replacing Forms Authentication. It won't be production code, but if after reading this you'd like to see a more complete Membership and Identity management library take a look at Brock Allen's Membership Reboot on GitHub https://github.com/brockallen/BrockAllen.MembershipReboot

The solution that goes along with this post is available at https://github.com/StephenFriend/AuthWithWIFAndSAM and it will probably be easier to look at the code as you read this. In the walkthrough below, I've used Visual Studio 2012 and there are different tagged commits, so that it's easy to see the changes that are made as we move from Forms Authentication to using the Session Authentication Module.

First, I'll set up an extremely simple solution using forms auth.  If you've cloned from github, simply type git checkout -f formsAuth

The first step is to create a new MVC4 app (imaginatively called 'DemoSite' in the code), using the 'Internet Application' Project template.  Next we want to amend the Web.config file at the root of the MVC site. 

In the controllers folder create a Home controller using the 'Empty MVC Controller' template from the drop-down in the scaffolding options section of the dialogue.  The code for the Home Controller should look like this:
[Authorize]
public class HomeController : Controller
{
 [AllowAnonymous]
 public ActionResult Index()
 {
  return View();
 }

 public ActionResult MyStuff()
 {
  return View();
 }
}

Note the use of the 'Authorize' attribute on the whole class and the 'AllowAnonymous' attribute on the 'Index()' method.  This should mean that anyone is able to access the Index view, but only users that are authorized can access the MyStuff view.

Next up let's create an Account controller.  The code for this will look like this initially:
public ActionResult Login()
{
   return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginInput model)
{
   if (ModelState.IsValid && LoginDetailsAreValid(model))
   {
    FormsAuthentication.SetAuthCookie(model.Email, false);
    return RedirectToAction("MyStuff", "Home");
   }

   ModelState.AddModelError("", "The user name or password provided is incorrect.");
   return View(model);
}

// In the real world this would be likely be a call to the database to get the user details, with a validation 
// that the user exists and that their password is correct.  See WebMatrix.WebData.SimpleMembershipProvider.ValidateUser()
// for an example (download the ASP.Net web stack here: http://aspnetwebstack.codeplex.com/)
private bool LoginDetailsAreValid(LoginInput loginDetails)
{
 return (string.Compare(loginDetails.Email, "you@example.com",
         StringComparison.InvariantCultureIgnoreCase) == 0 &&
   string.Compare(loginDetails.Password, "password", StringComparison.Ordinal) == 0);
}

In order for this to compile you'll also need to create a LoginInput class (in the Models folder), which is a simple View Model that we'll use to create the login view and user input.  It should look like this:
public class LoginInput
{
 [Required]
 public string Email { get; set; }
 [Required]
 [DataType(DataType.Password)]
 public string Password { get; set; }
}

The end point of this first stage is to create the views that go with the various controller actions. Home/Index looks like this:
@{
    ViewBag.Title = "Index";
}

Welcome to the demo

@Html.ActionLink("Login", "Login", "Account") @Html.ActionLink("My Stuff", "MyStuff", "Home")

Account/Login looks like this:
@model DemoSite.Models.LoginInput

@{
    ViewBag.Title = "Login";
}

Login

@if (User.Identity.IsAuthenticated) { You are already logged in as @User.Identity.Name
} else { using (Html.BeginForm()) { @Html.ValidationSummary()
@ViewBag.Title @Html.EditorForModel()
} }

and Home/MyStuff looks like this:
@{
    ViewBag.Title = "MyStuff";
}

Congratulations, you're authenticated


If you start up the website now, you should be able to log in (as you@example.com, password = 'password') and if you check your cookies, you will see that a cookie called .ASPXAUTH has been created.  If you try to access Home/MyStuff without logging in you will be automatically redirected back to Account/Login

Now, we're going to stop using Forms Authentication, initially not replacing it with anything.  (Use git checkout -f noAuth to see the code in the repo).

To start, go to the web.config file and change the authentication node from:

  

to:

This means that the FormsAuthenticationProvider module will no longer be loaded at application start-up.  Once you've done this, you'll see that if you log on you'll be presented with a 401 error when you are redirected to 'MyStuff'.  If, however, you check your cookies, you'll see that the call to FormsAuthentication.SetAuthCookie in the AccountController has set a cookie, but there is no provider specified so the 401 error is displayed on actions that have an 'Authorize' attribute.

In order to use the SAM module you will need to alter your web.config so that includes the following elements in the <config sections> element:

The first of these is to "configure a service or application to use Windows Identity Foundation" [1], the second names the configuration section for federation configuration, which you'll need to add to the config file:

    
      
    
  

The default configuration requires SSL, so you will need this section if you don't want to sort out setting up SSL for this example.

Under <system.webServer><modules> you will need to add the following so that the SessionAuthenticationModule is added to the ASP.Net pipeline.:


In order to have access to the classes you have just configured, you will also need to add references to System.IdentityModel and System.IdentityModel.Services to your project.

Finally, you need to alter the Account controller to look like this:
public class AccountController : Controller
    {
       public ActionResult Login()
       {
           return View();
       }

       [HttpPost]
       public ActionResult Login(LoginInput model)
       {
           if (ModelState.IsValid && LoginDetailsAreValid(model))
           {
               WriteAuthCookie(model.Email);
               return RedirectToAction("MyStuff", "Home");
           }

           ModelState.AddModelError("", "The user name or password provided is incorrect.");
           return View(model);
       }

        // In the real world this would be most likely be a call to a database to get the user details, with validation 
        // that the user exists and that their password is correct.  See WebMatrix.WebData.SimpleMembershipProvider.ValidateUser()
        // for an example (download the ASP.Net web stack here: http://aspnetwebstack.codeplex.com/)
        private bool LoginDetailsAreValid(LoginInput loginDetails)
        {
            return (string.Compare(loginDetails.Email, "you@example.com",
                                   StringComparison.InvariantCultureIgnoreCase) == 0 &&
                    string.Compare(loginDetails.Password, "password", StringComparison.Ordinal) == 0);
        }

        private void WriteAuthCookie(string userEmail)
        {
            var claims = new List();
            claims.Insert(0, new Claim(ClaimTypes.Name, userEmail)); 
            var claimsId = new ClaimsIdentity(claims, "Password");
            var cp = new ClaimsPrincipal(claimsId);
            var sam = FederatedAuthentication.SessionAuthenticationModule;
            var token = new SessionSecurityToken(cp);

            sam.WriteSessionTokenToCookie(token);
        }
    }

As you can see the new WriteAuthCookie method deals with persisting the authentication details to a cookie.  In it we create a new Name claim (the only claim we use in this example), that is then used to create a ClaimsIdentity, which in turn is used to create a new ClaimsPrinciple that is then persisted to a cookie.
Once you have logged in, if you check your cookies, you should see that you have a new 'FedAuth' cookie, which is what the SAM module uses.  If you then go back to Account/Login you should see that the claim of 'Name' is used for the User.Identity.Name property that is displayed on that page if you're logged in.

[1] http://msdn.microsoft.com/en-us/library/hh568638.aspx - MSDN WIF Configuration Schema

Monday 10 June 2013

How not to manually manage Garbage Collection

Sometimes code tells you something about the person that wrote it.  I've had the pleasure of working with a codebase that contains the following code*:
while (MainApplicationWork())
{
 GC.Collect();
 GC.WaitForPendingFinalizers();
 GC.Collect();
 GC.WaitForPendingFinalizers();
}

NullMyObjectGraph();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers(); 

Which I think bears some scrutiny - whenever you see a call to GC.Collect your .Net spidey sense should be going bonkers.

Code like this is dotted throughout the suite of applications this snippet comes from, specifically this:

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();

which implies that this is standard practice for the dev that wrote it, rather than the response to a problem.  It's conceivable that this person has done a lot of performance tests and could demonstrate that all the calls to GC.Collect are justified.  Or more formally, it's a logical possibility, like the sky being green or everyone from Birmingham having six fingers on their right hands.

Unfortunately because the code is proprietary I can't share the full horror and give the performance metrics to demonstrate how truly awful this is - for instance, the application that contains the top snippet calls GC.Collect() at least four times for every iteration of the while loop.  However what I can do is examine this code, look at why you might do something like this and try to show that the code tells you that the person who wrote it doesn't really understand it.

There are many sources that tell devs to not call GC.Collect() [1, 2], however there are some circumstances when it might be the right thing to do.  According to Microsoft you should "Use the Collect method when there is a significant reduction in the amount of memory being used at a defined point in your application's code."[3]  Rico Mariani also offers this piece of advice for when you might call GC.Collect, "if some non-recurring event has just happened and this event is highly likely to have caused a lot of old objects to die."[4]

At first glance this code doesn't seem to fit that last piece of advice, since it sits in a while loop, however the method that is used for the loop termination criterion (MainApplicationWork()) effectively returns false when there are no more records for the application to process.  Those records do not arrive in a regular fashion, so it is arguable that this is an event that occurs repeatedly, but is irregular (perhaps akin to the canonical example of a user closing a windows form - it might happen multiple times, but it's not a predictable event and so the GC algorithm self-tuning will not work).

When the call to GC.Collect() is made it "Forces an immediate garbage collection of all generations."[5]  Part of this process involves moving pointers from the finalization queue to the freachable queue for all objects with Finalizer methods that have been found to be garbage (i.e. are unreachable).  Interestingly this resurrects the objects you are trying to get rid of because there is now a reachable reference to them (on the freachable queue, which is considered a root) and they will only become unreachable again once their finalizers have been run by the Finalization thread (which runs automatically whenever there are objects in the freachable queue).

Because of this it is recommended[6] to call GC.WaitForPendingFinalizers after GC.Collect as this forces the current thread to wait until all the finalizers in the objects you are trying to clear up have been executed and thus avoids the objects getting promoted to Gen1.  Given that we've just resurrected some objects, it is recommended to call GC.Collect again to finally release the memory of all the objects that have just been finalized. So you should end up with:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

But in this codebase there is a further call to GC.WaitForPendingFinalizers which does, ummmm, precisely nothing since the only compaction/garbage collection that takes place as part of the second call to GC.Collect() is of the objects on the heap that have just been finalized.  Nothing else has changed in the application in the meantime since both GC.Collect() and GC.WaitForPendingFinalizers() block the current thread.

Does it do any harm?  Probably not (although that requires some actual performance metrics to be confident on), but what it does shout is that this snippet is a piece of cargo-cult programming, repeated through a codebase, no doubt with the best of intentions, but almost certainly for no good reason and very likely damaging application performance.


* more or less - the application method names have been changed to protect the innocent
1. http://blogs.msdn.com/b/ricom/archive/2003/12/02/40780.aspx - Rico Mariani "Two things to avoid for better memory usage"
2. http://msdn.microsoft.com/en-us/library/ff647790.aspx - MS Patterns & Practices "Improving Managed Code Performance"
3. http://msdn.microsoft.com/en-us/library/bb384155.aspx - MSDN "Induced Collections"
4. http://blogs.msdn.com/b/ricom/archive/2004/11/29/271829.aspx - Rico Mariani "When to call GC.Collect()"
5. http://msdn.microsoft.com/en-us/library/xe0c2357.aspx - MSDN Library GC.Collect definition
6. http://msdn.microsoft.com/en-us/library/ff647790.aspx - MS Patterns & Practices "Improving Managed Code Performance"

Sunday 26 May 2013

AngularJS Tutorial and .Net Web API (part 5)

In this blog post I'll look at getting steps 9, 10 & 11 of the AngularJS tutorial running on top of the .Net Web API (http://docs.angularjs.org/tutorial/step_09 http://docs.angularjs.org/tutorial/step_10). None of these tutorials requires changes to the .Net code, so this should be fairly straightforward.

First step 9. Do the usual git checkout thing one, other or both the original AngularJS tutorial code and this version. git checkout -f step9 for the .net version.

Copy app/js/filters.js from the Angular tutorial into the Scripts directory of the .Net project. Update Scripts/app.js to register the dependency on the phonecatFilters module. Update Views/Home/Index.cshtml to include a reference to the new Scripts/filters.js file. Update the Angular template (AngularPartials/phone-detail.html) to use the new filter. Ummm, that's it - behold the cross or the tick under GPS and Infrared on the phone-detail page.

On to step 10 - for the .Net code use git checkout -f step10.
Just follow along with the AngularJS tutorial. Update Scripts/controllers.js and update the template AngularPartials/phone-detail.html to change the main image source and add the 'ng-click' attribute to the smaller images. Finally copy across the latest version of app/css/app.css so that you get the cursor changing to 'pointer' when hovering over the click-able images.

And so finally onto step 11.

This tutorial is about tidying up the Angular code so that some of the implementation details are abstracted away, in effect moving the call to the .Net Web API to a different place. As such it means we don't need to touch the .Net code, however there is a change to the way in which AngularJS makes its requests, which needs a bit of attention.

Working along with the original AngularJS tutorial, amend Views/Home/Index.cshtml to include references to Scripts/services.js and Scripts/angular-resource.js. This latter should exist already (coming down with the nuget package), but you'll need to copy the services file into the Scripts directory. You'll also need to amend the registration of the 'Phone' service in the Scripts/services.js file to reference the Web API controller.
angular.module('phonecatServices', ['ngResource']).
    factory('Phone', function($resource){
         return $resource('api/phones/:phoneId', {}, {
            query: {method:'GET', isArray:true}
  });
});
Note the slight differences here from the AngularJS tutorial. First the path is to api/phones, secondly when the 'query' is set up I've removed the paramDefaults array because in its original state it causes Angular to make an http request to api/phones/phones when there is no parameter specified, which we don't want because that makes the Web API try to return us a PhoneDetail item with the id 'phones'. In the original tutorial this will cause a call to /phones/phones.json which works perfectly.

Now you just need to register the services in app.js, then amend the Scripts/controllers.js to use the service. This should be exactly the same as the Angular tutorial.

That's it - hopefully the AngularJS tutorial now looks the same live demo http://angular.github.io/angular-phonecat/step-11/app/#/phones

Friday 24 May 2013

AngularJS Tutorial and .Net Web API (part 4)

In this post I'll get step 8 of the AngularJS tutorial http://docs.angularjs.org/tutorial/step_08 running on top of the .Net Web API.  This tutorial uses more data, so we'll be plumbing in further ApiController actions to connect the Angular code to the data source (JSON text files).  I'll also take a look at some of the under-the-covers stuff about how the ApiController works when resolving requests to actions.

The code for the Web API can be got by using git checkout -f step8.

As per the Angular tutorial, use git to checkout out step 8 of the original tutorial, then copy all the phone model json files from app/phones (i.e. everything apart from phones.json, which you should have edited previously and don't want to overwrite).  Unfortunately all of these files contain a reference to an image file that won't work with our website directory structure, so you'll need to amend the paths in the 'images' section of the JSON files so that the paths point to "Content/img/phones" rather than "img/phones".

Following along with the original tutorial we're going to update the Angular controller (Scripts/AngularControllers/controller.js) so that it makes an http get request for the data the phone-detail view requires.  However it's going to call an action on our Phones controller, rather than make a direct call to a JSON file.  So the function call should look like this:
function PhoneDetailCtrl($scope, $routeParams, $http) {
    $http.get('api/phones/' + $routeParams.phoneId).success(function (data) {
        $scope.phone = data;
    });
}
Once again the path is to 'api/phones' so we'll be calling the Phones controller.  Note that we're also passing the phoneId, which in this case is a string.

Now update the AngularPartials/phone-detail.html file so that it matches the one from the AngularJS tutorial (app/partials/phone-detail.html).

In order for this to work we will need to update the PhonesController class so that it has a method that can respond to this call.
public PhoneDetail GetPhoneBy(string id)
{
 return this.phoneRepo.GetBy(id);
} 
There are a couple of things to note here.  First and most obviously, there's no 'PhoneDetail' class or GetBy(id) method on the repository - we'll add those in shortly.  More subtly, it's also worth thinking about what the ApiController does when it receives a Get request.  The base ApiController class uses a convention whereby it will try to match requests to method names that contain the the request type and the route parameters, (in this case 'Get' and a string).  What this means is that you cannot have two methods names that contain the same request verb (in this case 'get') that have the same signature in your ApiController.  It also implies that it doesn't matter what your methods are called from the application's point of view, those method names are really just for your benefit. 

If you do have two methods with the request type in their name and the same signature, the framework will throw a System.InvalidOperationException which will be caught and transformed into a 500 error response. For further detail download the code from http://aspnetwebstack.codeplex.com/ and take a look at System.Web.Http.Controllers.ActionSelectorCacheItem.SelectAction. Look for:
throw Error.InvalidOperation(SRResources.ApiControllerActionSelector_AmbiguousMatch, ambiguityList);
and
System.Web.Http.Dispatcher.SendAsync
Ultimately this means that Angular will return an empty template and you'll have to track down what the 500 error means.

Having said that, our controller has a single 'Get' method that takes a string as a parameter, so no issues there. It then calls a non-existent method on the repository class.  So, let's update the repository interface and implementation accordingly.
public interface IPhoneRepository
{
 IEnumerable<Phone> GetAll();
 PhoneDetail GetBy(string id);
}

public class FileDrivenPhoneRepository : IPhoneRepository
{
 public IEnumerable<Phone> GetAll()
 {
  string dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();
  var phonesText = System.IO.File.ReadAllText(dataDirectory +"/phones.json");
  return JsonConvert.DeserializeObject<List<Phone>>(phonesText);
 }

 public PhoneDetail GetBy(string id)
 {
  string dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();
  var phoneText = System.IO.File.ReadAllText(dataDirectory + "/" + id + ".json");
  return JsonConvert.DeserializeObject<PhoneDetail>(phoneText);
 }
}
Finally I'll create a new PhoneDetail Model (or ViewModel if you prefer).  Add a class 'PhoneDetail' to the Models folder:
public class PhoneDetail
{
 public string additionalFeatures { get; set; }
 public AndroidDetail android { get; set; }
 public string[] availability { get; set; }
 public BatteryDetail battery { get; set; }
 public CameraDetail camera { get; set; }
 public ConnectivityDetail connectivity { get; set; }
 public string description { get; set; }
 public DisplayDetail display { get; set; }
 public HardwareDetail hardware { get; set; }
 public string id { get; set; }
 public string[] images { get; set; }
 public string name { get; set; }
 public SizeAndWeightDetail sizeAndWeight { get; set; }
 public StorageDetail storage { get; set; }

 public class AndroidDetail
 {
  public string os { get; set; }
  public string ui { get; set; }
 }

 public class BatteryDetail
 {
  public string type { get; set; }
  public string talkTime { get; set; }
  public string standbyTime { get; set; }
 }

 public class CameraDetail
 {
  public string[] features { get; set; }
  public string primary { get; set; }
 }

 public class ConnectivityDetail
 {
  public string bluetooth { get; set; }
  public string cell { get; set; }
  public bool gps { get; set; }
  public bool infrared { get; set; }
  public string wifi { get; set; }
 }

 public class DisplayDetail
 {
  public string screenResolution { get; set; }
  public string screenSize { get; set; }
  public bool touchScreen { get; set; }
 }

 public class HardwareDetail
 {
  public bool accelerometer { get; set; }
  public string audioJack { get; set; }
  public string cpu { get; set; }
  public bool fmRadio { get; set; }
  public bool physicalKeyboard { get; set; }
  public string usb { get; set; }
 }

 public class SizeAndWeightDetail
 {
  public string[] dimensions { get; set; }
  public string weight { get; set; }
 }

 public class StorageDetail
 {
  public string flash { get; set; }
  public string ram { get; set; }
 }
}
Once again that I'm going with the convention of Camel case in my C# class to reduce the amount of work I have to do with the copied code for the Angular templates.  Also, I'm struck again by how clever newtonsoft json library is when it comes to transforming a fairly intricate object structure to and from JSON.  I guess that's  why MS use it under the hood.

Finally you'll need to update the CSS in Content/app.css to match what's in app/css/app.css in the Angular tutorial.

Hopefully you now have a working version of step8 of the AngularJS tutorial.

Monday 20 May 2013

AngularJS Tutorial and .Net Web API (part 3)

This is the third post in a series about using the .Net Web API to run the AngularJS tutorial app on. So far all that's happened is we've created a project that runs step5 of the tutorial.

In this post I'll move onto steps 6 & 7 http://docs.angularjs.org/tutorial/step_06 & http://docs.angularjs.org/tutorial/step_07
Step 6 of the AngularJS tutorial is about updating the template to use images and generate links to individual phones that for the moment don't go anywhere.

Check out step 6 with git checkout -f step6

If you look at app/index.html in the original tutorial directory (or just follow the AngularJS tutorial) you'll see that the content of the 'li' element has changed. Simply copy the new code over the top of the old:
  • {{phone.name}} {{phone.snippet}}
  • In order for this to work, you'll need to update your css, add the images to the project and amend the JSON phones document so that the path to the images is correct.
    So first grab the css from the app/css/app.css and paste it into Content/app.css. Then, create a new 'img' folder in the 'Content' folder of your .Net project. Within that create a 'phones' folder then copy the images from the Angular tutorial directory ('app\img\phones') into this new folder.

    If you try to run the application, no images will be rendered on the page because the paths don't match, so you'll need to update your JSON data file accordingly. Simply substitute img/ for Content/img/ in App_Data/phones.json. If you run the application now, you should see the same page as you do on the AngularJS tutorial live demo http://angular.github.io/angular-phonecat/step-6/app/
    If you click on any of the links, you'll soon realise that they don't work.

    Step7
    Onto step 7, which has much more of the meat of what AngularJS is all about, using Angular's routing capabilities in conjunction with different views and controllers. Again, if you're used to .Net MVC then everything here should be pretty easy to get your head around, but it's definitely the point for me at which I started thinking, "why am I using 2 sets of routing?" I'm not sure I have an answer yet, but I could imagine a hybrid app which has both .Net MVC and Angular MVC in it.

    use git checkout -f step7.

    Again, checkout the correct step of the AngularJS tutorial, then copy app/js/app.js into the 'Scripts' folder at the root of the .Net MVC project. This defines the routes and controllers for Angular's MVC structure.

    Next, update Views/Home/Index.cshtml so that it now has at the top and has a reference to after the reference to angular.js in the head (remember that Views/Home/Index.cshtml is pretty much exactly the same as app/index.html in the AngularJS tutorial). Finally, delete most of the content in the body of Index.cshtml and replace it with

    Now, create a new folder called 'AngularPartials' at the root of your .Net MVC project and add two HTML files to it, 'phone-list.html' and 'phone-detail.html', these should be exactly the same as the Angular app/partials/phone-detail.html and app/partials/phone-list.html files. Now you just need to update the Scripts/app.js file to reflect the paths to those partials, so it should look like this:
    angular.module('phonecat', []).
      config(['$routeProvider', function($routeProvider) {
      $routeProvider.
          when('/phones', {templateUrl: 'AngularPartials/phone-list.html',   controller: PhoneListCtrl}).
          when('/phones/:phoneId', { templateUrl: 'AngularPartials/phone-detail.html', controller: PhoneDetailCtrl }).
          otherwise({redirectTo: '/phones'});
    }]);
    


    Note that the only changes are to the 'templateUrl:' values. Amend 'Scripts/controllers.js' to include the definition for PhoneDetailCtrl
    function PhoneDetailCtrl($scope, $routeParams) {
    $scope.phoneId = $routeParams.phoneId;
    }

    The application should now be working, with links to the 'TBD' view for the phone details.

    Wednesday 15 May 2013

    AngularJS Tutorial and .Net Web API (part 2)

    This post builds on the previous post about running the AngularJS tutorial application on top of the .Net Web API Framework.  All it's going to do is tidy things up a bit, introducing a repository for the controller to get the data from, rather than it having hard-coded JSON.  Along the way we'll use the DependencyResolver so that our controller isn't creating its own dependencies.

    You should be able to see all the code by using 'git checkout -f step5b'.  Once again, you can either just read the code in its finished state, or work from scratch.

    First let's set up our data source, copy the file 'app/phones/phones.json' from the AngularJS tutorial directory to the App_Data folder in the MVC project directory.

    In the models directory create a new 'Phone.cs' class.  Because of the conventions used by the JSON serialization library, either the 'Models/Phone' class can use Camel case for its properties, or you can change the 'Scripts/AngularControllers/controller.js' file and the 'Views/Home/Index.cshtml' file so that the property names use Pascal case to match your model class.  No-one dies either way.  I've chosen to make the C# class match the AngularJS tutorial, because I only have to make the change in one place, the compiler can warn me of any problems if I use the wrong case somewhere else and I won't keep having to change the other files as I work through the AngularJS tutorial.

    public class Phone
    {
    	public int age { get; set; }
    	public string carrier { get; set; }
    	public string id { get; set; }
    	public string imageUrl { get; set; }
    	public string name { get; set; }
    	public string snippet { get; set; }
    }


    Create a data access folder at the root of the project and in it create an IPhoneRepository.cs file.  This should contain the IPhoneRepository interface that has a single method, GetAll()
    namespace AngularJSTutorial.DataAccess
    {
        public interface IPhoneRepository
        {
            IEnumerable<Phone> GetAll();
        }
    }
    

    In the same folder create a FileDrivenPhoneRepository class that implements IPhoneRepository.  This concrete implementation will read from the JSON file (our data store) in the App_Data.

    using System;
    using System.Collections.Generic;
    using AngularJSTutorial.Models;
    using Newtonsoft.Json;
    
    namespace AngularJSTutorial.DataAccess
    {
        public class FileDrivenPhoneRepository : IPhoneRepository
        {
            public IEnumerable<Phone> GetAll()
            {
                string dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();
                var phonesText = System.IO.File.ReadAllText(dataDirectory +"/phones.json");
                return JsonConvert.DeserializeObject<List<Phone>>(phonesText);
            }
        }
    }

    Next amend the PhonesController so that its constructor has an IPhoneRepository as a parameter and the 'GetAll' method uses that repository to get it's list of phones:
     public class PhonesController : ApiController
        {
            private readonly IPhoneRepository phoneRepo;
    
            public PhonesController(IPhoneRepository phoneRepo)
            {
                this.phoneRepo = phoneRepo;
            }
    
            public IEnumerable<Phone> GetAll()
            {
                return this.phoneRepo.GetAll();
            }
        }
     
    Make sure you add the relevant 'using' statements as well, or the project won't compile.

    Now you just need to ensure that the IPhoneRepository dependency is injected.  Create a folder called 'Infrastructure' at the root level of the project and add a class to it called 'SimpleResolver' (or think of a good name).  This class will implement the IDependencyResolver and will do one thing only - it will construct the PhonesController class and manage its dependencies (well, 'dependency' in this case).
    public class SimpleResolver : IDependencyResolver
        {
            public IDependencyScope BeginScope()
            {
                return this;
            }
    
            public object GetService(Type serviceType)
            {
                if (serviceType == typeof (PhonesController))
                {
                    var repo = new FileDrivenPhoneRepository();
                    return new PhonesController(repo);
                }
    
                return null;
            }
    
            public IEnumerable<object> GetServices(Type serviceType)
            {
                return new List<object>();
            }
    
            public void Dispose()
            {
                
            }
        }


    Finally we need to make sure that this is what the application uses when creating the PhonesController, so add the following line to the Application_Start() method of the Global.asax.cs file:
    GlobalConfiguration.Configuration.DependencyResolver = new SimpleResolver();


    Also ensure that you have the following 'using' statement at the top of the file:
    using AngularJSTutorial.Infrastructure;


    If you're familiar with creating your own ControllerFactory as part of a .Net MVC website, this probably feels pretty similar.

    While we're now in the slightly odd position of deserializing a JSON file only to let the framework re-serialize it in order for AngularJS to use it, I think this represents a more usual scenario of how the framework can be used - most likely your application will sit on top of a database of some sort and your repository will pull out the required data from that.

    It's worth noting the bit of magic that the framework performs in the PhonesController now, where it automatically serializes the objects to JSON.  This is because the Scripts/controller.js method 'PhoneListCtrl' calls $http.get(), which under the covers sets the Accept header of the request to 'application/json, text/plain, */*'.  When the Web API receives a request it interrogates the Accept header in order to decide what kind of formatter it should use to serialize data for the response and ultimately uses the Newtonsoft.Json library for the serialization to JSON.

    AngularJS Tutorial and .Net Web API (part 1)

    This is the start of a series of posts aimed at getting the official AngularJS tutorial running on top of the .Net Web API framework . 

    I would probably suggest doing the whole AngularJS tutorial first, however you could start with http://docs.angularjs.org/tutorial/step_00, following the instructions and the tutorial up to our jumping off point, step 5 (http://docs.angularjs.org/tutorial/step_05 XHRs and Dependency Injection) and then follow both these posts and the AngularJS tutorial at the same time (which you'll probably need to do anyway).

    In this first post I'll get the code running using the Web API and in the next one I'll tidy things up a bit so that the solution uses a few more of the features of the .Net Web framework.  You can clone the code from github 'git clone git@github.com:stevef4000/angular-and-web-api.git'. 

    There are a couple of missing references  - Newtonsoft.Json and Microsoft.Web.Mvc.FixedDisplayModes - as they were added in the packages folder, which is excluded by the .gitignore file.  The missing Newtonsoft reference will cause the build to fail, so use NuGet to search for Json.Net and install it.  (You can search for FixedDisplayModes and install that as well, but it shouldn't affect the code).

    If you just want to read the finished code, use 'git checkout -f step5' to get the correct commit that matches this post. Or you can follow this post in conjunction with the AngularJS tutorial and work from scratch.

    So, if you were going from scratch you would ...
    Create a new ASP.Net MVC4 Web Application "AngularJSWithWebAPI" using the 'Empty' template.  Use NuGet to install AngularJS.  You should now see a 'Scripts' folder at the root level of your website which contains a lot of Angular code.  (Note that the location of this code is not in keeping with the file structure for the Angular Seed project, but I will stick with this for these blog posts.  In terms of file layout, this may well not be the 'correct' way to do things.  The code still works though).

    Add a new controller 'Home' to the controllers folder.  Choose the 'Empty MVC controller' template.
    Add the matching 'Index' view for the automatically created ActionResult 'Index'.  Uncheck the 'Use a layout or master page' check-box, as we're just going to focus on the interaction bedtween AngularJS and the WebAPI so we'll keep the project very simple - one page/file that contains all the references it requires. Paste the code from the AngularJS 'app/index.html' file into your Home/Index.cshtml view.

    Copy the 'app/js/controllers.js' file from the Angular tutorial directory into the 'Scripts' directory
    Change the 'script src' tags in the head of the Index.cshtml view to:

      <script src="~/Scripts/angular.js"></script>
      <script src="~/Scripts/controllers.js"></script> 

    Add a new folder called 'Content' to the root level of your MVC project.  Copy the app/css/app.css and bootstrap.css files from the AngularJS project to this folder and add them (via add existing item) to your project).  Change the link to the stylesheets at the top of the Index.cshtml file to:
      <link rel="stylesheet" href="~/Content/app.css">
      <link rel="stylesheet" href="~/Content/bootstrap.css">
     
    Again, we're not using the power of the .Net MVC framework to use script and style bundles here, because I want to focus on getting the application using the Web API without a lot of other magic going on.
     
    Add a new controller 'Phones' to the controllers folder.  Choose the 'Empty API controller' template.  Create a new method 'GetAll', that looks like this:
    public HttpResponseMessage GetAll()
    {
     return new HttpResponseMessage
      {
       Content = new StringContent(_rawJson, Encoding.UTF8, "text/html")
      };
    }


    The private variable _rawJson comes directly from the 'app/phones/phones.json' file in the AngularJS repo and is best got from the code in the git repo (as it's so big and ugly I don't want to paste it here). This method simply returns a string to the client-side app, bypassing the cleverness of the WebAPI.

    Your application should now work and look like the live demo of the application http://angular.github.io/angular-phonecat/step-5/app/

    What we've done is to neatly side-step all the clever JSON formatting that the framework gives us in order to get the tutorial up and running as quickly as possible, while at the same time keeping it very similar to the original AngularJS tutorial.  In a real-world application you wouldn't have a massive string sitting in your controller (I hope).  In the next post, I'll move to something a bit more maintainable that uses the smarts of the Web API to better effect.