Impeachment in a functional way

Functional Programming (FP) did not really click with me until I saw how it utilizes composition of functions to model pipelines of tasks. Lots of sources on the internet mention immutability and algebraic types as great advantages of FP but it was composition that won me over.

In particular, composition is perfect for describing workflows from the real world.

The impeachment process

I came across such a real world workflow in this article on Axios. The process for impeachment and removal from office goes through a number of steps where each step has two possible outcomes: Either the process terminates or it continues.

The steps are:

  1. Investigation in the House
  2. House vote
  3. Senate trial

Our goal is to model the steps in a way that mimics the terminations and continuations of the process. We also want each step to report the reason for a termination.

The non-functional way

In a non-functional language such as C# there are a number of ways you could model the process. One way would be to let each step throw an exception in case the process should be terminated. In that case the overall code would look something like this:

public void RunImpeachmentProcess()
{
    try
    {
        InvestigateInHouse();
        VoteInHouse();
        TryInSenate();
    }
    catch (Exception ex)
    {
        Log($"The impeachment process stopped: {ex.Message}.");
        throw;
    }
}

It works but it is not very elegant. Exceptions are for exceptional cases and stopping an impeachment process is not exceptional and this way is not very explicit.

Another way would be to let each function return false or true indicating termination or not.

public bool TryRunImpeachmentProcess(out string reason)
{
    if (TryInvestigateInHouse(out reason))
    {
        if (TryVoteInHouse(out reason))
        {
            return TryTrialInSenate(out reason);
        }    
    }

    return false;
}

This also works and it does not look too bad. However, if the number of steps increase above three it will end up as a mess that is hard to follow. There are other variations, for example you could mix in return statements to avoid the triangle of nested if-statement. You may also have to pass information from one step to the next as a parameter which only makes it harder and messier.

The functional way

