I have a side project which I started at the beginning of this year. One of the top goals of this project is to learn new things and i'm still at the beginning of this, but I already have many things working. Now I don't want to go into the details of the software I build. Rather I will purely focus on the technology. I decided to do the whole thing with .NET core and building it from the beginning in a way that it can be hosted on any OS where .net core is available. This post will be very opinionated and I will summarise what was/is good and what is/was bad on this ~6 months journey (which will continue, so this is just a snapshot)
The Architecture
So in short:
- The database is hosted in Azure
- There is a data access C# library with EF Core
- The main services are implemented as an Asp.net core WebAPI service
- There is a Model projects, which is shared between the WebAPI project and the client. The WebAPI project only returns instances of this model project.
- Now comes the fun part: there is one library, currently only used by the WebAPI service, which is written in F#. (And this also runs on .net core!)
- The client is a UWP app, currently on 2 project: one for the app and a DataAccess project, which is responsible for the communication with the WebAPI services.
The code is hosted in Visual Studio Team Services and the source control is done by Git.
Long term I also plan to develop clients for other systems with Xamarin. At this point I expect to break my UWP app into more parts, but currently this architecture is fine for me.
The good part
- Cross platform
Currently the whole backend part is compilable and runnable on any platform where .NET core is available. One very cool thing is that I can use my Mac (with Mac OS, or as it's nowadays called macOS) for development. At this point I only have a UWP client, but I also plan to do something for iOS and Mac (most probably with Xamarin). And at that point it will be awesome that I will be able to start and debug the backend also on Mac. I already developed iOS apps for a .NET backend, but it was always a pain to have either a Windows VM to serve the backend or to host it in Azure, while I developed the iOS client. This will be now possible on a single machine
- Entity Framework Core
There were many breaking changes between the beta versions, but it was worth it! ...I think the whole rewrite of EF was worth it. I still remember the days when I worked on a "Metro style app" for Windows 8 and because to the new Windows Runtime, where many basic .NET classes were just not implemented I was not able to use Entity Framework to connect to a SQL Server database. That was such a pain! Now EF core is really cross platform and runs everywhere where you have .NET (not matter which .NET ;) ). I always smile when I start my .NET backend on my Mac, which connects to a SQL Server in Azure.
- Visual Studio Code
IDEs are very important and there are quite a few out there, which you can use with .NET on non Windows platforms. I think VS Code can be something interesting on the long run. I always use it when I write C# or F# on my Mac and I often see non .NET people also using it. At the beginning I thought I will use the Mac for the plain backend development, but it turned out that I'm extremely used to Visual Studio and Code cannot replace it yet. Jumping around in the code and between multiple projects is currently far better in VS than in VS code, so I ended up writing code 99% of the time on my Windows machine. I'm sure if someone is willing to invest more time into VS code the dev. experience on a mac can be awesome, but for me it was not worth it, since for the UWP client I need Windows anyway. So atm this is interesting, but for me not a killer IDE. But still very nice!
The bad part
- Updating to new versions
Obviously the jumps between .net core betaX <-> .net core rc1 and then .net core rc1 <-> .net core rc2 were not always easy and I always had to change a bunch of stuff. This was all fine, since I new what I signed up for: starting to work with beta software means that there can be breaking changes. One thing, which was and still is a paint is the looong discassion about project.json. I know it is not easy to get this right first, but thanks to this changes we still have this project.json, which will eventually die and everything I invest into it will be deprecated soon. Soon, but none knows when. So already in an RTM we have something, which is deprecated and this is not good.
- C# - F# interoperability
Now this is a point which really hurts. So currently you can create an F# project with the .net CLI tool and you can also turn it into a class library and you can even reference this from another C# project. Everything compiles and works. The problem is that there is basically zero tooling support for this. There is no intellisense and Visual Studio marks every call between the two languages as an error. I also posted this on SO, but as it seems this is what we have today.
- Code sharing between ASP.NET Core and UWP
I have a plain C# project, with literally zero dependencies, where I define all my models. I only use classes from the BCL, or .NET Standard Library as it is called nowadays. Currently there is no way to share this project, so I ended up creating a .net core class library, which targets a very low .net standard version and I reference it from ASP.NET Core. Referencing this from a UWP project is not possible, so I referenced the files in the UWP project, meaning I have a single file for each model class which is references in two project. In the RC2-Tooling Preview 1 release there was an option to create a PCL and share it between ASP.NET Core and UWP. Now there is a bug in that and that just simply does not work, and was not fixed in RTM, so the only option I have now is sharing the source files. This is very ugly and inconvenient from two reasons:
- When I add a new file in the model project I have to reference it also in the UWP project. (Which I always forget, so that is basically +1 compilation with error every time I add a new Model class)
- This kills inheritance with serialisation/deserialisation. Json.NET has a cool setting called TypeNameHandling and with this you can use inheritance when you send data over the wire. Unfortunately in this case the assembly names also have to match, which is not the case when you reference a single file in two different projects.
- +1: I'm sure there are many other problems with this, which I don't know yet, but will have
So here I just wait for a solution and keep going this way. But this is definitely a pain point currently. There are many posts and talks about the .net platform standard and all that complicated stuff and still we are not able to share an assembly between asp.net and UWP (both run on .NET Core!), which basically only uses strings and ints.
- Plus a few things
There were some changes e.g. regarding serialisation, but all these can be solved by googleing.
Summary
One of the top goals of this side project for me is to learn. There are many people out there, who just talk about technology, but never build anything. I think the most effective approach for learning new technology is to take it and build something with it. In sum I would say that if I would use .net classic instead of .net core i would have been much faster and I knew this up front. But on the oder hand I learned a lot about .net core, so it was worth it.
Talking on the technical level: With RTM I think it is already very stable and I do not expect any more changes in the application level (like renaming namespaces (e.g. we had this from "AspNet" to "AspNetCore" ) or moving classes). But there will be changes on the tooling and project system level. This project.json story is not finished and sharing between UWP, Xamarin, .net classic, .net core is still a horror. .NET standard is on the way to solve exactly this problem, but that work is far from finished.
So if you start a green field project (this is my case) I would just go with .net core, many of the hurdles early adapters had are already solved. If you have existing code base then it's not that easy. In that case I would look at the existing code base and check whether it is worth it. For example the older Entity Framework versions are not compatible with EF core, so you have to make a bunch of changes in your data access code. Plus EF core only uses code first model (of course you can generate C# classes from your DB), so if you have some old EF models then you cannot use them. And there are many other examples...