Project description

CarTrackr is a sample application for the ASP.NET MVC framework using the repository pattern and dependency injection using the Unity application block. It was written for various demos in presentations done by Maarten Balliauw.

CarTrackr is an online software application designed to help you understand and track your fuel usage and kilometers driven.

You will have a record on when you filled up on fuel, how many kilometers you got in a given tank, how much you spent and how much liters of fuel you are using per 100 kilometer.

CarTrackr will enable you to improve your fuel economy and save money as well as conserve fuel. Fuel economy and conservation is becoming an important way to control your finances with the current high price.

Source code

Latest version: CarTrackr (ASP.NET MVC 1.0 version)

Author blog feed

 Maarten Balliauw {blog} News Feed 
Friday, April 11, 2014  |  From Maarten Balliauw {blog}

During the past few weeks, I’ve been working on and off on setting up a build agent that can build as many open-source .NET projects as possible in an effort to learn how hard it is to do. Allow me to open this blog post with a rant… One which will feel very familiar if you’ve recently installed a build agent yourself.

Setting up a .NET build machine is insane

As the minimal installation of components I started with installing the .NET framework 2.0, 3.0, 3.5, 4.0, 4.0.1 (yes, that exists), 4.0.2, 4.0.3, 4.5, 4.5.1 and their multi-targeting packs on the build agent. Next, I took 100 random C# projects from GitHub that had activity in the last year or so and started building and reading build logs. Great news! There are a lot of self-contained open source projects out there that build happily on this minimal install. Most of these seem to be class libraries, often depending on some NuGet packages that are installed using NuGet package restore.

Unfortunately, there are a great number of projects that do not build on this minimal setup: those that require specific SDK’s and components installed. So I started delving deeper into build logs and tackled project by project with the necessary “headless installs” of SDK’s. In practice, this sometimes means running an installer with specific commands to only install what is required to build projects on it. In other cases it means copying .targets and reference assemblies from my Windows 8.1 machine to the Windows Server 2012 R2 machine that was my build agent (yes, you can build Windows Store apps on Windows Server if you are persistent…). And in other cases (looking at you, Windows Phone SDK!) it meant running the installer in compatibility mode with some registry keys changed to overcome installer checks that do not allow installing that SDK on Windows Server.

In the end, I had to install pretty much the entire world on the build agent, or at least all SDK’s and tools that have been released between Visual Studio 2010 and the latest 2013. Here’s 17.6 GB of sh… dependencies for you.

Installed programs and features

What is the issue?

Well, there isn’t just “one” issue. There are several. Here’s a quick list of issues and questions

  • There is no way to clearly specify dependencies on SDK’s and tooling in .NET projects. The only way to know what is required is to build, read the build log, build, read the build log and someday succeed in finding the right SDK for the job.
  • The fact that I need this amount of SDK’s installed is crazy in itself. Why is this? Most builds simply need a .targets file and some DLLs, not all the other stuff that is in the download of such SDK.
  • Some SDK’s don’t install on every platform. Why is that? Why can’t SDK X install on platform Y?
  • Will I be able to install future versions of the SDK side-by-side so “older” projects build on my machine? Or will I need a machine for every Visual Studio version separately? How to isolate these things?

This is not only Microsoft tooling and SDK’s. Various other SDKs also require installs, prerequisites, configuration, … If only that picture above would allow scrolling so you could see Amazon, Xamarin and many others in that list.

How should we solve this?

Let’s look at the Node.js community and how they manage to do things. Every project, whether an actual application, a library or component, contains an important file: packages.json. It contains a description of the project itself, as well as the dependencies it requires, both id and version. All you need to build or run most of such projects is a node executable and an Internet connection to download dependencies on the fly. Sounds familiar? It does!

We’ve been using NuGet for quite a while now in the .NET space (if you haven’t, look into it now!). We’re distributing open source projects as NuGet packages that we can depend on in our own software. We can publish our own software as a NuGet package so others can depend on it. Awesome! Then why aren’t we doing this with the 17.6 GB of SDK madness we have to install on a build machine?

I do not think we can solve this quickly and change history. But I do think from now on we have to start building SDK’s differently. Most projects only require an MSBuild .targets file and some assemblies, either containing MSBuild tasks or reference assemblies, to do their compilation work. What if… we shipped the minimum files required to succesfully build a project as NuGet packages? The NuGet gallery contains some examples of this, but there are only a few. Another example is the ReSharper SDK which is shipped as a NuGet package. Need a test runner? Wrap the executable in a NuGet package and I’ll bring it down and run it during build. My takeaway: if you have a .targets file and are wrapping it in an MSI, you are doing it wrong.

In my ideal world, all .NET projects would have a packages.config file in their root folder in which library dependencies as well as MSBuild dependencies can be described. My build machine would contain the .NET framework and Mono. And during build, all dependencies would be magically brought down for just that build.

Tuesday, March 11, 2014  |  From Maarten Balliauw {blog}

One way to remove friction from using NuGet in multiple projects is by making use of NuGet Configuration File inheritance, probably the awesomest unknown feature in there.

