Continuous Delivery

No Gravatar

Fredrik Normén på Squeed kommer den 30:e April att prata om Continuous Delivery och hans erfarenheter kring området i det projekt han sitter i just nu för ett finansbolag. Ni kommer att få grundläggande förståelse kring begreppet Continuous Delivery, samt hur Fredrik och hans team har valt att lösa vissa problem i sitt utvecklingsteam, allt från process, källkodshantering, branchning, automatisering etc,  detta med hjälp av Microsoft Team Foundation Server 2012 och NuGet samt andra verktyg och hack!

Detta är ett event via Swenug som sponsras av Squeed AB.

Anmäl er här:

http://www.swenug.se/events/gbg-continuous-delivery

Global Windows Azure Bootcamp på Squeed HQ

No Gravatar

Lördagen den 27:e Apirl kommer Global Windows Azure Bootcamp att genomföras runt om i världen, över 90 st platser. Vi på Squeed tillsammans med SweNug har valt att sponsra och vara med och arrangera denna bootcamp i Göteborg. Det blir en dag med labbar, så ni som är nyfikna på Windows Azure så är detta är ett bra tillfälle att få möjlighet att testa på och labba med Microsoft cloud services.

Vi börjar kl 10:00 och håller på fram till kl 15:00.

Det finns dock bara 20 platser, så försten till kvarn.

http://www.swenug.se/events/global-windows-azure-bootcamp

OWIN and Razor

Just for fun added a simple support for using Razor together with OWIN. You can read a little bit about OWIN on my previous blog post.

I wanted my example to be similar to the MVC pattern, so I can use a Model, Controller (in this case I use a simple method) and a View. My Model is simple:

    public class Customer
{

        public int Id { get; set; }

        public string Name { get; set; }
}

 

The "Controller" I use will only return the Model, but I can also return a IView and specify which view to be used to render my model. By default convention is used, so the name of the returned Model will be the name of the View to use. Here is my "Controller":

 

    public Customer ListCustomer()
{

       return new Customer() { Id = 1, Name = "John Doe" };
}

 

It just return a new Customer with the name "John Doe".

To configure the use of Razor with OWIN and to setup "routes", I created a RazorConfig class. By using its Get property, I can map a "route" to a "Controller". Here is the RezorConfig class:

 

     public class RazorConfig
{
private readonly Dictionary<string, Func<object>> _get = new Dictionary<string, Func<object>>();

        private IViewLocator _viewLocator;
private IViewParser _viewParser;

        public IDictionary<string, Func<object>> Get
{
get { return _get; }
}

        public IViewLocator ViewLocator
{
get
{
if (_viewLocator != null)
return _viewLocator;

                return new RazorViewLocator();
}
set
{
_viewLocator = value;
}
}

public IViewParser ViewParser
{
get
{
if (_viewParser != null)
return _viewParser;

                return new RazorViewParser();
}
set
{
_viewParser = value;
}
}
}

 

 

The RazorConfig can also be used to specify a custom view locator and a custom view parser. The RazorViewLoctor I have created will look for views in a Views folder. The RazorViewParser will use RazorEngine.

Here is the Startup.cs where I configure the "routes" with the RazorConfiguration:

 

   public class Startup
{
public void Configuration(IAppBuilder app)
{
var razorConfig = new RazorConfig();

            razorConfig.Get["/customer"] = ListCustomer;
razorConfig.Get["/user"] = ListUser;

            app.UseRazor(razorConfig);
}
}

 

The Get property of the RazorConfig will be sued to configure the "controllers" to be used for HTTP Get of a specific "route".

If I do a HTTP GET, e.g. GET http://localhost/customer", the ListCustomer will be invoked. The ListCusomer returns a Customer, so a view with the name Customer.cshtml will be used to render the returned Customer model.

I have created an extension method for the IAppBuilder, UseRazor. UseRazor takes the RazorConfig as a parameter:

 

    public static class RazorExtensions
{
public static void UseRazor(this IAppBuilder builder, RazorConfig razorConfig)
{
if (builder == null)
throw new ArgumentNullException("builder");

            builder.Use(new Func<object, object>(ignored => new Razor(razorConfig)));
}
}


The extension will use the class Razor. The class Razor will handle the HTTP request and make sure the correct view for the request will be written to the HTTP stream:

 

    public class Razor
{
private RazorConfig _config;

        public Razor(RazorConfig config)
{
_config = config;
}

public Task Invoke(IDictionary<string, object> env)
{
switch (((string)env["owin.RequestMethod"]).ToUpper())
{
case "GET":
HttpGetHandler(env);
break;
}

            return Task.FromResult<object>(null);
}

        private void HttpGetHandler(IDictionary<string, object> env)
{
var responseContent = _config.Get[(string)env["owin.RequestPath"]].Invoke();

            var responseHeader = (IDictionary<string, string[]>)env["owin.ResponseHeaders"];
responseHeader.Add("Content-Type", new[] { "text/html" });

            using (var writer = new StreamWriter((Stream)env["owin.ResponseBody"]))
{
var parsedView = ParseView(responseContent.GetType(), responseContent);
writer.Write(parsedView);
}
}

        private string ParseView(Type type, object model)
{
var viewName = GetViewName(model != null ? model.GetType() : type);
var view = model as IView ?? new View(viewName, model, type);

            var viewTemplate = _config.ViewLocator.GetView(null, view);

            return _config.ViewParser.ParseView(view, viewTemplate);
}

        private string GetViewName(Type modelType)
{
var viewAttributes = (ViewAttribute[])modelType.GetCustomAttributes(typeof(ViewAttribute), true);
if (viewAttributes.Length > 0)
return viewAttributes[0].ViewName;

return modelType.Name;
}
}

 

The Razor class can get the name of the view to be used to render a model by convention, or attribute (ViewAttribute on the model).

