So, on the plus side with the new .net, I recently made a .net core web app on Linux, and generally it's been pretty easy.
I'm also impressed at just how fast asp.net core is compared to asp.net, the time it takes to open your site in debug mode has dropped dramatically, from what used to be 1/2 minute in asp.net to a few seconds in .net core.
On the bad side? Mainly the asp.net core team and their push for Dependency Injection and the really poor async code has got to be the most frustrating thing about the whole thing.
My biggest bugbear is the way you access your config, which is an absolute and utter kafka-esque mess. Because someone at MS was drinking the DI kool-aid you have to add a minimum of 5 lines of code to any class you want to access config values in, and you're in for an even bigger nightmare if you want to separate business logic and web code into two projects (which is a pretty common design). I've given up with the config DI and just assign them all to static variables. I still don't get why you'd even want your config injected!
The entire authentication uses async code too, which still has all the normal problems of being hard to debug, silently failing if you invoke it wrong and completely overwhelming the callerstack with a bunch of redundant calls.
Huge disadvantages with absolutely zero performance gains for 95% of programmers.
Having been using express again recently, I'm seriously thinking of ditching the asp.net core stack despite my general preference for statically typed languages. C# is great, but the asp.net core are so obsessed with shoving DI and async down your throat and making you write really unpleasant, boilerplate code. Feels like you're back in 1990 with all the FactoryFactoryFactories.
> My biggest bugbear is the way you access your config, which is an absolute and utter kafka-esque mess. Because someone at MS was drinking the DI kool-aid you have to add a minimum of 5 lines of code to any class you want to access config values in
I'm not sure if maybe you're referring to the Options<T> stuff?
The way I do it is pretty simple.
1. Create a POCO that represents your config. You can have properties for bested configs if you want, e.g. SecurityConfig, MessageBusConfig
2. When the app starts, use a ConfigurationBuilder to build an IConfiguration from whatever Co fig sources you want - typically JSON files and env vars
3. Bind the IConfiguration to your POCO
4. Configure both IConfiguration and the POCO as singletons
Now you can inject the POCO config object wherever you want it, or the IConfiguration should you need it. I feel like this is simple, and works well for dev, test and prod.
I agree. The first thing I always do is make a custom Settings class which just loads settings via good old `Environment.GetEnvironmentVariable`. Super simple and never failed me.
Bonus Points, by loading all settings at once into strongly typed properties at startup, it will fail fast if a setting is missing, which to me is a benefit.
But I still pass this class via DI to the controllers for testability reasons. If you are using ASP Net, just do things the asp-net way for the sake of other people who have to inherit the code.
You'd want your config injected so that you can swap out configs for test harnesses for continuous integration and deployment. It's one of the mainstays of making your software deployable by automation.
I agree with the DI for config and async push. Too much ceremony for a very simple task. Async being used by auth can certainly be frustrating if you have sync code that needs to use it at some point. Then suddenly you have to redo all sync code that calls the async method.
I’ve been experiencing the same issue with some Azure SDKs that only expose async methods rather than both async and sync. Frustrating to have to redo 8 caller functions to make a single sdk call.
Authentication is in the request pipeline, so it makes sense that it's async if you're talking to some sort of storage engine. We're using the async APIs to pull user/client app information from our database. Why would we want that to be synchronous?
The async stuff may require some attention, but it's part of the performance story when dealing with many requests, not when evaluating just one.
As regards configuration, all the means you could want for configuration are there. You can access items directly [1], or via strongly typed objects. These all support multiple sources of configuration data, and many means of overriding them.
I generally really don't like environment variables as they expose configured secrets to everything in the same machine / container, but we make use of the standard configuration system's environment variable overrides, but we use akv2k8s.io and thus only expose secrets to the container's entry point application.
[1] public Startup(IConfiguration config) { // injects config store
var setting = config["yourConfigKey"] // ... but you now have to convert this from a string for any other datatype
}
Yeah, the DI stuff is a lot, but eventually bringing in the dependencies becomes total autopilot.
> I've given up with the config DI and just assign them all to static variables.
Not to be a fanboy, but it's designed in a way where you CAN use all the fancy features. If you want something simpler, you can just do exactly what you did.
This syntax is probably wrong because I'm doing this from memory, you should probably also use the Lazy class or something, and if I were to actually write this code I'd think twice about thread safety -- but if you want simple static access to config values, you can just do this:
public static MyConfigPoco MyConfig {get;set;} = JsonConvert.DeserializeObject<MyConfigPoco>(File.ReadAllLines("appsettings.json")) ;
Can't you just ignore the built in configuration and roll your own (probably there's a dotenv library?). That said, I've also personally moved away from C# despite really likeing the lanaguage due to a lacking ecosystem.
I'd recommend both node with TypeScript and Rust for backend web development in a statically typed langauge.
I found Go to be a really nice replacement for C#. It has the static typing and garbage collection, but you also get a self-contained binary executing without the requirement of an external runtime environment. I also discovered that I don't miss classes at all.
Also, I find DI to be very useful. I dont know about small projects, but in any reasonable size projects, having a DI container is a god send. Easy to setup and use.
>and you're in for an even bigger nightmare if you want to separate business logic and web code into two projects (which is a pretty common design). I've given up with the config DI and just assign them all to static variables.
So you have static variable in web project and then add reference to web project to obtain that config? Do I get that right?
I never felt like config DI was a problem once you did all the stuff that you do at the beginning of the project
You also have to understand that shoving async down our throats is part of the philosophy of how aspnet core and kestrel (built ontop of libuv) is implemented: the whole stack is built to run async and with DI in mind. aspnet core itself uses the same DI system to manage itself.
No part of aspnet core is built to run synchronous. Its all async all the way down.
This is a pretty interesting comment section to read. I went from Node.js to .NET Core development for about a year, and got the impression that Microsoft had already figured out all the best practices, and shoving it down my throat was for my own good, so I didn’t question whether or not DI was good, as if it was dogmatic. My team thinks the same. I thought DI was pretty much the final conclusion to how software should be architected due to the collective trial-and-error of decades of OOP programmers.
In usual HN fashion, even the most seemingly obviously true points to me are being argued and refuted.
Agree with your complaint on async. And on asp.net, async doesn't disrupt that much the workflow (but creates the possibility for deadlocks). But if you are dealing with a UI and make a method async, then suddenly you have a ton more problems to deal with, like what happen if the user changes the state while you are waiting for an async call. That increases a lot the complexity of the code. Which is why I am lukewarm about their approach of mandating async for new features.
C# is great, but the asp.net core are so obsessed with shoving DI and async down your throat and making you write really unpleasant, boilerplate code. Feels like you're back in 1990 with all the FactoryFactoryFactories.
It's been said that C# is "Microsoft's Java". That applies not only to the language, but the culture of "enterprise-ism" (insanely excessive abstraction and complexity) that seems to permeate throughout the code.
I worked briefly with Enterprise Java a long time ago, and it brings back much of those memories whenever I have to look for something in a C# codebase.
Most DI containers are not just injectors, but they also manage life cycles/scopes of objects: singleton/transient/scoped.
Since in web development, a request hitting a controller endpoint is typically short lived and most objects and services are tied to the main request scope, it makes sense that all your objects should live and die when the request is made and completed. What is the cleanest way to manage this life cycle scopes? Dependency Injection. Most of your object/services will be "scoped", with fewer being transient (aka a pool of reusable objects) and the fewest being singletons that will survive individual requests.
A second side effect of DI, it forces you to code by convention. Conventions make maintaining the code 6 months from now a breeze. Want to add a new service? Just let it inherit from an IService and consume it in 10 places, it will auto find/inject your new code. No need to new() up and dispose your service in 10 place.
Do all of this without DI and use only constructors + Dispose(). Good luck! Mercy on the poor soul who has to maintain all that mess.
If you want to go a step further, instead of having 100's of IService and each constructor declaring they each need 10 of them (ILoggerService, IAccountService, IEmailService, IStockService etc etc)... that also becomes very gross in large projects: so to go a step further, use the Mediator pattern. You can either implement your own (super easy) or use the Mediatr nuget package. Then each service becomes much cleaner. Each service then only has 1 method that does work. It also ties in nicely with the Unit of Work pattern.
Why should my IStockService inject the IEmailService when I just want to check stock levels with GetLatestStock() that return an int and does no other work?
Lets say the IStockService has 15 methods to do with stock and 10 dependencies. So on each request where you depend on IStockService, you would also pull in the 10 dependencies and their inner dependencies which may add 1 second to your response time and uses 10mb RAM. But all you wanted to was check stock which takes 10ms and 1mb RAM.
This is exactly the scenario that mediator pattern can help solve. So your 15 methods become 15 individual classes, each pulling in ONLY the dependencies it needs and nothing more. Your file and git commits stay small too which makes everything more digestible (less than 100 lines of code if lucky),
So my favourite setup is DI + Mediatr. Each file/class has only ONE purpose to exist and only one reason to be pulled into a dependency tree, all while DI will manage their life cycles.
Edit: For those downvoting, please go read "Dependency Injection by Mark Seemann" and also read https://docs.microsoft.com/en-us/aspnet/core/performance/per... . Then try to build your own framework from scratch. Do it. Then come crawl back and upvote this comment. I've have a ton of experience with this stuff and have built 2 or 3 custom frameworks. The core trait that keeps everything sane and fast is to keep things simple, keep dependencies low, keep hot paths lean. The easiest way to get to that place is DI + Mediatr and to break some services into their own api's if they get deployed too often. It's that simple.
Having been using express again recently, I'm seriously thinking of ditching the asp.net core stack despite my general preference for statically typed languages.
Microsoft has made exceptional strides in terms of performance and compatibility.
The whole vision is what is really impressive, not any individual part.
It is cross-platform, open source, and has almost complete coverage of the old .NET APIs. The new csproj format is vastly superior. The new dotnet CLI is a pleasure to use.
Many of the surrounding libraries like ASP.NET, Kestrel, LINQ, Entity Framework Core, System.Text.Json, etc are best in class.
I look forward to the Linker becoming stable, as this will really help in contexts such as Azure Functions and AWS Lambda.
The future is very bright for .NET. It has the right raison d'etre - .NET is part of the growth story for Nadella-Microsoft.
They already have you programming in their editors (VS/Code) and pushing to their VCS (Github). They're even teaching you the C# type system with TypeScript :) If they can just convince you to use their stack, Azure will win you over from AWS every time.
As a result, I really wanted to adopt .NET earlier this year. But they have some work to do to make the ecosystem approachable to newcomers.
One of the core issues feels so... trite. But experiencing it, I realized how real it really was:
The Names. Microsoft has created a Ninja Warrior obstacle course of proper nouns.
It is comical. It is worthy of parody.
.NET, the CLR, and their relation to C# and F#. ASP.NET, ASP.NET MVC, ASP.NET Web Api, Blazor vs Razor, .NET Core vs .NET Framework vs .NET Standard.
I think I could draw the lines between all those with about 50% accuracy. And I read like 3 books on .NET before diving in.
It's bad off the top when you're trying to figure out which way is up in the ecosystem. It goes from bad to worse when you're looking through docs and Stack Overflow answers.
It was almost never immediately clear if a document I was looking at on Microsoft's own website applied to me or not. That is a cardinal sin of technical documentation.
Ultimately, this meant that .NET Core Web API (or whatever I was using) felt poorly documented.
I'd find myself looking at docs that mention .NET Web API - but I can't remember if that rolls up to .NET Core or Framework -- or both? Am I using MVC? Is Web API a subset of MVC? No clue.
It's definitely a hard problem. Here's to hoping that now that everything is unified, they can work on paving clearer roads into their ecosystem.
As someone who uses .NET daily, but loves Clojure and other functional programming paradigms - Records seem like a very compelling feature. Immutable data structures without any hassle to set up. Simply write “record” where you would normally write “class” and boom, you are working with immutable objects. This is one step closer to one the best features of Clojure IMO -everything is immutable.
Additionally, there seems to be another new way to accomplish this. Normally class properties are accessed via get; and set;
Now we have the ability to use get; and init; which effectively makes the object immutable/read only after initialization. The syntax is just a little cleaner and more obvious to the reader how the property should be used.
C# has really been adding some great features the past few years and is certainly getting more expressive and concise which I appreciate.
Congratulations to the team but more than a year after the Surface Pro X shipped and there is still no way to build desktop applications for aarch64 using dotnet/vs2019 on the local machine. Windows on ARM has no native support for WPF, WinForms, or WinUI.
Visual Studio 2019 running as x86 32bits application can't see the local machine as a target for aarch64 applications. When I asked microsoft, the response was to use a x86-64 machine to develop on the same LAN as the aarch64 machine and use remote debugging. So you need two machines to ship a desktop application.
This is bad, and part of the reason there are so few app running natively on the Surface Pro X.
> From what we’ve seen and heard so far, .NET 5.0 delivers significant value without much effort to upgrade.
From the previous version of .Net Core only. They've done absolutely nothing to make migrating from MVC 5 any easier, while proclaiming that this somehow merges .Net Framework and .Net Core. Going from MVC 5 to .Net 5.0 MVC is a complete re-write of the web layer from an empty project upon up (even according to their own article[0]).
I think the poor messaging on .Net 5.0 bugs me more than the actual work required for the mitigation (which hasn't changed significantly). .Net 5.0 is just .NET Core 4 with a fancy new name.
> .NET 5.0 is a current release. That means that it will be supported for three months after .NET 6.0 is released. As a result, we expect to support .NET 5.0 through the middle of February 2022. .NET 6.0 will be an LTS release and will be supported for three years, just like .NET Core 3.1.
I'm excited about this! I've used .NET Core to build some CLI tools for Linux in F#. It's great to have an alternative to Go in terms of mainstream, high level languages (read: has tons of good libraries) that can compile to an easily distributed Linux binary.
Congrats to everyone involved. This is a huge accomplishment and arguably many steps in the right direction.
We are very excited to get our hands dirty with .NET 5 sometime in Q1 next year. We currently run on .NET Core 3.1. I expect our migration from 3.1=>5.0 will be a total non-event, but we don't want to risk any regressions during our current crunch phase. Our migration from 4.7=>2.0 was the most difficult, but once we got everything off Framework and onto Core things have been going really smoothly with the incremental upgrades. Really hoping this trend continues indefinitely.
The only part of .NET 5.0 that has left me disappointed is the continued lack of polymorphic deserialization support in System.Text.Json - a la Newtonsoft.Json's TypeNameHandling enumeration. This is the only thing holding us back from migrating to this first-party dependency. I have already left feedback regarding our use case in the appropriate dotnet/runtime GH issue.
The biggest new features I am looking forward to are the performance enhancements surrounding startup time, GC, etc. Improved P95 latency is something that will be very welcome in some of our busier environments.
In terms of the overall package that .NET brings to the table, we couldn't be happier. Sure, VS could run a little smoother and some of the configuration/DI stuff can be very aggravating (at first), but overall its a fantastic experience.
It is a bit sad that so-called "native AOT" was not included in the release. When I heard last year that .NET 5 would support single-file binary, I expected it to be the same as something like Rust or Go would offer. But no, Microsoft changed the meaning of AOT and moved the goal post, introducing the real AOT as "native AOT". Thankfully they are aware of the issue, so I hope to finally see in when .NET 6, which will also be an LTS release, is released.
the highlights are great. 2 lowlights:
- HttpClient/WebRequest ReadWriteTimeout is silently ignored which can result in infinitely hung sockets when doing synchronous network i/o
- System.Speech is unsupported
I wish the post was more direct that .NET 5 is the successor to .NET Core 4. I gathered this was the case but it didn't feel clear that I don't need '.NET Core' anymore to run .NET on mac/linux.
On the other hand, I'm still missing an easier interop with other ecosystems. C# is an easy to use language and I would love to write some common code / business logic / whatever you name it in C# and expose it as webassembly and C/C++, this would cover mobile, web and desktop workloads. You can do something like that with Rust (or at least they claim it, I never tried), but with C# I don't see any _easy way_ doing it. I would be happy if someone could correct me If I'm wrong.
Maybe in a year or eighteen months, I'll be able to move to this, from Framework code that still has dependencies that nobody has ever updated to .NET Core.
This version will be nearly out of support by then...
I know .NET Core applications could run on Linux. But do they natively (without any wrappers) support Linux OR is there a wrapper to simulate windows within Linux?
The C# libraries either invoke the native Linux libraries directly or go throw a thin wrapper[1] that does the normal things you have to do to support multiple flavors of Unix (epoll vs kqueue, etc). Parts of the C++ runtime are written in terms of the Win32 API and on Unix these API are implemented in the PAL[2]. The PAL is not that big and I don’t the steady state performance critical code paths go through it.
Someone already answered this, but yes, it's native. I've been building with C# since it was first released, and dotnet core has really opened up development on Linux for me - I build apps for Linux and Docker all the time, and they "just work" the same as they do on Linux.
It would never achieve its performance if it would wrap something. .NET on Linux is as native on Linux as is Java, Python or Go. Also priority in Microsoft has completely changed. Most .NET runs on Linux nowadays (dockerized or not).
It actually does the opposite: it is able to expose memory-alike resources (from e.g. the network interfaces) deep into its consuming programs by using abstractions like Span<T>. And while that sounds like a wrapper, it is actually (depending on the "alike") just a typed and safe pointer.
[+] [-] mattmanser|5 years ago|reply
I'm also impressed at just how fast asp.net core is compared to asp.net, the time it takes to open your site in debug mode has dropped dramatically, from what used to be 1/2 minute in asp.net to a few seconds in .net core.
On the bad side? Mainly the asp.net core team and their push for Dependency Injection and the really poor async code has got to be the most frustrating thing about the whole thing.
My biggest bugbear is the way you access your config, which is an absolute and utter kafka-esque mess. Because someone at MS was drinking the DI kool-aid you have to add a minimum of 5 lines of code to any class you want to access config values in, and you're in for an even bigger nightmare if you want to separate business logic and web code into two projects (which is a pretty common design). I've given up with the config DI and just assign them all to static variables. I still don't get why you'd even want your config injected!
The entire authentication uses async code too, which still has all the normal problems of being hard to debug, silently failing if you invoke it wrong and completely overwhelming the callerstack with a bunch of redundant calls.
Huge disadvantages with absolutely zero performance gains for 95% of programmers.
Having been using express again recently, I'm seriously thinking of ditching the asp.net core stack despite my general preference for statically typed languages. C# is great, but the asp.net core are so obsessed with shoving DI and async down your throat and making you write really unpleasant, boilerplate code. Feels like you're back in 1990 with all the FactoryFactoryFactories.
[+] [-] GordonS|5 years ago|reply
I'm not sure if maybe you're referring to the Options<T> stuff?
The way I do it is pretty simple.
1. Create a POCO that represents your config. You can have properties for bested configs if you want, e.g. SecurityConfig, MessageBusConfig 2. When the app starts, use a ConfigurationBuilder to build an IConfiguration from whatever Co fig sources you want - typically JSON files and env vars 3. Bind the IConfiguration to your POCO 4. Configure both IConfiguration and the POCO as singletons
Now you can inject the POCO config object wherever you want it, or the IConfiguration should you need it. I feel like this is simple, and works well for dev, test and prod.
[+] [-] 0xcoffee|5 years ago|reply
Bonus Points, by loading all settings at once into strongly typed properties at startup, it will fail fast if a setting is missing, which to me is a benefit.
But I still pass this class via DI to the controllers for testability reasons. If you are using ASP Net, just do things the asp-net way for the sake of other people who have to inherit the code.
Outside of AspNet I never use any automatic DI.
[+] [-] balabaster|5 years ago|reply
[+] [-] elamje|5 years ago|reply
I’ve been experiencing the same issue with some Azure SDKs that only expose async methods rather than both async and sync. Frustrating to have to redo 8 caller functions to make a single sdk call.
[+] [-] lwansbrough|5 years ago|reply
[+] [-] mdpm|5 years ago|reply
As regards configuration, all the means you could want for configuration are there. You can access items directly [1], or via strongly typed objects. These all support multiple sources of configuration data, and many means of overriding them.
I generally really don't like environment variables as they expose configured secrets to everything in the same machine / container, but we make use of the standard configuration system's environment variable overrides, but we use akv2k8s.io and thus only expose secrets to the container's entry point application.
[1] public Startup(IConfiguration config) { // injects config store var setting = config["yourConfigKey"] // ... but you now have to convert this from a string for any other datatype }
[+] [-] jiggawatts|5 years ago|reply
One curious thing is that Java has elected to use lightweight threads instead of async methods: https://www.javacodegeeks.com/2019/12/project-loom.html
Their arguments are compelling:
- Works with existing debuggers and debugging techniques.
- Stack traces aren't polluted with irrelevant garbage.
- Doesn't create method apartheid, where async and non-async can't "mix".
- Doesn't force library authors to "buy into" the async model.
[+] [-] jackfoxy|5 years ago|reply
Should be able to likewise give you a much simpler and understandable config model.
https://safe-stack.github.io/
[+] [-] GordonS|5 years ago|reply
I do this with a lot (most?) web apps, and don't have any issues with it at all - what kind of problems are you seeing?
[+] [-] asdfman123|5 years ago|reply
> I've given up with the config DI and just assign them all to static variables.
Not to be a fanboy, but it's designed in a way where you CAN use all the fancy features. If you want something simpler, you can just do exactly what you did.
This syntax is probably wrong because I'm doing this from memory, you should probably also use the Lazy class or something, and if I were to actually write this code I'd think twice about thread safety -- but if you want simple static access to config values, you can just do this:
public static MyConfigPoco MyConfig {get;set;} = JsonConvert.DeserializeObject<MyConfigPoco>(File.ReadAllLines("appsettings.json")) ;
[+] [-] nicoburns|5 years ago|reply
I'd recommend both node with TypeScript and Rust for backend web development in a statically typed langauge.
[+] [-] Lendal|5 years ago|reply
[+] [-] kumarvvr|5 years ago|reply
[+] [-] tester756|5 years ago|reply
So you have static variable in web project and then add reference to web project to obtain that config? Do I get that right?
I never felt like config DI was a problem once you did all the stuff that you do at the beginning of the project
[+] [-] BatteryMountain|5 years ago|reply
No part of aspnet core is built to run synchronous. Its all async all the way down.
[+] [-] nexus2045|5 years ago|reply
In usual HN fashion, even the most seemingly obviously true points to me are being argued and refuted.
[+] [-] cm2187|5 years ago|reply
[+] [-] userbinator|5 years ago|reply
It's been said that C# is "Microsoft's Java". That applies not only to the language, but the culture of "enterprise-ism" (insanely excessive abstraction and complexity) that seems to permeate throughout the code.
I worked briefly with Enterprise Java a long time ago, and it brings back much of those memories whenever I have to look for something in a C# codebase.
[+] [-] BatteryMountain|5 years ago|reply
Most DI containers are not just injectors, but they also manage life cycles/scopes of objects: singleton/transient/scoped.
Since in web development, a request hitting a controller endpoint is typically short lived and most objects and services are tied to the main request scope, it makes sense that all your objects should live and die when the request is made and completed. What is the cleanest way to manage this life cycle scopes? Dependency Injection. Most of your object/services will be "scoped", with fewer being transient (aka a pool of reusable objects) and the fewest being singletons that will survive individual requests.
A second side effect of DI, it forces you to code by convention. Conventions make maintaining the code 6 months from now a breeze. Want to add a new service? Just let it inherit from an IService and consume it in 10 places, it will auto find/inject your new code. No need to new() up and dispose your service in 10 place.
Do all of this without DI and use only constructors + Dispose(). Good luck! Mercy on the poor soul who has to maintain all that mess.
If you want to go a step further, instead of having 100's of IService and each constructor declaring they each need 10 of them (ILoggerService, IAccountService, IEmailService, IStockService etc etc)... that also becomes very gross in large projects: so to go a step further, use the Mediator pattern. You can either implement your own (super easy) or use the Mediatr nuget package. Then each service becomes much cleaner. Each service then only has 1 method that does work. It also ties in nicely with the Unit of Work pattern.
Why should my IStockService inject the IEmailService when I just want to check stock levels with GetLatestStock() that return an int and does no other work?
Lets say the IStockService has 15 methods to do with stock and 10 dependencies. So on each request where you depend on IStockService, you would also pull in the 10 dependencies and their inner dependencies which may add 1 second to your response time and uses 10mb RAM. But all you wanted to was check stock which takes 10ms and 1mb RAM.
This is exactly the scenario that mediator pattern can help solve. So your 15 methods become 15 individual classes, each pulling in ONLY the dependencies it needs and nothing more. Your file and git commits stay small too which makes everything more digestible (less than 100 lines of code if lucky),
So my favourite setup is DI + Mediatr. Each file/class has only ONE purpose to exist and only one reason to be pulled into a dependency tree, all while DI will manage their life cycles.
Edit: For those downvoting, please go read "Dependency Injection by Mark Seemann" and also read https://docs.microsoft.com/en-us/aspnet/core/performance/per... . Then try to build your own framework from scratch. Do it. Then come crawl back and upvote this comment. I've have a ton of experience with this stuff and have built 2 or 3 custom frameworks. The core trait that keeps everything sane and fast is to keep things simple, keep dependencies low, keep hot paths lean. The easiest way to get to that place is DI + Mediatr and to break some services into their own api's if they get deployed too often. It's that simple.
[+] [-] girvo|5 years ago|reply
[+] [-] davidfowl|5 years ago|reply
[+] [-] Scarbutt|5 years ago|reply
Why not typescript?
[+] [-] hu3|5 years ago|reply
But the ASP.NET part feels bloated.
Is there a simpler .NET framework?
[+] [-] kumarvvr|5 years ago|reply
Very curious. Why do you think it is poor ? Are you comparing it against other languages or frameworks?
[+] [-] brainzap|5 years ago|reply
[+] [-] nwah1|5 years ago|reply
Microsoft has made exceptional strides in terms of performance and compatibility.
The whole vision is what is really impressive, not any individual part.
It is cross-platform, open source, and has almost complete coverage of the old .NET APIs. The new csproj format is vastly superior. The new dotnet CLI is a pleasure to use.
Many of the surrounding libraries like ASP.NET, Kestrel, LINQ, Entity Framework Core, System.Text.Json, etc are best in class.
I look forward to the Linker becoming stable, as this will really help in contexts such as Azure Functions and AWS Lambda.
[+] [-] _acco|5 years ago|reply
They already have you programming in their editors (VS/Code) and pushing to their VCS (Github). They're even teaching you the C# type system with TypeScript :) If they can just convince you to use their stack, Azure will win you over from AWS every time.
As a result, I really wanted to adopt .NET earlier this year. But they have some work to do to make the ecosystem approachable to newcomers.
One of the core issues feels so... trite. But experiencing it, I realized how real it really was:
The Names. Microsoft has created a Ninja Warrior obstacle course of proper nouns.
It is comical. It is worthy of parody.
.NET, the CLR, and their relation to C# and F#. ASP.NET, ASP.NET MVC, ASP.NET Web Api, Blazor vs Razor, .NET Core vs .NET Framework vs .NET Standard.
I think I could draw the lines between all those with about 50% accuracy. And I read like 3 books on .NET before diving in.
It's bad off the top when you're trying to figure out which way is up in the ecosystem. It goes from bad to worse when you're looking through docs and Stack Overflow answers.
It was almost never immediately clear if a document I was looking at on Microsoft's own website applied to me or not. That is a cardinal sin of technical documentation.
Ultimately, this meant that .NET Core Web API (or whatever I was using) felt poorly documented.
I'd find myself looking at docs that mention .NET Web API - but I can't remember if that rolls up to .NET Core or Framework -- or both? Am I using MVC? Is Web API a subset of MVC? No clue.
It's definitely a hard problem. Here's to hoping that now that everything is unified, they can work on paving clearer roads into their ecosystem.
[+] [-] elamje|5 years ago|reply
Additionally, there seems to be another new way to accomplish this. Normally class properties are accessed via get; and set;
Now we have the ability to use get; and init; which effectively makes the object immutable/read only after initialization. The syntax is just a little cleaner and more obvious to the reader how the property should be used.
C# has really been adding some great features the past few years and is certainly getting more expressive and concise which I appreciate.
[+] [-] modernerd|5 years ago|reply
https://devblogs.microsoft.com/dotnet/announcing-f-5/#string...
Knew it was coming but still really happy to see this.
[+] [-] soapdog|5 years ago|reply
Visual Studio 2019 running as x86 32bits application can't see the local machine as a target for aarch64 applications. When I asked microsoft, the response was to use a x86-64 machine to develop on the same LAN as the aarch64 machine and use remote debugging. So you need two machines to ship a desktop application.
This is bad, and part of the reason there are so few app running natively on the Surface Pro X.
[+] [-] Someone1234|5 years ago|reply
From the previous version of .Net Core only. They've done absolutely nothing to make migrating from MVC 5 any easier, while proclaiming that this somehow merges .Net Framework and .Net Core. Going from MVC 5 to .Net 5.0 MVC is a complete re-write of the web layer from an empty project upon up (even according to their own article[0]).
I think the poor messaging on .Net 5.0 bugs me more than the actual work required for the mitigation (which hasn't changed significantly). .Net 5.0 is just .NET Core 4 with a fancy new name.
[0] https://docs.microsoft.com/en-us/aspnet/core/migration/mvc?v...
[+] [-] SloopJon|5 years ago|reply
> .NET 5.0 is a current release. That means that it will be supported for three months after .NET 6.0 is released. As a result, we expect to support .NET 5.0 through the middle of February 2022. .NET 6.0 will be an LTS release and will be supported for three years, just like .NET Core 3.1.
[+] [-] eatonphil|5 years ago|reply
[+] [-] bob1029|5 years ago|reply
We are very excited to get our hands dirty with .NET 5 sometime in Q1 next year. We currently run on .NET Core 3.1. I expect our migration from 3.1=>5.0 will be a total non-event, but we don't want to risk any regressions during our current crunch phase. Our migration from 4.7=>2.0 was the most difficult, but once we got everything off Framework and onto Core things have been going really smoothly with the incremental upgrades. Really hoping this trend continues indefinitely.
The only part of .NET 5.0 that has left me disappointed is the continued lack of polymorphic deserialization support in System.Text.Json - a la Newtonsoft.Json's TypeNameHandling enumeration. This is the only thing holding us back from migrating to this first-party dependency. I have already left feedback regarding our use case in the appropriate dotnet/runtime GH issue.
The biggest new features I am looking forward to are the performance enhancements surrounding startup time, GC, etc. Improved P95 latency is something that will be very welcome in some of our busier environments.
In terms of the overall package that .NET brings to the table, we couldn't be happier. Sure, VS could run a little smoother and some of the configuration/DI stuff can be very aggravating (at first), but overall its a fantastic experience.
[+] [-] hbcondo714|5 years ago|reply
Huge endeavor and launch! Looks like mobile app development will be the same with Xamarin
[+] [-] maxpert|5 years ago|reply
[+] [-] xpressvideoz|5 years ago|reply
https://visualstudiomagazine.com/articles/2020/08/31/aot-sur...
[+] [-] Siira|5 years ago|reply
[+] [-] Belphemur|5 years ago|reply
[+] [-] mmd45|5 years ago|reply
[+] [-] rattray|5 years ago|reply
[+] [-] szntb|5 years ago|reply
On the other hand, I'm still missing an easier interop with other ecosystems. C# is an easy to use language and I would love to write some common code / business logic / whatever you name it in C# and expose it as webassembly and C/C++, this would cover mobile, web and desktop workloads. You can do something like that with Rust (or at least they claim it, I never tried), but with C# I don't see any _easy way_ doing it. I would be happy if someone could correct me If I'm wrong.
[+] [-] thrower123|5 years ago|reply
This version will be nearly out of support by then...
[+] [-] the_arun|5 years ago|reply
[+] [-] nwah1|5 years ago|reply
[+] [-] MarkSweep|5 years ago|reply
1: https://github.com/dotnet/runtime/tree/master/src/libraries/...
2: https://github.com/dotnet/runtime/tree/master/src/coreclr/sr...
[+] [-] GordonS|5 years ago|reply
[+] [-] oaiey|5 years ago|reply
It actually does the opposite: it is able to expose memory-alike resources (from e.g. the network interfaces) deep into its consuming programs by using abstractions like Span<T>. And while that sounds like a wrapper, it is actually (depending on the "alike") just a typed and safe pointer.
[+] [-] spoonspoon2|5 years ago|reply