I tried writing a simple crud api with asp.net, which should parse and respond json. It was the worst development experience I ever had while writing json apis.
Validation? Not existent. OpenAPI/swagger documentation generation? Not existent.
Then it also tried to force me into using MVC, while acting that it is express with its middlewares.
I switched back to node.js with fastify and wrote my app in an hour.
I really like C# for cli and windows desktop applications, but I probably won’t touch it for the web in the next few years.
As a C# developer I could say the same about my experience dealing with my first foray into [insert random language] and my attempt to develop [something with a non-trivial framework].
The issues you had could be attacked by navigating through this section of documentation, diving into the tutorial referenced in the beginning of the Overview section and the subsequent sections: https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=a.... This is not necessarily in defense of c# and dotnet, but this reads like you barely spent any time trying to digest the documentation.
I’ve been a C# developer for a decade and I still think it’s hopelessly convoluted for getting very simple things up and running. Maybe there is something wrong with me, but it’s just not intuitive to me and it has frankly never been. I do think the move to core and then core to .net has improved things, but it’s still a really weird and way of doing things compared to other languages that I have worked with, and most of the “boiler plate projects” are very rarely useful, so why are they there?
Then once you need to go beyond the standard libraries it becomes a nightmare to deal with. In some cases, like extending the AD libraries, it’s sort of easy to extend classes with methods but the documentation on how to do so tends to assume a lot of domain knowledge. In other cases like if EF’s standard functionality isn’t enough for you, or you need to deal with weirdly formatted XML or non standard SOAP requests (don’t ask) it can be such a nightmare that it’s sometimes easier to write a micro-service in another language to do the “translation”.
I think it speaks of a language that doesn’t see too much use by its own creators. I may be wrong on that, but having build a lot of things for Azure, Typescript has often felt more like a first class citizen than C#. Obviously not for everything, far from it, but sometimes and those sometimes are enough to make C# troublesome because unlike things like typescript that are great second class citizens in the Microsoft ecosystem, C# isn’t. It either fits really well or you have to fight it.
I wholly disagree as a person who worked in C#/.NET for over 15 years and recently waded into Node/JS/TS dev. C# and .NET are hands down the easiest platform to start on.
In my decade around management that was not my experience with onboarding new people.
Maybe that is because we didn’t have a fascist linter for C# the way we do with Typescript, but it’s always been much, much, harder to get people to make “good” C# code in my experience. It hasn’t been hard to have the build things in C#, but it’s been hard to get people to build things the same way so that they can work on each others code flawlessly. So hard that I would never again consider using resources on it until developers drop significantly in pay, which isn’t likely to happen until I’m retired, if ever.
I wonder if it has to do with regional differences. I’m Danish, everyone (there are odd cases, but it’s more “everyone” than “almost everyone”) here has a CS degree and often they’ve been taught Java, sometimes C# but poorly, while obtaining it.
And it says right at the bottom, that OpenAPI and model binding is not supported in their route to code feature.
I initially googled how to create a simple json api, and that’s the documentation which I found. Looks really easy in the beginning, but after you’re done with your routes, you’ll read at the end of the documentation, that OpenAPI generation, model binding etc is not supported. I blame that the guide‘s title is misleading and - of course - that I should’ve read till the end before actually following any step of that tutorial.
That's true (and minimal APIs help a lot) but ASP.NET still has a real problem with too much magic.
For example, the secret incantations required to output a mere string as raw json mimetype or log incoming deserialization errors* are unintuitive and very labourious - see InvalidModelStateResponseFactory. Or that I had to create a custom output formatter to output raw json. Why? Sometimes I just want ASP.NET to get out of my way and it's not trivial to tell it to let go.
* For example, url?parameter=1 for a boolean parameter, which would have worked with .NET Framework but won't for .NET Core/.NET.
I think that's the barrier with C# in general - the framework nature of it means there's a lot of "I don't know what I don't know" especially with ASP.NET which is quite large in scope. Don't get me wrong - that's the usual dev reaction when switching from their familiar language/tools to a new one but I don't think, at least historically, C#/ASP.NET made it as easy as it could of been. Which namespace do I open to import the right extension method to register swagger generation? How do I configure it? All that stuff IS existent actually and having worked with both in my current role the .NET version eventually ends up being a "just works" experience. Its just hard to approach and integrate if you don't already know the "patterns" and the libraries. Sadly there's a lot to learn compared to say Fastify for a basic working app. However it is very configurable and flexible. I've seen the same reaction from dev's to the Spring Framework as well - its just feels bloated for a lack of a better term to people coming from JS.
As per another comment after having seen JS devs switch to F# for very large professional application and not wanting to go back I feel its fine for web. YMMV.
> Which namespace do I open to import the right extension method to register swagger generation
If you use the templates provided by .NET Command Line Interface or Visual Studio, you'll get this all baked in & setup.
VS also added a very nice feature where it suggests & imports popular packages if you type a method on a type that's well known. If you already have it added to your project but need a using statement in this file, it'll pick that up fast as well.
They've also improved their docs quite a bit from years ago with lots of good examples for common things.
- Templates are no substitute for intuitive and minimal code for a number of reasons. (e.g. how to extend, how to customize, confidence that it isn't brittle if I change one thing, etc etc). If a template doesn't have the exact variation you want (e.g. a faster logging library) the learning curve is very high for a newcomer .NET dev. NOTE: I think this applies to some other OO languages too.
- Suggesting popular packages and namespaces is a great tooling improvement. But it could also imply a closed wall garden. The fact that other non C#/Java like languages don't have this problem even with something as minimal as VS Code as your IDE shows that the tooling is trying to cover over a language and/or library problem. With the Java/C#/other old OO lang workflow you need the knowledge you need to use the library itself (convention based, which class, which extension method, which namespace for that object to configure this feature, startup class conventions, etc). It isn't discoverable even with the packages imported. Remember just getting Serilog working in new ASP.Core and it taking a day or so with all the packages, config, etc etc if you don't already know what you are doing.
I like the improved docs. But fundamentally simplification/minimization is better. I think the dev workflow that means I don't need these tooling improvements is still a better experience. I like .NET, but I do understand when using other languages they seem to not have these issues despite not having the uber tooling that C# has. They don't have package suggestions, they barely even have auto complete yet the library design feels a lot more intuitive.
I can look up say a Fastify, Golang, even some F# examples with something like Giraffe and get a web app quickly with little code and no convention magic with everything being explicit yet concise. No fancy attributes I need to remember, no conventions in my startup classes I need to understand if any customisation, even dep injection is something to learn from people coming from some other platforms rather than just standard library calls composed together.
I actually like the .NET platform, don't get me wrong, I do think it is one of the best web platforms right now. Its more intuitive than Spring/Java as a comparison but that isn't saying much IMO. For newcomers I think the user experience to newcomers who are used to a lot less ceremony could be improved further. My first suggestion would be less "developer headspace required" to get started. On a personal note I think natural F# code tends to favor this from the teams I've been in but can't put my exact finger on a reason as to why - it feels more like coding Go/JS to me at least than C#.
I'm curious who does this well? I've personally not found any specific language or framework that is better than others unless you're using their preferred libraries. At that point it depends more on the library authors than the base framework.
For newcomers, I would say the best user experience (no matter language/framework) is provided by code hinting such as GitHub GitLens & competitors do. If I'm using an unfamiliar framework/language it's great at suggesting what I might want without me having to search.
You might really like the new .NET minimal APIs that are being built for web development. They're very similar to a Node.JS style of API.
In regards to logging specifically, I've found swapping logging tools fairly easy & straightforward as far as adding the logging in the code base. If there has been anything challenging it's been outside the code base & setting up the infrastructure or learning the logging's reporting tools. I'm curious what was challenging for .NET with you. It's usually as simple as using Ilogger no matter the tool & writing a few lines in the program.cs file.
Validation and Swagger/OpenAPI have been available for a long time and well documented. I don't know what resources you used to learn ASP.NET, but they failed you.
Well, while I understand, what you are trying to say (a simple crud web api should be easy to accomplish), I think that you were just overwhelmed by amount of possibilities, tutorials and outdated information, because C# / .NET is evolving fast.
That said, you may take a look at my small very early state pet project `tonehub`[1], which can be seen as pretty modern CRUD Web API in 2022, utilizing swashbuckle for OpenAPI, JsonApiDotNet for CRUD, Entity Framework 6 for Database, HostedServices for background tasks and some other nice concepts (DI / IoC, Options Pattern, FileStreams, etc.). I could also use SignalR for WebSockets / Realtime, integrated OpenID/OAUTH2 Authentication, FluentValidation for validation, Api Versioning and much more.
I've never accompilished something like this with this small amount of code...
FluentValidation and Swashbuckle are two great libraries for the tasks you referenced. This is a good enough reference repository should your curiosity be piqued again in the future: https://github.com/jasontaylordev/CleanArchitecture
Yep. The problem that the parent commenter had is distinguishing between "Not existent" i.e. the tool that I am trying out sucks; and "I don't know how to use this tool yet" - a completely normal part of the learning experience.
Failing to find the differences between them will impede learning in general.
I'm not sure which learning material you used back then but this seems more like an unfortunate accident.
With .NET 6 SDK, 'dotnet new webapi' will give you a template project that does everything you listed save for extended validation logic which you can easily add with 'FluentValidation'.
In addition, to run ASP.NET Core nowadays you only need:
var builder = WebApplication.CreateBuilder();
var app = builder.Build();
app.MapGet("/posts/{name}", ([FromRoute] string name) => /* controller logic, classes will be serialized as JSON */);
await app.RunAsync("http://localhost:8080");
This will scaffold a project which is more or less the exact same as Flask, Express, or any other "easy" framework.
OpenAPI output is built-in, but tooling for development does require a bit of knowledge (agree that Microsoft would benefit from making this work out of the box).
ASP.NET configuration is one of the most arcane parts of .NET that I don't like. You have to perform the incantation thrice: add package reference, add service reference, invoke the builder extension. And there's the right order and the wrong order of invocations, and if you pick the wrong one, your app silently won't work correctly.
Arcane? What did you expect? Add a package and magically everything works? If you make it work by just adding a reference its “too much magic”, if you make it so people write everything “it’s boilerplate” and if you do something in between “its arcane”.
Since I'm already spawning a TestHost and trying out various API calls, one of these tests basically does "curl $host/openapi/openapi.json | diff ./docs/openapi.json". If it spots a change and fails the test, I check that the difference is expected, and if so I temporarily enable and run a different "test" which actually writes the updated file.
> It was the worst development experience I ever had while writing json apis. Validation? Not existent. OpenAPI/swagger documentation generation? Not existent.
Totally opposite experience for me. C# + .NET ASP core Web Api framework + Swashbuckle + FluentValidation does out of the box what I still haven't seen a good solution for in the NodeJs world (which is the one I'm in now).
NestJS seems to hit the sweet spot for these. I'd add a proper Result type (from fp-ts) to get better error handling (than try-catch everywhere) and you're good to go.
We've just started looking into that, but the amount of existing raw JS+express we have means adopting something like NestJS is going to be a huge undertaking. What slightly baffles me is that at no point did anyone seem to stop and think if there shouldn't be a better way...
> I switched back to node.js with fastify and wrote my app in an hour.
Of course you did. You're on familiar ground.
Personally I'm also familiar with .Net and could do the same in that stack in that timeframe too. Like with many things worth doing, it requires a time investment to reach that point.
Having said that, .Net APIs support JSON request/response out of the box, validation is available on the models in seconds using a powerful set of attribute annotations, and Swagger is also built in out of the box. And API projects can seem similar to MVC ones as they use the same framework and libraries, but whilst the out of the box APIs have controllers they don't have views.
So to repeat, it's down to familiarity.
Edit: For clarity this is not a criticism. I fully understand why these things may not be obvious up front. Both the validation attributes and the Swagger URL for the default support are not obvious to the newcomer.
What do you actually mean by "non-existent"? The asp.net framework includes more functionality by default with its standard libraries than just about anything else.
I switched back to node.js with fastify and wrote my app in an hour.
I really like C# for cli and windows desktop applications, but I probably won’t touch it for the web in the next few years.