Here is the Customer.cshtml view I used to see that I managed to get Razor to work:

 

    <!DOCTYPE html>
<html>
<head></head>
<body>
<div id="body">

            <section>                
<div>

                  <hgroup>
<h1>Welcome '@Model.Name' to OWIN Razor Test!</h1>
</hgroup>
</div>

           </section>

         </div>
</body>
</html>

 

The code in this blog post is far from perfect, it just a simple code to render a Razor view for a model. You may notice that I fail to follow the law of delimiters when I Get- and Parse a View ;)

If you are interested in the RazorViewLocator and RazorViewParser code, you can take a look at the code added to the ASP.Net Web API Contrib.

If you want to know when I publish a new blog post, feel free to follow me on twitter: @fredrikn

Feature enabling when using Branch by Abstraction

Something that I haven't liked for a long time is the use of branches in a projects. I don't like the waste when it comes to merge between branches, "Merge hell". In the beginning of the project I'm in now, it took hours to do merges before a release, both handling conflicts, but also selects different changeset that should include and not include in the merge before a release. The hard part was when a branch per feature was present. Later on this was changed into one single dev branch, but still sometimes two branches may exists. The team was used to work like this from previous projects. To handle this merge hell one dedicated person handle all the merge so the team can work undisturbed (not true, they were involved when conflicts occurs). Even with a dedicated person, the problem still exists, it was just moved. The time it takes to do the merge, was there, the problem with non-disciplines people that did not following the guidelines when it comes to fixing bugs in different branches, or forgot to merge into the main branch, created problems. Wouldn't it be nice to get rid of all the merge problems, let everyone just work in the same branch? There is a way, it may not work for every projects though (sometimes a bigger change may be useful to have in a single branch, but I think it should first be avoided). The solution to the problem is what Paul Hammant calls "Branch by Abstraction".

In short, it's about creating an abstraction over the part of the system that need to be changed, or use an existing abstraction. Implement the new feature side by side with the current production code, and when the new feature is tested and ready for production, switch the old code with the new one, then the old code can be removed. New abstractions added, may also be removed if it's not needed for future use. All code is checked-in into one mainline by everyone in the team. Before a release, a release branch from the mainline is created (used to fix production bugs).

BUT! And it's a BIG but, it requires a lot of discipline among the team members and also a good architecture.

One key "solution" when it comes to work with Branch by Abstraction is to use "feature enabling", to be able to enable features first when it's ready for production.


Feature enabling on an environment level


Visual Studio has support of using compiler directives or build options like Debug and Release etc. I decided to not use those options, instead a flag in a configuration file, the reason is that I want my Continuous Integration still always use a release build, and the deployment of artifacts to the test environment (for the test team) should be in release mode. The same with compiler directives.

Because the build script we use uses XML transforming of configuration files based on the environment it will build and deploy too, I think the configuration file is a good place to add a "featuring enable" switch.

<appSettings>
<add key="FeatureEnableEnvironment" value="development" />
<appSettings>

 

The value of the FeatureEnableEnvironment key in the configuration for the test and development environment is "development". For production it's "production", but this value is ignored. Example of a transforming settings in the configuration file for the production environment:

<appSettings>
<add
key="FeatureEnableEnvironment"
value="production"
xdt:Transform="SetAttributes"
xdt:Locator="Match(key)"/>
</appSettings>

 

The bootstrapper used for configure the object to an IoC Container will read from the setting, and will override the production registration (default registration is for production) with the new object that developers is working on. Here is the bootstrapper for the IoC container, Microsoft Unity 2.0 is used as a IoC contrainer.


public void Configure(IUnityContainer container)
{
RegisterForProduction(container);

if (IsDevelopmentEnvironment())
RegisterForDevelopment(container);
}

private void RegisterForProduction(IUnityContainer container)
{
container.RegisterType<IRejectInvoiceProcess, RejectInvoiceProcess>();
}

private void RegisterForDevelopment(IUnityContainer container)
{
container.RegisterType<IRejectInvoiceProcess, RejectInvoiceProcess_2>();
}

 

When a new feature is under development, an override of the production registration is done within the method RegisterForDevelopment. When the feature is approved for production, the old object will be removed, and the new one will be used instead (probably also be renamed). The override registration in the RegisterForDevelopment will of course also be removed by the team.

Any suggestion and comment of making this even better are welcome, the problem with the blog I use is that there are a lot of spam, so adding a comment to the post will probably disappear among all the spams. So please send med a message on twitter when a comment is added, so I know when to look among all the comments.

If you want to know when I publish a new blog post, feel free to follow me on twitter: @fredrikn

Creating a simple REST like service with OWIN – Open Web Server Interface

"OWIN, a standard interface between .NET web servers and web applications. The goal of OWIN is to decouple server and application and, by being an open standard, stimulate the open source ecosystem of .NET web development tools." – owin.org

OWIN can be used for extremely lightweight hosts that can run from command line, Windows service, client, low power devices etc. Many applications today doesn't use all the features that IIS (Internet Information Service) provide use with, because we just doesn't need them.