Enter composition. With composition your code could look something like this (I will be using F#):

let runImpeachmentProcess =
    investigateInHouse
    >=> voteInHouse
    >=> tryInSenate

This is very explicit. The workflow is self-documenting and you can easily see the steps involved.

Let’s see what the implementation looks like. We start with a type that holds the result for a step, whether the process continues or terminates:

type Reason = Reason of string

type ImpeachmentResult<'T> =
| Impeach of ImpeachValue:'T
| DontImpeach of Reason 

We could have used the built-in Result type that can be either Ok or Error. Depending on your political standpoint, using Error for ending the impeachment process may not be the correct term so I created my own ImpeachmentResult type.

We now add the >=> (fish-)operator for composing two functions that each return an ImpeachmentResult:

let (>=>) a b x =
    match a x with
    | Impeach v -> b v
    | DontImpeach reason -> DontImpeach(reason)

The operator takes two functions, a and b with the following signatures:

a:'a -> ImpeachmentResult<'b>
b:'b -> ImpeachmentResult<'c>

Hence, the >=> unwraps the impeachment result of function a and feeds it into function b. The parameter x can be of any type and it does not have to be the same type for each step. I.e. each step may return different results. The only requirement is that the next function takes the same type as parameter.

Let’s add dummy implementations for the three steps (I’ll leave the actual implementation as an exercise for the reader). I have added a exitAtparameter of type ExitAtStep to each function to control which step the process should exit at. In the real world you won’t need such a parameter. However, it does show that you can pass parameters from on step to the next, all handled by the >=>operator:

type ExitAtStep =
| None
| Investigation
| Vote
| Trial

let investigateInHouse exitAt = 
    match exitAt with
    | Investigation -> DontImpeach (Reason "Investigation did not find enough evidence")
    | _ -> Impeach exitAt

let voteInHouse exitAt =
    match exitAt with
    | Vote -> DontImpeach (Reason "Less than two-thirds voted for impeachment in House")
    | _ -> Impeach exitAt

let tryInSenate exitAt =
    match exitAt with
    | Trial -> DontImpeach (Reason "Senate trial exonerated the President")
    | _ -> Impeach exitAt

Finally, we get to the workflow function that is a composition of the three steps above:

let runImpeachmentProcess =
    investigateInHouse
    >=> voteInHouse
    >=> tryInSenate

Note that for this example runImpeachmentProcess is a function of type:

runImpeachmentProcess:ExitAtStep -> ImpeachmentResult<ExitAtStep>

Let’s run it:

let run exitAt =
    let result = runImpeachmentProcess exitAt

    match result with
    | Impeach _ -> printfn "Remove from office."
    | DontImpeach (Reason reason) -> printfn "No impeachment for the following reason: %s." reason

If all three steps return Impeach, it will print out “Remove from office”. If at least one of the three steps return DontImpeach, the code will print out the reason for the exited process with the reason for the first function that returns DontImpeach. Subsequent steps will not be called if one returns DontImpeach. Let’s have a look at the output:

run None
// Remove from office.

run Investigation
// No impeachment for the following reason: Investigation did not find enough evidence.

run Vote
// No impeachment for the following reason: Less than two-thirds voted for impeachment in House.

run Trial
// No impeachment for the following reason: Senate trial exonerated the President.

Closing

Composition gives us a very strong tool for creating explicit workflows for our processes. We are able to create a function composed of other functions that each represent a step in the workflow. The code for the composed function is in itself a documentation of what it does because it very clearly shows the steps:

let runImpeachmentProcess =
    investigateInHouse
    >=> voteInHouse
    >=> tryInSenate

I am in no way the inventor of this method. I just applied it to a world (in)famous ongoing process. Please have a look at the following sources:

Please don’t use headphones when working

There are lots of good reasons why you’d want to don headphones and listen to music while coding. They block out noise and help you concentrate. There are also a number of compelling reasons why you should not.

Disclaimer: Below is based on my own experience and may not be scientifically correct.

Here are three reasons why you should leave those headphones off:

  • Increased sensibility to noise: If you wear your noise reducing head phones all the time, eventually the noice free environment will be the new normal for you. It will be much harder for you to concentrate without your headphones.
  • Missing out on networking: At you workplace your colleagues will be talking, sharing knowledge and joking around. If you are wearing headphones you will miss out and you will create an invisible barrier between you and your peers making it harder for them to involve you.
  • Hearing loss: This is the most important point. I know I sound like your father but using headphones will dramatically increase the risk of hearing loss and tinnitus and neither can be cured. When I started coding for what seems a very long time ago I would put on my headphones to block away noice and concentrate. Sadly, I now have tinnitus. It is not something that bothers me in everyday life but it gets worse when I am tired or stressed out and then it is very annoying. I know that when you are young you think that you are invincible but please be careful.

Putting on headphones may be a great help if you work in an open office and the noise gets overhand. But please, please please, listen to this grumpy old man, and do it as little as possible 🙃

Using single case union types for entity IDs in F# and make it work with Dapper

In C# it is a common and popular pattern to use strongly typed entity IDs instead of using integers or the likes for IDs on your entities. Strongly typed entity IDs is a great help when trying to prevent you from mixing an Order ID with an OrderLine ID.

Andrew Lock recently wrote a series on the topic that you should go read now.

A strongly typed entity ID may look something like this (the example used by Andrew Lock):

public readonly struct OrderId : IComparable<OrderId>, IEquatable<OrderId>
{
    public int Value { get; }

    public OrderId(int value)
    {
        Value = value;
    }

    public bool Equals(OrderId other) => this.Value.Equals(other.Value);
    public int CompareTo(OrderId other) => Value.CompareTo(other.Value);

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        return obj is OrderId other && Equals(other);
    }

    public override int GetHashCode() => Value.GetHashCode();
    public override string ToString() => Value.ToString();

    public static bool operator ==(OrderId a, OrderId b) => a.CompareTo(b) == 0;
    public static bool operator !=(OrderId a, OrderId b) => !(a == b);
}

That is a lot of code to write for every ID in your domain model and you should create a code snippet in Visual Studio to do it. However, as with many things you get this more or less for free in F# with single case union types. All it takes is this:

type CarID = CarID of int

