A Djangonaut's Experience With .NET MVC

Django has been my web framework of choice, ever since I switched from PHP many years ago. This semester I've been taking a web programming course, where we had to use .NET MVC, so I thought I'd share some of my thoughts on it, and how it compares to Django.

The good parts

C#

While not strictly the only option you have in terms of programming language, there's no reason not to use C#. C# feels like Java done right. It's statically typed, unlike Python, so that adds a bit of safety in the form of compilation errors ahead of time, that Python won't give you.

One gripe I have with Java is that it feels very verbose. Among other things, you have to repeat type names a lot, and I feared that C# would feel just as bad. Thankfully, that wasn't the case. You can just use "var", and the compiler (and Visual Studio - more on that in a second) will infer it for you. Also, LINQ is really nice! You can do a lot of what you do with LINQ with list comprehensions, map, filter etc. in Python. While it took me a while to learn and use the functional aspects of Python effectively, LINQ clicked nearly instantly.

I could go on about C#, but we'll leave it at that. You get the point: I quite like C#.

Visual Studio

I wasn't sure if I was going to put Visual Studio under the good parts or the bad parts, as I'm somewhat conflicted about it. While it's a very powerful programming environment (and even better with ReSharper), it's also quite heavy. For most of the project, I had to run a Windows 10 virtual machine on my Linux and Mac, and it was pretty slow.

Still, I imagine the experience would have been better if I'd run it natively, but it wasn't bad enough that I ended up dual booting to Windows for it.

The reason I wasn't sure if I should put it under "The good parts" is that, while a good IDE, it's heavily coupled to .NET (MVC). You really can't use any other development environment to develop .NET MVC applications right now. Unless you want to dig deep into configuration files and learn exactly what the IDE does. You really don't want to go there.

The .NET ecosystem has recently been open sourced, so I imagine the coupling with Microsoft tools and services will be lightened moving forward. I actually did try an early version of .NET Core on my Mac, and it almost worked. The CLI for setting up a project, and launching a web server worked, but I got a bunch of 500 internal server error messages, and didn't have time to dig further.

Django's CLI, and the fact that it can be used comfortably from any editor, is what I hope will be the future of .NET also. But I guess it's quite a big change for those who've worked with .NET from Visual Studio for a long time, and barely ever uses the command line.

Project structure

The project structure of a .NET MVC application isn't that far from a Django project. While Django uses the Model-Template-View naming convention, .NET MVC uses the more familiar Model-View-Controller. Views in .NET MVC map to templates in Django, and Controllers map to Views.

While a Django project consists of a set of applications, a .NET MVC application can be organized into "Areas".

In short, I felt right at home with the project layout.

The bad parts

Razor

The templating engine for .NET MVC is called Razor. Even thought I spent a couple of months, working an hour or two almost every day on this project, I never learned to like Razor. It seems quite minimalistic at first. Where Django uses {{ and }} to insert variables, Razor uses a @ followed by the variable name. So far so good.

It's when you try to use if statements, for loops, and clever (at least that's what you think) things that it breaks down. Razor basically gives you the full power of C# inside your views (in Django, templates), and it can quickly turn into a mess.

I also found its block scoping (if you can call it that) rules to be really confusing. Let's look at a couple of code snippets:

@if(something) {
    <span>@something</span>
}
@if(something) {
    @something
}

They should work, right? No? The second one fails, because everything from the beginning of a code block, like an if statement, until the end of it -- or -- the beginning of a HTML tag, is parsed as C#. So if you just want to conditionally show some value, you need to either wrap it in a HTML tag, or use a ternary operator and do something like @(something ? "show if true" : ""). This took me a while to understand, and even experienced .NET developers I talked to on IRC didn't immediately understand why my view code failed (it wasn't as short a snippet as above, I'll give them that).

Giving developers full access to C# in views is a bad idea. Even though Django's templates restrict what you can do, it's still tempting to insert an ugly mess of a hack instead of doing the right thing, and keep most of the logic in your views (in .NET MVC terms, the controller). Just because you can, doesn't mean you should.

Oh, the restarts

When working with Django, I'm used to making small changes, and just reload the page in the browser to see it in action. This is possible because of Python being an interpreted language, with no need for compilation ahead of time.

The situation with C# is quite different. There is no such thing as automatic rebuilding when you make a change. You have to actively stop the server, and rebuild the project again. Well, it doesn't build the whole project, but you still have to actively press several buttons or shortcuts to restart. And it still takes quite a while to launch even when no compilation is needed. The only exception is view code (in Django terms, templates), which can be changed while the application is running, and viewed by simply refreshing the browser. Such a refresh may still take several seconds, though.

This meant that I had to change the way I work quite a bit. Making lots of smaller, incremental changes, testing as I go doesn't really work in a .NET MVC project. Luckily the language, being statically typed, combined with powerful code inspection of Visual Studio and ReSharper, made it bearable. Some of the mistakes I would have made in similar code in Python, due to its dynamic nature, are no longer an issue in C#.

Conclusion

So, will I switch to C# and .NET for my future projects? Probably not. I still feel much more productive, and at home, with Django. It'll be interesting to follow the development of .NET Core, though, so maybe I'll pick it up for a small project once it has a stable release.

I know I still haven't touched on many aspects of the development experience, so depending on if people find this blog post interesting, I may do a part two. Be sure to let me know on Twitter, if you have any comments, or want to read more about this.