By default, all NuGet clients (the command-line tool, the Visual Studio extension and the Package Manager Console) all make use of the default NuGet configuration file which lives under %AppData%\NuGet\NuGet.config. NuGet can make use of other configuration files as well! In fact, NuGet can walk an entire tree of configuration files and fetch settings from those.

Which configuration file will be used?

Good question and happy you asked! The standard answer I always give to any question is: it depends. In this case on the client you are using. But ignoring that fact, here’s a generalized version of the three that is walked for building the configuration the client will work with.

  • The current directory and all its parents
  • The user-specific config file located under %AppData%\NuGet\NuGet.config
  • IDE-specific configuration files, for example:
        %ProgramData%\NuGet\Config\{IDE}\{Version}\{SKU}\*.config (e.g. %ProgramData%\NuGet\Config\VisualStudio\12.0\Pro\NuGet.config)
        %ProgramData%\NuGet\Config\{IDE}\{Version}\*.config
        %ProgramData%\NuGet\Config\{IDE}\*.config
        %ProgramData%\NuGet\Config\*.config
  • The machine-wide config file located under %ProgramData%\NuGet\NuGetDefaults.config (which, as a sysadmin, is a good one to put default configuration options in using an Active Directory Group Policy, just saying)

Full details can be found in the NuGet docs, just keep in mind that first item of the list: all clients start with a NuGet.config in the current directory and then walk up to the drive root, and only then are the standard files checked. Wow. Just WOW! This means every parent folder of a project or solution can contain additional configuration details that will be applied (note: the file that is first consulted wins).

So in short, if I have a solution file C:\Projects\CustomerA\AwesomeSolution\AwesomeSolution.sln, all NuGet clients will load configuration values from:

  • C:\Projects\CustomerA\AwesomeSolution\NuGet.config
  • C:\Projects\CustomerA\NuGet.config
  • C:\Projects\NuGet.config
  • C:\NuGet.config
  • All the other locations mentioned above

This gives some pretty interesting scenarios! Let’s cover a few. But again, check the NuGet docs for more information on possible entries in a NuGet.config.

Example 1: a project-specific configuration

So you are using a private feed? That’s a good thing! (I do hope it’s on MyGet ;-)). It’s the default for your current project? Even better! But why do all your developers have to add this feed to their NuGet configuration if a NuGet.config can be shipped in source control? Simply putting the following file right next to your .sln file will do the job:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="Chuck Norris Feed" value="https://www.myget.org/F/chucknorris" />
</packageSources>
</configuration>

Want to block access to NuGet.org and simply use the private feed all the time? Here’s some more:


<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="Chuck Norris Feed" value="https://www.myget.org/F/chucknorris" />
</packageSources>
<disabledPackageSources>
<add key="nuget.org" value="true" />
</disabledPackageSources>
<activePackageSource>
<add key="Chuck Norris Feed" value="https://www.myget.org/F/chucknorris" />
</activePackageSource>
</configuration>

Example 2: help, my devs are pushing our internal framework to NuGet.org!


Good one, good one. We don’t want that to happen. Probably they forgot the -Source parameter to NuGet.exe, but still. Accidental pushes are not fun! Place this one next to the .sln file and you should be good:


<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="DefaultPushSource" value="https://www.myget.org/F/chucknorris/api/v2/package" />
</config>
</configuration>

Feel free to combine it with example 1, it may make sense!

Example 3: NuGet.exe always asks me for proxy credentials


That is not funny. Proxies are like printers: the idea is great but when you need them things don’t always go well. Good thing is we can configure default proxy credentials. While possible to put this one in a project, it’s probably better to do this in the default %AppData%\NuGet\NuGet.config:


<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="http_proxy" value="host" />
<add key="http_proxy.user" value="username" />
<add key="http_proxy.password" value="encrypted_password" />
</config>
</configuration>

Example 4: feed inheritance and package restore


We have multiple customers, each with a specific feed they can use. Awesome! Every customer project can contain the following NuGet.config:


<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="Customer X" value="https://www.myget.org/F/customerx" />
</packageSources>
</configuration>





In the C:\Projects folder, we can add another configuration file which adds in another feed for every project located under C:\Projects. All customer projects use both of these feeds, typically. Customer specific components as well as that framework built in-house, each on their own feed. But help! All of a sudden, package restore started complaining no package named X can be found!


The reason for that is probably the active package source is set to one specific feed and not the “aggregate” of all configured feeds. Here’s a solution to that which can go in C:\Projects\NuGet.config:


<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="Our Cool Framework" value="https://www.myget.org/F/ourcoolframework" />
</packageSources>
<activePackageSource>
<add key="All" value="(Aggregate source)" />
</activePackageSource>
</configuration>

All sorts of fancy combinations are possible, the only thing you have to do is find an approach that works for you.


Enjoy!

 Maarten Balliauw {blog} News Feed 

Last edited Oct 15, 2008 at 7:15 AM by maartenba, version 4