This is Best Way To Create CLI Apps in .NET
Вставка
- Опубліковано 27 гру 2023
- Use code CLEAN20 and get 20% off the brand new "Deep Dive in Clean Architecture" course on Dometrain: dometrain.com/course/deep-div...
Get the source code: mailchi.mp/dometrain/4khfrbjhchc
Become a Patreon and get special perks: / nickchapsas
Hello everybody, I'm Nick, and in this video, I will introduce you to what I think is the easiest way to create elegant CLI (Command Line Interface) tools in .NET using C#. There are many ways to achieve this in .NET but by far my favourite is using a Nuget package called Cocona.
Give Cocona a star on GitHub: github.com/mayuki/Cocona
Workshops: bit.ly/nickworkshops
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: github.com/Elfocrash
Follow me on Twitter: / nickchapsas
Connect on LinkedIn: / nick-chapsas
Keep coding merch: keepcoding.shop
#csharp #dotnet
Nice lib. But what I loved is that you mentioned that you wouldn't/shouldn't put commands into program.cs. I recently talked to a guy that said he doesn't like minimal apis, cause the program.cs is a mess. Cause all he saw were those presentations where it was "one file API" and didn't think about splitting it. Here's similar approach so mentioning the splitting may ease adoption for some people.
I'm one of those guys - I was always aware that we could split onto multiple files, but seeing all the examples and talks about minimal APIs in a single-file scope clearly makes it seem like these talks are being targeted at other framework/language devs (e.g. Node.js devs) and not .NET devs (which is, of course, fine).
All in all, they have their place and their use, but I am still not captivated by the beauty of a single-file use, even if it's for a very simple API structure. I'm keeping an open mind and giving me time to get used to it, though (because I used Carter in the past and loved it, I'm expecting the same for these sort of minimal API approaches).
Well, minimal APIs can actually reside in a separate file other than Program.cs
Also there are Visual Studio scaffolders which can do this for you.
The beauty is that you can have a really simple solution to eg. attract non .net developers: easy to learn. But both in Node and c# you can of course split things them in any way you want if you are scaling out to more features.
massive. so pleased to know about this. I built a testing tool and the navigation here will totally streamline the workflow and extensibility.
I've attempted to make rudimentary CLI programs approximating this structure a whole bunch of times over the years, never quite got it right. Glad to see there's a library that already has me covered.
I'm currently working on a CLI myself and setting up DI is challenging but doable. Gonna give Cocona a try.
Perfect timing. Was just going to create a CLI tool.
Nick seems to be always make relevant videos, appreciate it a lot!
I was just thinking about making such framework by myself. Glad it already exists, saves me a lot of time.
Wow! As usual thanks for sharing! That looks pretty powerful!
Happy New Year, Nick! And congratulations on the great content that you produce. Wish you a great 2024.
This is so cool! Thanks Nick for a that little gem!
Amazing!!! I definitely will use this lib in my future applications
This project is really nice, I’ve been following for a while now. I think a good point to make is that people should be careful when injecting services since the console process runs as a singleton. Thanks for sharing
This is a great package. This week I added a app builder to a CLI project I have to assist with some integration tests, If I had seen this before hand, I would have used this package.
I feel like spectreconsole library is a bit more advanced in feature set.tried cocona in a PoC and liked it but spectreconsole felt more mature
I really like this library and am using it when I need to create some CLI console tools
That's a nice lib! I built a simmilar one around a year ago, with a difference that there were a class-based commands with tagging Attributes for arguments injecting into a properties, and to define names, descriptions, etc, but I feel like MinimalAPI approach could be better for some tasks
Cool video. Thanks Nick!
Thanks,
I usually use it for small tools for me or some team-mates. Thats why I never thought of even doing unit-tests for them :-)
Feels like if you could take the minimal api architecture and rip out the exposed port you’d have a solid structure for this. Especially the slim web builder sans the serving of course
really nice. thanks Nick
Thanks. I'll take look at this. I've been using the CommandLine package which does a good job of defining verb + verb specific options style CLI (like git). Although not show in the video I'm gonna guess a public method can be decorated so that the "command" as a verb not an option. I'm a little surprised that isn't the default behaviour but may be there is config that will make it the default.
We recently switched to the System.CommandLine Package from McMastersCommandLineUtils. I am totally satisfied with that package so far and might soon use it for a new project.
Thanks, I will use it to build a tool to create fake data to help with local development of microservice. You are awesome nick. Keep going.
I use the Command Dot Net. Very good CLI framework.
I write command line apps all the time, mostly for testing code parts in clean environment before using it in main project
I’ve liked working with Sprache more personally, but fun watch regardless!
Going to have to give this library a go - looks like it will make everything a lot cleaner. Just need to work out how to get it to return an exit code so it will better integrate with scripts
Loved this Cocona stuff!! WAY more useful than those old args[] trash!
Ah, this video could save me a couple of hours if was few days before. But anyway, this is very nice solution, will use it next time. Thanks!
Very nice, now may be say bye bye mono options :)
Waiting for new web application builder benchmark ⌛, Good Luck 🌹
I've tried multiple CLI packages, and I prefer the Console.Spectre package. It was a better experience and more powerful for "pretty" console output. Perhaps you could try that one as well...
my man’s timing is insane
I'd have loved to hear a comparison with CliFx or Typin
Hey Nick, as usual thanks for the tip. Do you know how to pass a cancellation token into the class based commands?
It looks like you can pass the CoconaAppContext into the command method directly. I wonder why the application looks to be stuck if you inject it into the constructor
How do you show the project and version in DOS?
I probably missed the part, but is it possible to have it accept commands WHILE the application is running?
I prefer spectre personally. They also provide alot of console interaction helpers like printing progress bars, tables, treeview + prompting for input values including selection of values etc
nice lib and video
What does this library offer in addition to system.commandline?
Was wondering about that too. System.CommandLine is still in preview, but it is directly from Microsoft and looks very promising.
I've tried using the library and I ran into a problem when inputting json strings. For example when i input {"name":"Something"} I get { name : Something }. Does anybody have an idea why is that happening
I remember you've already done a video about Cocona 🤔
I have a business use case that this library could work for.
I love how you (intentionally?) say "option-null" for nullable parameters.
why there is space after the first two dashes, i.e dotnet run -- weather
is it a quirk of the package or what, can someone kindly explain?
It's to stop the dotnet command from potentially taking the args; it forces dotnet to pass the args to the Program.cs. If you don't do that and some of your args names clash with the dotnet cli, it could be a problem.
All arguments before "--" are for "dotnet run" while the others are passed to the application being run
@@ghidello thanks for explaining
@@ghidello same thing with npm run
@@SirusStarTVYep, it's pretty common in unix commands. You made me remember when I used to create a file named "-i" challenging people to delete it.
Nice
I like commandlineparser/commandline
which tool are you using for that colorful console?
That's "Oh My Posh"
Pretty cool, but the last update was on March 27, 2023 so it doesn't seem to be maintained as much; and it is targeting .NET 6 only (I know there is backward compatibility in .NET, but still). :(
"Cocona" is an excellent Pokemon Rangers reference
Bash and zsh completion support but no pwsh? Sad day for Powershell.
Is this AOT compatible?
Nope everything gets trimmed to oblivion. CLI without AOT makes me want to move to Rust or GO.
can't we make our own command type instead of dotnet run? let's say I want to name it as Weatherize and the command's name will be Weatherize --city London?
Ofc you can. It’s only dotnet run because I’m running it while I’m working on it. Once you package it and you give it a name you can call it by its name
@@nickchapsas thanks
👍👍👍
There is a terrible bug in the code in about 2 min into the video. The traditional greetings is written "Hello, world!". No exceptions! 😀
Nesting subcommands using the class base approach is very clunky ATM.
The source code link in the description leads to a 404
Fixed
I'm coining a new term called "DI container obsession". While dependency injection itself is great, the use-case for DI containers is actually super narrow. The obsession with using them all over the place in .NET is really annoying.
don't use this library. it only looks good on short youtube videos like this with hello world vibe. i actually tried to used it - you will not know what's wrong. the application will just stop/freeze and you will not know what happened. for example, if you won't configure a dependency injection for one of the classes, you will never know it explicitly. this library has a big issue with hiding runtime exceptions and giving you 0 feedback on what's wrong. don't use it for anything serious or you will waste hours of your time.