In this blog post I will show you a very simple REST like service using OWIN (the code will just support easy GETs nothing more, so it's not a complete REST service).

OWIN is based on a very simple interface, it uses something called application delegate or AppFunc. An application delegate takes the IDictionary<string,object> environment and returns a Task when it has finished processing.

  using AppFunc = Func<
IDictionary<string, object>, // Environment
Task>; // Done

 

The dictionary has some keys that can be used to get access to request and response, headers, body, Query string, request method etc. You can find the key's in the OWIN specification (This blog post will mention some of them later).

In this blog post I will use Katana to host my OWIN and REST like service. To setup a simple OWIN application using Katana, take a look at this documentation (I will not give instruction how to set it up in this blog post).

An OWIN hosts can do the following when its starts:

It first creates properties with startup data or capabilities provided by the host. The properties is an IDirectory<string, object>. The host selects the server to be used and will provides it with the Properties collection, then it locates the application setup code and invokes it with the Properties collection. The application can then use the properties and decide its own requesting pipeline. Then the host invokes the server startup code with the properties and finish configure itself to accepting requests.

The OWIN namespace has the IAppBuilder interface, this will contain the Properties mentioned above. When using Katana a Startup class is needed with two methods:


public void Configuration(IAppBuilder app)

public Task Invoke(IDictionary<string, object> env)

 

The Configuration method will be called when the hosts is starting, and the IAppBuilder will be passed to the Configuration method. The Invoke will be called every time an incoming request should be handled. The env argument will contain a dictionary with environment information, such as request and response.

I created a simple solution to register "routes" and execute methods based on the requested path. Here is my Startup class:

 

public class Startup : BaseNavigation
{
public void Configuration(IAppBuilder app)
{
Get["/list/customers"] = ListCustomers;
Get["/list/users"] = ListUsers;

app.Run(this);
}

public Task Invoke(IDictionary<string, object> env)
{
switch (((string)env["owin.RequestMethod"]).ToUpper())
{
case "GET":
HttpGetHandler(env);
break;
//...

       }

return Task.FromResult<object>(null);
}

}

 

The BaseNavigation class inherited by the Startup class just contains a Get property:


public class BaseNavigation
{
Dictionary<string, Func<object>> _get = new Dictionary<string, Func<object>>();

public IDictionary<string, Func<object>> Get
{
get { return _get; }
}
}


In the Startup's Configuration method I use the Get property to set up which methods that should handle the request for a specific "route". The Get property will only be used to get the "routes" when the incoming request is a HTTP GET. Within the Startup class's Invoke method (as mentioned earlier, the Invoke method will be called on each request) I use the "env" argument to get access to the requested method, this is done by using one of the key specified ("owin.RequestMethod") in the OWIN specification.

If the request method is GET, I make a call to my HttpGetHandler that will handle the GET:

private void HttpGetHandler(IDictionary<string, object> env)
{
var responseContent = Get[(string)env["owin.RequestPath"]].Invoke();

var requestHeader = (IDictionary<string, string[]>)env["owin.RequestHeaders"];
var responseHeader = (IDictionary<string, string[]>)env["owin.ResponseHeaders"];

responseHeader.Add("Content-Type", requestHeader["Accept"]);
env["owin.ResponseStatusCode"] = 200;

using (var writer = new StreamWriter((Stream)env["owin.ResponseBody"]))
{
new JsonSerializer().Serialize(writer, responseContent);
}
}

 

NOTE: I don't care about the HTTP Headers "Content-type" or "Accept" header to decide the format for the returned response, I simply use JSON, the goal is not to write a perfect REST infrastructure, just a simple demonstration of OWIN, there are no error handlers is added to the code.

By using the "owin.RequestPath", I can get access to the request path, for example if I do GET http://localhost/list/customer, the "list/customer" will be the request path. Because the key value of the BaseNivgation's Get property is the request path, I just use the path as a key and invoke the Func<T> registered, in this case when "list/customer" is the request path, the ListCustomers method will be executed. To demonstrate how we can get access to the request and response header, I simply gets the "owin.RequestHeaders" and "owin.ResponseHeaders", and adds the "Content-Type" to the response header with the value of the request headers "Accept" header.

To write to the response stream of a request, the "owin.ResponseBody" key of the "env" argument can be used. The "owin.RequestBody" can be used to get the stream of the request body.

By setting the "env"'s "owin.ResponseStatusCode", I can specify the HTTP status of the request, in this case 200 (which is also default).

Here are the ListCustomers and ListUsers methods and the Customer and User classes:

public IEnumerable<Customer> ListCustomers()
{
return new[] { new Customer() { Id = 1, Name = "John Doe" } };
}

public IEnumerable<User> ListUsers()
{
return new[] { new User() { Id = 1, Name = "Super User" } };
}


public class Customer
{
public int Id { get; set; }

public string Name { get; set; }
}

public class User
{
public int Id { get; set; }

public string Name { get; set; }
}

 

Summary

 

In this blog post you have seen how OWIN and Katana was used to create a simple REST like service (well, far from a complete one). The idea was to show some basic stuffs that can be done by using OWIN.

 

If you want to know when I publish a new blog post, feel free to follow me on twitter: @fredrikn

Team Foundation Server 2012 build notification using ASP.Net Web API Part 2

In my previous blog post I wrote about how to get information about a build, the problem with that code was that the code only returned the user who requested the build, not the user who had checked-in a changeset that failed the build. So this blog post will cover that part.

The VersionControlServer class in the assembly Microsoft.TeamFoundation.VersionControl.Client can be used to get Changesets from a specific branch. To get access to the VersionControlServer I use the TfsTeamPorjectCollection's GetService<T> method, where T is set to VersionControlServer. To query a branch changeset history, the QueryHistory method of the VersionControlServer can be used. The QueryHistory method needs the path to the branch and other query parameters to get changessets. To get the path, I created a helper method (GetFirstServerItemFromBuild, it will get the path from the BuildDefinition:

        private string GetFirstServerItemFromBuild(string buildName)
{
var buildService = _teamProjectCollection.GetService<IBuildServer>();
var build = GetBuildDefinition(buildName, buildService);

return build.Workspace.Mappings.First().ServerItem;
}



When setting up a build in TFS, we need to specify Working folders under the Workspace settings, in my case the first working folder has the path to the branch.

By using the BuildDefintion's Workspace and its Mappings property, I can get the first item from the Working folders. The ServerItem property will return the Source Control Folder.

To get the most possible ChangeSet that may cause the build to fail I specify a "from date" (passed as an argument to a helper method, more about that later) and a "to date" to the QueryHistory method. The "from date" will be three weeks back in time from when the latest build was started, and the "to date" will be when the latest build was started. I will then take the First ChangeSet from the QueryHistory's result. QueryHistory don't take a DateTime as argument for the dates, instead a VersionSpec class, so I created a helper method that will parse a DateTime to a VersionSpec.

        private static VersionSpec CreateDateVSpec(DateTime date)
{
//Format is: D2009-11-16T14:32
return VersionSpec.ParseSingleSpec(
string.Format("D{0:yyy}-{0:MM}-{0:dd}T{0:HH}:{0:mm}", date),
string.Empty);
}



I created a helper method added to my TfsBuidService class for helping me to get the latest change set, here is the code for the helper method.

    public Changeset GetLatestChangeset(DateTime versionTodate, string buildName)
{
var path = this.GetFirstServerItemFromBuild(buildName);

            var vcs = _teamProjectCollection.GetService<VersionControlServer>();

var versionFrom = CreateDateVSpec(versionTodate.AddDays(-21));
var versionTo = CreateDateVSpec(versionTodate);

var results = vcs.QueryHistory(path, VersionSpec.Latest, 0, RecursionType.Full, null, versionFrom, versionTo, int.MaxValue, false, true);

return results.Cast<Changeset>().FirstOrDefault();
}

 

I made some changes to my Web API, so it takes information from the latest change set:

 

    private static BuildDetail GetBuildDetail(string buildName)
{
var tfsBuildService = new TfsBuildService(
TFS_SERVER_COLLECTION_URI,
USER_DOMAIN,
USER_NAME,
USER_PASSWORD,
PROJECT_NAME);

var lastBuild = tfsBuildService.GetLastBuildDetail(buildName);
var changeSet = tfsBuildService.GetLatestChangeset(lastBuild.StartTime, buildName);

return new BuildDetail
{
RequestedBy = lastBuild.RequestedBy,
Status = lastBuild.Status.ToString(),
FinishTime = lastBuild.FinishTime,
StartTime = lastBuild.StartTime,
LastCheckedInUser = changeSet != null ? changeSet.OwnerDisplayName : lastBuild.RequestedBy,
ChangeSetComment = changeSet != null ? changeSet.Comment : string.Empty,
ChangeSetId = changeSet != null ? changeSet.ChangesetId : -1,
WorkItemTitle = tfsBuildService.GetLatestWorkItemTitle(changeSet)
};
}



The resource returned from the Web API will now also include extra information, such as the last work item associated to the last changeset, changeset's id, changeset's comment by the user who check-in the code and the last user who checked-in the code. To get the latest changeset, the last build's StartTime is used to query the build's branch for the latest changeset.

To get the latest work item associated to the changeset, I created a helper method that takes the ChangeSet as an argument, just to extract the Work item title:

 

      public string GetLatestWorkItemTitle(Changeset changeSet)
{
if (changeSet == null)
return string.Empty;

if (changeSet.AssociatedWorkItems == null || !changeSet.AssociatedWorkItems.Any())
return string.Empty;

return changeSet.AssociatedWorkItems[0].Title;
}

 

Even if the TFS API for 2012 had lack of example on MSDN, it was quite easy to understand how to use them.

I hope some of you may found this blog post useful.

If you want to know when I have published a blog post, then feel free to follow me on twitter: @fredrikn

Team Foundation Server 2012 build notification using ASP.Net Web API

For the last three years I have helped a financial company with a business critical financial system. I have the role as an architect and coach when it comes to system design. I also spend times to make the team work more efficiently, to release new features with high quality, and maintainable code faster. So the last months I have spent a lot of time with a Deployment Process, to see how we can use Continuous Delivery. We use Visual Studio 2012 and Team Foundation Server 2012 (TFS) as our configuration system. We use gated check-ins (The goal is to use branch by abstractions, so the team work against one mainline only, to remove the "merge hell"). Even if we use gated check-ins we had to disable some acceptance tests because the time it takes for them to run. Instead we use a build that runs at lunch time and one at the night to include the acceptance tests (Those needs to be observed by the team). So far TFS have worked perfect, both for Gated check-in and Continuous Integration for the mainline. We also use TFS for a "push deployment" to our internal test and UAT environment. Everything is automated. We haven't yet "enable" the "push-deploy" against our production environment yet.

For showing progress and what the team is working on we have a LCD screen on the wall displaying the TFS's Kanban board. During this weekend I have put together a simple program that will show if a build has failed (the one we run during lunch and at the night, that includes the long running acceptance tests) and the person that brook it, just for fun. Today every team member uses the Build Notification program shipped with Visual Studio, and also an e-mail alert for build notifications. The little program I put together during this weekend will show alerts on the LCD screen.

Team Foundation Server has Web Services that can query the build server for information, but it returns a lot of data and I had some authentication problem accessing it. Instead I decided to create a REST service with ASP.Net Web API to query the build server, and just fetch the information I need for my purpose, and also to try out the TFS 2012 APIs.

Accessing the TFS Build server


To access the TFS build server from code I added references to the Microsoft.TeamFoundation.Build.Client, Microsoft.TeamFoundation.Client and Microsoft.TeamFoundation.Common assemblies (In the Reference Manager you can find those assemblies by selecting Assemblies/Extensions).

To connect to the TFS and get the Team project collection I'm working against, I use the TfsTeamProjetCollection class. The TfsTeamProjectCollection constructor can take an URI and ICredentials as argument. I will use the NetworkCredential to provide login information to the TFS.


_teamProjectCollection = new TfsTeamProjectCollection(

                                                      new Uri(uri),

                                                      new NetworkCredential(username, password, domain));

 

To get access to the Build Server to get the latest build definition, the TfsTeamProjectCollection's GetService<T> method can be used, and the <T> represents the type of the service to get. In this case I want the IBuildServer. To get a build definition from the build server, the IBuildServer's GetBuildDefinition method can be used, it can take the name of the project the build belongs to and also the build to get. The GetBuildDefinition method returns IBuildDefintion.

var buildService = _teamProjectCollection.GetService<IBuildServer>();

 

var build = buildService.GetBuildDefinition(_projectName, buildName);

 

if (build == null)

   throw new BuildDefinitionDoesNotExistException(string.Format("The Build '{0}' can't be found", buildName));

 

To get the details from a specific build, the IBuildServer's GetBuild method can be used. The GetBuild method can take an URI for a specific build and returns IBuildDetail. In my case I want to get the latest build, so I use the IBuildDefinition's LastBuildUri property so get the URI for the latest build.

return buildService.GetBuild(build.LastBuildUri);

 

Here is the whole code of a class (TfsBuildService) that uses the code above (I uses this as a simple helper method for my Web API):

 

namespace TfsNotifierWebApi.Models

{

    using System;

    using System.Net;

 

    using Microsoft.TeamFoundation.Build.Client;

    using Microsoft.TeamFoundation.Client;

 

    public class TfsBuildService : ITfsBuildService

    {

        private readonly string _projectName;

 

        private TfsTeamProjectCollection _teamProjectCollection;

 

        public TfsBuildService(string uri, string domain, string username, string password, string projectName)

        {

            _projectName = projectName;

 

            _teamProjectCollection = new TfsTeamProjectCollection(

                                                                new Uri(uri),

                                                                new NetworkCredential(username, password, domain));

        }

 

 

        public IBuildDetail GetLastBuildDetail(string buildName)

        {

            var buildService = _teamProjectCollection.GetService<IBuildServer>();

 

            var build = buildService.GetBuildDefinition(_projectName, buildName);

 

            if (build == null)

                throw new BuildDefinitionDoesNotExistException(string.Format("The Build '{0}' can't be found", buildName));

 

            return buildService.GetBuild(build.LastBuildUri);

        }

    }

}


The IBuildDetail will provide me with information such as who requested the build (RequestedBy) and the status of the build (Status).

 

The Web API

I created a simple ASP.Net Web API ApiController that will use the TfsBuildService class (mentioned above) to access a build, and returns information about the build. Here is the code of my Web API:

namespace TfsNotifierWebApi.Controllers

{

    using System;

    using System.Net;

    using System.Net.Http;

    using System.Web.Http;

 

    using TfsNotifierWebApi.Models;

 

    public class BuildController : ApiController

    {

        public const string PROJECT_NAME = "myProject";

        public const string TFS_SERVER_COLLECTION_URI = "http://<my server>:8080/tfs/<my collection>";

 

        public const string USER_NAME = "<username>";

        public const string USER_PASSWORD = "<password>";

        public const string USER_DOMAIN = "<domain>";

 

 

        public HttpResponseMessage Get(string buildName)

        {

            try

            {

                return Request.CreateResponse(HttpStatusCode.OK, GetBuildDetail(buildName));

            }

            catch (Exception e)

            {

                return Request.CreateResponse(HttpStatusCode.NotFound, new HttpError(e.Message));

            }

        }

 

        private static BuildDetail GetBuildDetail(string buildName)

        {

            var tfsBuildService = new TfsBuildService(

                                                    TFS_SERVER_COLLECTION_URI,

                                                    USER_DOMAIN,

                                                    USER_NAME,

                                                    USER_PASSWORD,

                                                    PROJECT_NAME);

 

            var lastBuild = tfsBuildService.GetLastBuildDetail(buildName);

 

            return new BuildDetail

            {

                RequestedBy = lastBuild.RequestedBy,

                Status = lastBuild.Status.ToString(),

                FinishTime = lastBuild.FinishTime,

                StartTime = lastBuild.StartTime

            };

        }

    }

}

 

IMPORTANT NOTE: The constants storing the information about accessing the TFS is only used in this code for demonstration purpose, NEVER store sensitive information in constants, it's a BAD idea when it comes to security.

The Web API will returns a HttpRespnseMessage with the content set to my custom class, BuildDefintion:

namespace TfsNotifierWebApi.Models

{

    using System;

 

    public class BuildDetail

    {

        public string RequestedBy { get; set; }

 

        public string Status { get; set; }

 

        public DateTime FinishTime { get; set; }

 

        public DateTime StartTime { get; set; }

    }

}

 

I think the Web API code will describe itself, so I will skip the details.

The Client Side

 

On the client side to call the Web API, I decided to use a simple WPF application. I use the HttpClient to access the Web API.

private dynamic GetBuildInfo(string buildName)

{

    var httpClient = new HttpClient();

 

    var result = httpClient.GetAsync("http://localhost:10927/api/build/" + buildName).Result;

    var buildDetail = result.Content.ReadAsStringAsync().Result;

 

    return JObject.Parse(buildDetail);

}

 

I use the Newsoft.Json lib to parse the JSON result returned from the Web API into a dynamic object, JObject.Parse.

The WPF application was made by KISS (Keep it Simple Stupid). I use a simple DispatcherTimer to poll against the Web API to see if the latest build status has changed.


using System;

using System.Net.Http;

using System.Windows;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using Newtonsoft.Json.Linq;

public MainWindow()

{

   WindowState = WindowState.Minimized;

 

   InitializeComponent();

 

   UpdateBuildStatus();

 

   var dispatcherTimer = new System.Windows.Threading.DispatcherTimer();

   dispatcherTimer.Tick += dispatcherTimer_Tick;

   dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 5);

   dispatcherTimer.Start();

}

 