F# will give to equal operators and the other stuff for free, hence:

let id1 = (CarID 42)
let id2 = (CarID 42)

id1 = id2 // true

As Scott Wlaschin points out on the legendary F# for fun and profit you can use single case union types for anything, not just IDs:

module Domain =
    type CarID = CarID of int
    type CarMake = CarMake of string
    type Model = Model of string

    type Car = {
        CarID: CarID;
        Make: CarMake;
        Year: int;
        Model: Model;
    }

I am not saying this is always a good idea but don’t take it for any more than an example.

What happens if you try to read a Car from a database with Dapper?

Single case union types and Dapper

Dapper uses reflection to create instances of your entity types either by calling the appropriate constructor or by setting properties. For F# record types you cannot set the properties so Dapper tries to call the constructor when querying the database:

use cn = getConnection ()
let cars = cn.Query<Car>("SELECT CarID, Make, Year, Model FROM Car")

This will fail because Dapper tries to find a constructor on OrderLine with the signature (int * string * int * string).

To help Dapper convert from int to CarID, from string to Make and so on you can register a type handler with Dapper. A type handler is a class that inherits SqlMapper.TypeHandler<>. For reading CarID from the database the type handler would look like this.

    type CarIDTypeHandler() =
        inherit SqlMapper.TypeHandler<CarID>()

        override x.SetValue(parameter: IDbDataParameter, value: CarID) =
            ()
        
        override x.Parse(value: obj) = 
            (CarID (Convert.ToInt32(value)))