void dispatcherTimer_Tick(object sender, EventArgs e)

{

   UpdateBuildStatus();

}

 

The UpdateBuildStatus method will update the client with red color if the build has failed, and yellow if partially succeeded. It will also try to get an image from an Images folder of the user started the build.

private void UpdateBuildStatus()

{

   var result = GetBuildInfo("Test - Nightly Build");

 

    requestByTextBlock.Text = result.RequestedBy;

    requestByImage.Source = new BitmapImage(new Uri("Images/" + result.RequestedBy + ".jpg", UriKind.Relative));

 

    var status = result.Status;

 

    switch ((string)status)

    {

        case "Failed":

             SetBackgroundColor(237, 28, 36);

             Activate();

             WindowState = WindowState.Maximized;

             break;

        case "PartiallySucceeded":

             SetBackgroundColor(255, 201, 14);

             Activate();

             WindowState = WindowState.Maximized;

             break;

        default:

             WindowState = WindowState == WindowState.Maximized ? WindowState.Minimized : WindowState;

             SetBackgroundColor(195, 195, 195);

             break;

        }

    }
}


The SetBackgroundColor method is a helper method to set a Grid's background color.

private void SetBackgroundColor(byte r, byte g, byte b)

{

   mainGrid.Background = new SolidColorBrush(Color.FromRgb(r, g, b));

}

 

Here is the XAML is you are interested:

<Window x:Class="TfsNotifier.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="MainWindow" Height="1000" Width="800">

    <Grid Name="mainGrid">

        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">

            <TextBlock FontSize="90px" FontWeight="ExtraBold" Name="requestByTextBlock"></TextBlock>

            <Image Stretch="None" Name="requestByImage" MaxHeight="500" MaxWidth="700"></Image>

        </StackPanel>

    </Grid>

</Window>

 

The last words


You may wonder why I have created a Web API instead of using the TFS Api directly from the WPF. By using the Web API I can also create a Windows 8 app or a ASP.Net Single Page Application (SPA) as clients etc.

If you want to know when I have published a blog post, then feel free to follow me on twitter: @fredrikn

Using Razor engine together with Asp.Net Web API to create a Hypermedia API

This blog post is created just for fun, and it's will be about how we can use Razor to create a Hypermedia API using XML as a hypermedia for a "Maze game" inspired from the book "Building Hypermedia APIs with HTML5 and Node", Mike Amundsen. Only the server-side API is covered in this blog post, so no Client.

Note: The code in this blog post will use the WebAPI Contrib's Formatting.RazorViewEngine

Here is a short description of the game:

In this "Maze Game", a client should be able to request a maze to play. The client should be able to navigate from a starting point through the maze to the exit. The cells in the maze can have different exit (doorways) into other cells (north, south, east and west).