You register the type handler with Dapper with SqlMapper.AddTypeHandler(typeof<CarID>, new CarIDTypeHandler()). It gets boring very quickly to write type handlers for every single single case union type you come up with (sorry about that strange sentence) and fortunately there is a way to write a generic type handler for single case union types using reflection.

    type SingleCaseUnionTypeHandler<'T>() =
        inherit SqlMapper.TypeHandler<'T>()

        override x.SetValue(parameter: IDbDataParameter, value: 'T) =
            ()
    
        override x.Parse(value: obj) =
            let cases = FSharpType.GetUnionCases(typedefof<'T>)
            FSharpValue.MakeUnion(cases.[0], [| value |]) :?> 'T

The last line makes use of FSharpValue.MakeUnion to create a union. It assumes that the union type 'T has one and only one case when using cases.[0]. I have not found a way to restrict the generic type parameter to unions.

Now you can register the type handler for all single case union types:

SqlMapper.AddTypeHandler(typeof<CarID>, new SingleCaseUnionTypeHandler<CarID>())
SqlMapper.AddTypeHandler(typeof<CarMake>, new SingleCaseUnionTypeHandler<CarMake>())
SqlMapper.AddTypeHandler(typeof<Model>, new SingleCaseUnionTypeHandler<Model>())

Closing

Above we have seen how we can easily use single case union types for type safe handling of entity IDs and other values to prevent using them interchangeably. We have also created a generic Dapper type handler for single case union types.

The generic type handler is only suitable for cases where you do not need extra logic or validation for creating your single union value types and you should also be careful when it comes to performance issues with the reflection in case you need to handle large amounts of instances.

Close the Circle

Some years back my wife introduced a new principle called “Close the Circle” into our house hold. It was something she had read about somewhere on the www (unfortunately, neither of us can find the original reference).

Closing the Circle means that you finish your job before moving on to the next.

Our interpretation is that you always clean up after you have done something. Some examples: You do not leave the dishes for the next day, you make your bed in the morning, and you clean the bit after going horse back riding (free tip: Always mention horses in your blog 🐎).

Needless to say, we keep a pretty tidy home.

Of course there will always be jobs that cannot be finished in a short period of time.  They may take weeks or months to complete.  But you  may be able to break the job into smaller task where each can be completed in a shorter time.  For example, the last couple of months I have been putting up new fencing for our horses (there, I did it again) during the weekends.  Each Saturday morning I set new goals for the weekend and when the weekend closing I set my tools aside and made sure everything looked tidy.

I like to apply the Closing the Circle principle to coding as well.

A task (on your Kanban board or whatever) should never be larger than what you can complete before moving on to the next task. That is, before moving on you
should have made a push to your remote repo and maybe even a pull request with the coded solution for the task including passing unit tests and updated documentation.

I am not saying this is what I always do. I am just saying that is what I strive to do and I think it is something that will keep your code tidy and give you a better work life balance.

Users are in for a bad experience with the Mojave app restrictions

With the Mojave update to macOS, Apple has introduced a couple of restrictions on what your apps are allowed to do. If you are the developer of apps that are downloadable outside of the Apple App Store you need to be wary of these restrictions.

The two new restrictions I will be talking about in this article is the Automation and Full Disk Access restrictions. The new restrictions on Automation will prevent apps from scripting other apps through AppleScript and the Full Disk Access will prevent apps from manipulating files owned by other apps.

In these scary times of the World Wide Web it is probably a very good idea for Apple to add these restrictions to the OS. But I do think that Apple has done it in a not very user friendly way, especially when it comes to Full Disk Access.

Full Disk Access

Unless the user has specifically given Full Disk Access to your app, it is not allowed to change files not owned by itself. If you try you will get an error telling you that it is not allowed.

Screenshot 2018-10-18 at 22.16.56

That is a good thing! You should not be allowed to mess up things for everybody else.

The problem is that Apple has not given us an API to prompt the user to give access. There is not even an API for checking if we have access to a file.

The user is in for a bad experience because they have to manually give Full Disk Access to our app in the Security & Privacy panel.

Screenshot 2018-10-18 at 22.24.09

That is absolutely terrible! Most users I have met have no clue on how and where to find the .app file or the security center. You have to write a thorough user guide to help the users and who reads user guides these days?

Fortunately, Apple has done a better job when it comes to Automation.

Automation

Mojave will stop you if your app tries to access another app through AppleScript. This too is a good thing. Imagine the mess a malicious app could do!

Fortunately, Apple has done better when it comes to usability than they did with Full Disk Access. All you as a developer need to do is add the key NSAppleEventsUsageDescription to your app’s plist.info file with a description.

Screenshot 2018-11-09 at 19.11.23

The first time the app tries to script another application, the runtime will automatically prompt the user for permissions.

Screenshot 2018-11-09 at 19.14.52

Of course, you have to make sure that your app gracefully fails if the user denies permissions.

If the user grants the permission your app is added to the Automation tab under Privacy & Security settings.

Screenshot 2018-11-09 at 19.17.56

Note how there is no way to add an app manually to the Automation tab. Shame on you, Apple!

You can clear the entire list from the Terminal:

tccutil reset AppleEvents

Hardened build

Beware that if you need a hardened build for notarisation, the good people of Apple have in all their glory decided to completely ignore the NSAppleEventsUsageDescription property unless you also specifically enable Apple Events in the Capabilities tab in Xcode.

Screenshot 2018-11-09 at 19.26.35

Conclusion

While I think it is a good idea to restrict permissions for macOS apps installed outside of the App Store, I do believe that the user experience is terrible. How many users know the consequences of granting permissions to full disk access or to Apple Events? Nobody knows what those terms mean. Apple is also making it very hard for developers to properly instruct the app users.

Next step Git for those that already know add and commit

When I first started using Git a while back it seemed pretty straight forward although I had to get used to the disconnected nature of Git which is different than how TFS works (or used to work). I mostly used Visual Studio’s Git integration and usually it worked like a charm.

But then after a while things started to get complicated. I had to work with submodules, change the remote URL, and handle untracked files. That is when I decided to move out of my comfort zone in Visual Studio and into the Git CLI.

The Git CLI is not easily remembered and everything can be done in more than one way so I started my own compilation of useful commands. Below is the result of that compilation. I hope it can be hopeful for those of you going through the same process and please let me know if you have any Git gems of your own that belong on the list.

The list

In no specific order whatsoever.

Edit configuration

On Windows the Git configuration file is usually placed under “c:\Users[user]”. You can also start an editor from the command prompt.

git config --global -e

Set editor for commit messages

To change the default editor for commit messages to Notepad++, add a [core] section to the config file looking like this.

[core]
    editor = 'C:/put-your-folder-here/Notepad++/notepad++.exe' -multiInst -notabbar

From now on Notepad++ will open when ever you run git commit without the -m switch.

Set merge tool to Visual Studio

[diff]
    tool = vsdiffmerge
[difftool]
    prompt = true
[difftool "vsdiffmerge"]
    cmd = \"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\TeamFoundation\\Team Explorer\\vsDiffMerge.exe\" \"$LOCAL\" \"$REMOTE\" //t
    keepbackup = false
    trustexistcode = true
[merge]
    tool = vsdiffmerge
[mergetool]
    prompt = true
[mergetool "vsdiffmerge"]
    cmd = \"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Professional\\Common7\\IDE\\CommonExtensions\\Microsoft\\TeamFoundation\\Team Explorer\\vsDiffMerge.exe\" \"$REMOTE\" \"$LOCAL\" \"$BASE\" \"$MERGED\" //m
    keepbackup = false
    trustexistcode = true

Submodules

Cloning submodules

If the repo contains submodules, and you want to bring the code in the submodules down, you’ll need to clone recursively.

git clone --recursive https://github.com/hocuspocus/icsharp.git

Change submodule to own fork

If you have cloned a repo with a submodule and you want to change the submodule to a different fork (if for example you have forked the submodule), you need to edit the URL in the file .gitsubmodule.

[submodule "Engine"]
    path = Engine
    url = https://github.com/scriptcs/scriptcs.git

After saving .gitsubmodule, run the command.

git submodule sync

It seems that this may detach from HEAD, so a checkout may be necessary (before making any local changes).

git checkout

If you have trouble downloading the code for the submodule, try running the command:

git submodule update --remote

Start merge tool

If there is a merge tool, you can start your merge tool (set in the config file).

git mergetool

Compare to remote

Start by fetching all from the remote repo:

git fetch origin

Then compare with local:

git log HEAD..origin/master --oneline

If you are happy with the results, you may merge the remote changes with the local repo:

git merge

Show remote URL

Show remote URL for “origin”:

git remote get-url origin

For a bit more information you may use:

git remote show origin

I your remote has moved, you can change the URL using set-url:

git remote set-url origin https://hocuspocus@bitbucket.org/myteam/myproject.git

Delete branch

Delete the remote branch:

git push -d  

For example:

git push -d origin my-feature-branch

You may also use:

git push  :

Delete the local branch:

git branch -d 

Delete local changes

Undo all unstaged local changes:

git checkout .

Undo git add for at single file:

git reset folder/file.cs

Undo git add . :

git reset .

Fix untracked files

git rm . -r --cached
git add .
git commit -m "Fixed untracked files"

Create an alias for a command

If you are tired of typing long hard-to-forget commands you can create aliases.

git config --global alias.a "add ."
git config --global alias.c "commit"

You can now just type git a to add unstaged files.

Aliases can also be added directly to the config file.

[alias]
    a = add .
    c = commit

Should you Fire a Coworker for Making an Honest Mistake?

A while back my hairdresser accidentally cut my ear. It was just a small cut and I hardly felt it but since cuts in ears have a tendency to bleed a lot my hairdresser felt really bad and almost starting crying.

After having driven home with one hand on the steering wheel and the other hand holding a towel to my ear (it’s hard to drive a stick that way), why wife went into conniptions and while she tried stopping the bleeding she demanded that I find a new hairdresser.

“Why would I do that?”, I asked.

“Well, obviously this one is highly incompetent. And she even made you pay 100 DKK for this mess”.

I said: “I am not going to find a new hairdresser. I just invested 100 DKK to be absolutely sure that this hairdresser will never cut my ear again.”

So far I have been right. The nice little scar on my ear reminds my hairdresser to be extra careful and thorough :-).


Once in a while you read about developers being fired for making honest although massive bugs. The question is: Is it the right thing to fire people?

Personally, I think it is the wrong thing to do. Making an honest mistake is not enough to get you fired.

But it all depends on how you handle that mistake. If the person who made the mistake steps up to the plate, takes responsibility and does everything he or she can to fix it and learn from it, then you as a company will not get a better co-worker by firing and hiring somebody else. The new guy might even make the same mistake. It’s also very likely that the mistake happened because the processes in your company are not good enough.

What do you think is the right thing to do?

Some Advice for Beginners

If you are new at programming, here is some sane advice for you.

The list is built from my own experience since we are all newbies at something, right?

The list could be a lot longer but I have picked 7 important pieces of advice that recently have had some relevance for me while mentoring.

1. Have Fun!

Yes, that’s right. This is the first and most important piece of advice. Coding is supposed to be fun. If you are not having fun, maybe coding is not for you 🙂

2. Use Existing Guide Lines

You may be a beginner and you may be in over your head but the sooner you start using existing guide lines such as naming standards and best practices, the sooner your coding skills will take off. Your company may have existing coding standards (they should) and they are there for a reason. Following guide lines and standards will help you and your mentor better understand the code.

Also, your code will probably not pass code review without following existing standards and it is a real pain to fix it all later.

3. Your Code is not a Special Case

I am sorry I have to break this to you but your code is in no way ground breaking or requires special treatment. That means you do not get to use gotos liberally, use inheritance like the world has never seen before, or put all 3,000 lines of your program in the same file.

Everybody else can do without strange constructs and so can you.

4. Read the Error Messages

If the compiler refuses to compile your code, then by all means read the errors messages. They may be cryptic but you might as well get used to them because it won’t be the first time you see them.

Runtime errors can be hard to figure out but the next item on this list may help you with that.

5. Debug Everything

Debugging is really, really, really important. Someone once gave me the advice to always debug through your code. So this piece of advice applies to everybody, not just beginners.

Debugging will help your understand how your code is working. Whenever I write a piece of code I step through it with the debugger, even though it appears to be working. A good way of doing this is to debug through your unit tests.

So, learn how to debug in the programming environment that you are starting to learn. Did I mention that it is important?

6. The Error is Most Likely in Your Code

If your code fails (and it will) it is like 99.99 percent certain that you are the one who introduced a bug. The bug is not in the programming language or in the platform. It is in your code!

So it you think that .NET cannot save files larger that 50 lines or that C# is slow at simple math operations, then you are wrong.

The bug is in your code!

7. Stop Excusing

Everybody seems to make excuses for their code. There is no reason to. Your code has bugs and it could be designed better but I am yet to meet a programmer who writes perfect code. If your mentor ridicules your code, you need to find a better mentor (yes, we are all guilty of laughing at some poor guy’s code).

That’s it. I hope it will make your journey into coding a tad easier.

Deploying ASP.NET Core Applications from Bitbucket to Azure

Give the most tedioust jobs to your laziest employee and they will automate it.
My boss

That’s right. I am lazy. I hate repetitive tasks. And as a developer you probably feel the same way.

One of those repetitive tasks is deployment

There are numerous ways and frameworks to set up automated builds and deployments. Some of them can do just about anything almost up to the point where they will make you coffee while you wait for your builds.

Recently while working on a small ASP.NET Core website I found out that Microsoft Azure has a very simple deployment tool for building and deploying from your favourite code repository to an Azure web application. I was especially happy to find that it supports BitBucket even though it seems anything not-on-Github is not cool.

Well, I am too old to be cool and I like Bitbucket so bear with me.

Setup

Setup is a breeze. Got to the new Azure portal and create your new web application.

After the web app has been created, go to your web app and choose “Deployment Options”.

azure-deployment-options

The next steps allow you to log in to your source code provider (i.e. Bitbucket) and choose project and branch (typically the master branch). The beauty here is that Azure supports pulling code from all kinds of sources like Dropbox, Onedrive, Github, and of course Bitbucket.

azure-deployment-options-configure

After you save your settings, Azure will fetch your last commit and start building it. You can se the progress by clicking “Deployment options” again.

azure-deployment-progress

Build Errors?

It looks like Microsoft has just recently upgraded the compiler but I have previously run into problems with building newer C# features such as inline declaration of variables like so.

var salaries = new Dictionary<string, decimal>()
{
    { "Jakob", 10000000000 },
    { "Some other guy", 42 },
};

// Inlining variable declaration
if (salaries.TryGetValue("Jakob", out var salary))
{
    // Do something with salary.
}

If you run into this problem, all you need to do is add the Nuget package Microsoft.Net.Compilers to your project. This will make sure that your project is compiled with the latest C# compiler.

Conclusion

This kind of deployment is extremely simple and easy, which is a good thing. On the other hand it will not run any unit tests in your project and it will deploy straight to production without any testing or staging. You might consider this solution for smaller, non-mission-critical sites.

Creating Your Own Visual Studio Project Template

All code on Github.

In previous articles (1 and 2) I walked through how to add Webpack and Typescript to a Visual Studio ASP.NET Core MVC project.

It turned out to be quite a cumbersome and error prone process and it is not something you wish for your worst enemy to go through twice (or maybe you do – I don’t know).

Luckily, it is quite easy to create your own project templates for Visual Studio so that you can repeatedly create new projects with the same setup.

As you probably know, you can create new projects for Visual Studio by using the dotnet new command. For example you can create a new ASP.NET Core MVC project by running

dotnet new mvc -n "MyFacebookKillerApp"

Type dotnew new to list all available templates.

Wouldn’t it be nice if we could do the same thing for our ASP.NET MVC with Webpack and Typescript thingy project? Fortunately, we can (otherwise this would be a very uinteresting article).

First step is to configure our template.

Configuring the Template

Start by creating a folder named “.template.config” at the root folder of your solution. This is typically where the .sln file is sitting.

Create a file named “template.json” inside the “.template.config” folder. Insert the following into the file and change the relevant properties (such as author, identity, shortName, and sourceName):

{
  "author": "Jakob Christensen", 
  "classifications": [ "Web" ],
  "name": "ASP.NET MVC Core with Knockout/Webpack/TypeScript",
  "identity": "t4rzsan.MvcKnockoutTypeScript", // Unique name for this template
  "shortName": "mvcknockouttypescript", // Short name that can be used on the CLI
  "tags": {
    "language": "C#"
  },
  "sourceName": "CoreWebApplication2", // Will replace the string 'CoreWebApplication2' with the value provided via -n.
  "preferNameDirectory": true,
  "exclude": [ "**/[Bb]in/**", "**/[Oo]bj/**", ".template.config/**/*", "**/*.filelist", "**/*.user", "**/*.lock.json", "**/node_modules/**/*" ]
}

Choose something brief but meaningful for “shortName”. This is the name that you will use when running the dotnet new command.

The property “sourceName” is important. When the template runs, the string “CoreWebApplication2” will be replaced by whatever the user specifies for the -n(ame) parameter for dotnet new. The text will be replaced in all files. That includes namespaces in .cs files and renaming of .csproj files. So you must change “CoreWebApplication2” to whatever you used as project name for the solution, you are using as template for your template (if you know what I mean).

I have set “preferNameDirectory” to true which means that dotnet new will use the name of the current folder as project name if -n has not been specified.

When you are done with the configuration it is time to register the template.

Registering the Template

You install the template by running the command dotnet new --install [folder] where [folder] is the path to the parent folder of “.template.config”. So, for me that would be

dotnet new --install C:\Users\Jakob\Source\Repos\CoreWebApplication2

When listing the installed templates you will we your own short name in the list:

dotnetnewinstall

Finally, let’s see if it works.

Using the Template

Create a new folder somewhere for your new project and CD your way to the folder in the command prompt. Start by typing (insert your own short template name):

dotnet new mvcknockouttypescript

That’s it. Very cool!

By the way, Don’t forget to update npm and install all dependencies for the new project.

npm update npm@latest -g
npm install
npm run build