To design the media type for the game, we first need to know what clients can do, so here is a list of requirements of the game:

  • A list of available mazes to select among.
  • Be able to select one maze to play.
  • See all the doorways in each cell.
  • Navigate through a selected doorway into the next cell.
  • See the exit of the maze and navigate through the exit.

To design the hypermedia we can take the requirements and turn it into some states.

The following is a list of application states and transitions for each identified state of the maze:

Collection State

    The response represents a list of mazes.

Possible transitions are:

1) Select a maze (Item State), or
2) reload the list (Collection state).

Item State

    The response represents a single maze.

    Possible transition are:

  1. Start into the maze, or
  2. reload the list (Collection Sate), or
  3. reload the maze (Item State).

Cell State

    The response represents a single cell in the maze.

    Possible transitions are:

  1. Continue through one of the doorways to the next cell (Cell State)
  2. Return to the maze (Item State)
  3. Return to the maze list (Collection State), or
  4. reload the cell (Cell State).

Error State

    The response represents the details of an error. No transitions from this state.

Here is the hypermedia design of the above states:

<maze>
    <collection/>
    <item/>
    <cell/>
    <error>
</maze>


For the Item State's transition the <link href="…" rel="maze"/> will be used, the "href" and "rel" attribute is used to hold the URI and transition identifier.

For the Collection State the "href" attribute will be used for reloading the list:

<collection href="…">

A fully Collection State could look like this

<maze>
    <collection href="…">
        <link href="…" rel="maze" />
        <link href="…" rel="maze" />
        …
    </collection>
</maze>

The Item State is represented by using the <item/> element, it also uses the <link/> element for transitions and the" href" attribute for reloading the maze details. Here is an example:

<maze>
    <item href="…">
        <link href="…" rel="collection" />
        <link href="…" rel="start" />
        …
    </item>
</maze>


The Cell State is represented in the following way:

<maze>
    <cell href="…">
        <link href="…" rel="north" />
        <link href="…" rel="south" />
        <link href="…" rel="east" />
        <link href="…" rel="west" />
        <link href="…" rel="exit" />
        <link href="…" rel="maze" />
        <link href="…" rel="collection" />
    </cell>
</maze>


Now when the design of the hypermedia is done, we can start creating our API and the Razor views that should render the media.

The following code are simple fakes that representation the Model of the Maze:

using System.Collections.Generic;
using System.Linq;

namespace MvcWebApiSiteTest.Models
{
public class MazeDb
{
public MazeGame GetMaze()
{
var maze = new Maze { Id = "my-only-maze", Description = "My only maze" };

            maze.AddCell(new Cell { Id = 1, Doorways = new[] { new DoorWay { Id = 1, Direction = "north", Cell = 2 } } });
maze.AddCell(new Cell { Id = 2, Doorways = new[] { new DoorWay { Id = 1, Direction = "exit" } } });

            return new MazeGame { Mazes = new List<Maze> { maze } };

        }
}

   public class MazeGame
{
public IEnumerable<Maze> Mazes { get; set; }
}

public class Maze
{
private IList<Cell> _cells = new List<Cell>();

public string Id { get; set; }
public string Description { get; set; }
public Cell Start { get { return Cells.First(); }}
public IEnumerable<Cell> Cells { get { return _cells; }}

public void AddCell(Cell cell)
{
cell.Maze = this;
_cells.Add(cell);
}
}

public class Cell
{
public Maze Maze { get; set; }
public int Id { get; set; }
public IEnumerable<DoorWay> Doorways { get; set; }
}

public class DoorWay
{
public int Id { get; set; }
public string Direction { get; set; }
public int Cell { get; set; }
}
}

 

The following is the ApiController used. The code for accessing the Maze are just fakes (Because the blog post is not about how to write the server-side code, it's about how to use the RazorViewEngine to create a hypermedia, the code is simple and stupid and far from perfect!):

using System.Web.Http;

namespace MvcWebApiSiteTest.Controllers
{
using System.Linq;
using MvcWebApiSiteTest.Models;

public class MazeController : ApiController
{
// GET /maze
public MazeGame Get()
{
var mazeDb = new MazeDb();
return mazeDb.GetMaze();
}

// GET /maze/{maze}
public Maze Get(string maze)
{
var mazeDb = new MazeDb();
return mazeDb.GetMaze()
.Mazes.Single(m => m.Id == maze);
}

// GET /maze/{maze}/{id}
public Cell Get(string maze, int id)
{
var mazeDb = new MazeDb();
return mazeDb.GetMaze()
.Mazes.Single(m => m.Id == maze)
.Cells.Single(c => c.Id == id);
}
}
}



The following code configures the route for the API so it can take "maze" and "id" from the URL as parameters (instead of using Querystrings) into the Get methods of the MazeController:


config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "maze/{maze}/{id}",
defaults: new { controller = "maze", maze = RouteParameter.Optional, id = RouteParameter.Optional }
);


Now when the server-side API is created, we can go on to the Razor Views that will render the hypermedia designed earlier in this blog post.

The WebApi Contrib's Formatting RazorViewEngine can use convention before configuration to locate the View for rendering the Model the MazeController returns. The name of the view should be the same name as the class the MazeController returns. The Views are created in the Views folder and the views are MazeGame.cshtml (Representation the Collection State of the Maze), Maze.cshtml (Represents the Item State) and the Cell.cshtml (Represents the Cell State). Here is the code of the Views:

MazeGame.cshtml


<?xml version="1.0" encoding="utf-8" ?>
<maze>
<collection href="http://weblogs.asp.net/mazeGame">
@foreach (var maze in Model.Mazes)
{
<link href="http://weblogs.asp.net/maze/@maze.Id" rel="maze" />
}
</collection>
</maze>


Here is a representation of the MazeGame.cshtml ouput:

<?xml version="1.0" encoding="utf-8" ?> 

<maze>

    <collection href="http://weblogs.asp.net/mazeGame">

            <link href="http://weblogs.asp.net/maze/my-only-maze" rel="maze" />

    </collection>

</maze>



Maze.cshtml


<?xml version="1.0" encoding="utf-8" ?>
<maze>
<item href="http://weblogs.asp.net/maze/@Model.Id" >
<link href="http://weblogs.asp.net/mazeGame" rel="collection">
<link href="http://weblogs.asp.net/maze/@Model.Id/@Model.Start.Id" rel="start" />
</item>
</maze>

 

Here is a representation of the Maze.cshtml output:


<?xml version="1.0" encoding="utf-8" ?>

<maze>

    <item href="http://weblogs.asp.net/maze/my-only-maze" >

        <link href="http://weblogs.asp.net/mazeGame" rel="collection">

        <link href="http://weblogs.asp.net/maze/my-only-maze/1" rel="start" />

    </item>

</maze>



Cell.cshtml

 

<?xml version="1.0" encoding="utf-8" ?> 

<maze>

    <cell href="http://weblogs.asp.net/maze/@Model.Maze.Id/@Model.Id">

        @foreach (var cell in Model.Doorways)

        {

            <link href="http://weblogs.asp.net/maze/@Model.Maze.Id/@cell.Cell" rel="@cell.Direction" />

        }

        <link href="http://weblogs.asp.net/maze/@Model.Maze.Id" rel="maze" />

        <link href="http://weblogs.asp.net/maze" rel="collection" />

    </cell>

</maze>

 

Here is a representation of the Cell.cshtml output:

<?xml version="1.0" encoding="utf-8" ?> 

<maze>

    <cell href="http://weblogs.asp.net/maze/my-only-maze/1">

        <link href="http://weblogs.asp.net/maze/my-only-maze/2" rel="north" />

        <link href="http://weblogs.asp.net/maze/my-only-maze" rel="maze" />

        <link href="http://weblogs.asp.net/maze" rel="collection" />

    </cell>

</maze>

 

Now when the Views for rending the hypermedia is done, we need to configure so we can use a specific media type to access our hypermedia. We will use "application/maze+xml" as the media type.

To add the support of our own media type "application/maze+xml" we can take advantage of the WebApiContrib Razor Formatter's HtmlMediaTypeViewFormatter. We can simply add the "application/maze+xml" media type to the HtmlMediaTypeViewFormatter, here is the Application_Start method of the Global.asax to add our media type and use the HtmlMediaTypeViewFormatter:

protected void Application_Start()

{

      AreaRegistration.RegisterAllAreas();

 

      var formatter = new HtmlMediaTypeViewFormatter();

      formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/maze+xml"));

 

      GlobalConfiguration.Configuration.Formatters.Add(formatter);

 

      GlobalViews.DefaultViewParser = new RazorViewParser();

      GlobalViews.DefaultViewLocator = new RazorViewLocator();

 

      WebApiConfig.Register(GlobalConfiguration.Configuration);

      FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

      RouteConfig.RegisterRoutes(RouteTable.Routes);

      BundleConfig.RegisterBundles(BundleTable.Bundles);

}


To access the Maze Hypermedia API by a HTTP GET, make sure the HTTP Header Accept is set to "application/maze+xml":

Accept: application/maze+xml


All done!

By using ASP.Net Web API and the WebApiContrib.Formatting.RazorViewEngine, we can use Razor to create a hypermedia, wasn't that cool? ;)

By following me on twitter @fredrikn, you will know when I publish new blog posts.

 

 

 

 

 

 

ASP.Net Web API and using Razor the next step

In my previous blog post “Using Razor together with ASP.NET Web API” I wrote about a solution to use a MediaTypeFormatter to render HTML by using Razor when the API is accessed from a browser. I’m now sort of done with the basics and will share the current solution in this blog post. The source code will later be available.

I decided to make the solution more extendable so I created a HtmlMediaTypeViewFormatter that inherits from the MediaTypeFormatter:


public
class HtmlMediaTypeViewFormatter : MediaTypeFormatter { //... }

 

With the new generic solution any kind of “parser” can be used to render the HTML, not only by using Razor. I made this possible by using a IViewParser:


public
interface IViewParser { byte[] ParseView(IView view, string viewTemplate, Encoding encoding); }

The IViewParser’s responsibility is to implement the logic to use a template (for example a razor template) and parse a view’s model into a encoded byte array.

Another interface that is introduce is the IViewLocator, with the IViewLocator it will be easy to replace how to locate the templates passed into the IViewParser. At the moment the IViewLocator also has the responsibility to return the content of the located template, so the default RazorViewLocator in the project will locate and read a .cshtml or .vbhtml file and the content of the file is passed as an argument to the IViewParser. Here is part of the IViewLocator code:

public interface IViewLocator
{
    string GetView(string siteRootPath, IView view);
}


internal class RazorViewLocator : IViewLocator
{
     private readonly string[] viewLocationFormats = new[]
        {
             "~\\Views\\{0}.cshtml",
             "~\\Views\\{0}.vbhtml",
             "~\\Views\\Shared\\{0}.cshtml",
             "~\\Views\\Shared\\{0}.vbhtml"
         };


     public string GetView(string siteRootPath, IView view)
     {
         if (view == null)
             throw new ArgumentNullException("view");

         var path = GetPhysicalSiteRootPath(siteRootPath);

         foreach(string viewLocationFormat in viewLocationFormats)
         {
             var potentialViewPathFormat = viewLocationFormat.Replace("~", GetPhysicalSiteRootPath(siteRootPath));

             var viewPath = string.Format(potentialViewPathFormat, view.ViewName);

             if (File.Exists(viewPath))
                 return File.ReadAllText(viewPath);
         }

         throw new FileNotFoundException(string.Format("Can't find a view with the name '{0}.cshtml' or '{0}.vbhtml in the '\\Views' folder under  path '{1}'", view.ViewName, path));
     }

      ///...
}


Here is some code from the HtmlMediaTypeViewFormatter, so you can get a glimpse how the IViewLocator and IViewParser is used:

public override Task WriteToStreamAsync(
                                       Type type,
                                       object value,
                                       Stream stream,
                                       HttpContentHeaders contentHeaders,
                                       TransportContext transportContext)
{
     return TaskHelpers.RunSync(() =>
           {
              var encoding = SelectCharacterEncoding(contentHeaders);

              var parsedView = ParseView(type, value, encoding);

              stream.Write(parsedView, 0, parsedView.Length);
              stream.Flush();
           });
}


private byte[] ParseView(Type type, object model, System.Text.Encoding encoding)
{
      var view = model as IView;

       if (view == null)
            view = new View(GetViewName(model), model, type);

        var viewTemplate = _viewLocator.GetView(_siteRootPath, view);

        return _viewParser.ParseView(view, viewTemplate, encoding);
}


Note: The WriteToStreamAsync in the RTM code of ASP.NET WebAPI is different from the above code. I decided to still use the bits shipped with Visual Studio 2012 RC. This will of course be changed later.

The IViewLocator and IViewParser can be changed by using a global configuration class, GlobalViews, so in App_Start of a Web API project or in Global.asax the locator and parser can be replaced with another implementation, for example:

GlobalViews.DefaultViewLocator = new MyViewParser();
GlobalViews.DefaultViewLocator = new DatabaseViewLocator();

 

The HtmlMediaTypeViewFormatter can also inject the dependencies to a locator and parser.

How to decide which view to be used


There are different ways to configure which View that should be used when accessing a API of a ApiController. Here are the examples:

Convention

public class CustomerController : ApiController
{
     // GET api/customer
     public Customer Get()
     {
        return new Customer { Name = "John Doe", Country = "Sweden" };
     }
}

 

By default with no configurations at all (just adding the HtmlMediaTypeViewFormatter to the Formatters collection in the Global.asax) a view will be located by using the name of the returned model, in the above code “Customer”

 

Configuration

By using annotation (with the ViewAttribute) you can specify which view a specific model should use:

 

[View("Customer")]
public class Customer
{
    public string Name { get; set; }

    public string Country { get; set; }
}

 

By using the GlobalViews in the Global.asax, mapping between model an views can be configured, here is code from the App_Start folder:

public class ViewConfig
{
    public static void RegisterViews(IDictionary<Type, string> views)
    {
        views.Add(typeof(Customer), "CustomerViaConfig");
    }
}


So if the Customer type is returned from the Web API, the “CustomerViaConfig” view will be used.

By returning an IView class, the view can be specified within the Web API’s return result:

public class CustomerController : ApiController
{
   // GET api/customer
   public View Get()
   {
      return new View("CustomerViaView", new Customer { Name = "John Doe", Country = "Sweden" });
   }
}

 

Summary

By using a HtmlMediaTypeViewFormatter, we can now render HTML when accessing our Web API from a browser, and we can specify which view to be used by using different kind of configuration or convention. It’s easy to replace the parser that is used to render the HTML and also how and where to locate a view to be used. The source code will sometime in a near future (I hope) be available for download.

My next goal is to make a WHOLE web site explaining the use of my project, just by using ASP.Net Web API.. I promise to let all of you know when that happens.

 

If you want to know when I post a new blog post, you can simply follow me on twitter @fredrikn