Well the above picture shows that there is a long way to have a good artisan command in dotnet CLI; like the one we already have in Laravel but it is totally doable 😏.
I don’t know if you have the same feeling; I developed for years in C# then with hesitation moved to Php with Laravel and after a month felt in love with it and coded for almost four years in it then switched back to C# (Don’t ask why ). Now you know the feeling. I missed the good, useful artisan commands where you do not want a UI but still need to upload some data or process something or even test your installation when you deploy for production.
BTW we are talking about web development 😅.
So I searched for an alternative, something similar but did not get satisfied until I developed my own in our company and I am happy to share this library with you.
You can check out the library from the code below.
With this package you will be able to add artisan commands to your dotnet core project and run your own custom commands…
The code looks simple but it is useful and based on it you can also develop your own. I was also thinking about developing a dotnet CLI tool where we can do like “dotnet artisan” but lets not dream.
Let’s get to it
Please first go on and add the nuget package that I shared with you, to your project.
After doing so, the first thing you need to do is to change your Program.cs file to make sure that the host will search for running your commands. So you should have something like this in your Program.cs.
Note: RunWithCommands(args) is an extension method which comes with the package we are discussing in this post.
Then you need to register, lets call it “Terminal” to the DI.
Here I always rather to have a specific folder for my Terminal Commands so you also can do the same or take any other approach that you are already used to.
I will add “Terminal” folder to my project like below
The reason I have these folders is also to isolate the DependencyInjection registrations by adding a Kernel.cs file in there which looks like this:
So the above code will let you register your commands into your artisan terminal as a “Transient” which means you need to take care of some stuff yourself when you are doing some of other stuff in your command, which I will explain later (I have the same feeling 🤯 don’t worry)
So now let’s create a good old HelloWorld command.
In the Terminal folder that you added earlier add a HelloWorldCommand.cs. This class MUST implement ITerminalCommand interface so the code that we changed in Program.cs can detect it and execute it if it is requested.
The name that you set here will be the name of your command when you are going to run it from the dotnet CLI and the execute function is self explanatory enough I think.
Now lets register it. Do you remember the Kernel.cs? change it to this 👇
Now you want to run your command but no. First we need to really register it into DI. So open your Startup.cs and you should have “AddDefaultArtisan()” under your services like below.
And now that you have registered it go on open your console in the root folder of your project and run the following command.
dotnet run hello-world
It should build your project and give you the “Hello World” in the output and if it is not so, please recheck your config based on what is described so far but if you are good lets continue.
Do you remember where everything got complicated with handling some stuff yourself? lets explain what you need to actually handle there.
Well assume that you want to seed some data from a json file into your database. You already know EntityFramework and you already know what a DbContext is. So we are going to see how we can get access to the DbContext in these ArtisanCommands.
Create a new command, name it TestSeederCommand.cs and implement the ITerminalCommand interface. In the commands you have access to the IServiceProvider so to get the DbContext and do your things you need to do the following.
So you get the dbContext from the ServiceProvider. Notice that you must create the scope because the DI will create a scoped version of DbContext.
Now you ask what is in the args? args contains the inputs you put in dotnet CLI when you are running your command. So lets say for this seeder you want to pass a path to your command to read a json file, then you want to write the command like below.
dotnet run test-seeder "PATH/TO/My/JSON_FILE.json"
The path part will be inside args. You can read it, and then read the file, do whatever you want while your website is actually running.
Ok I think I covered everything and made my point. There is one other thing that can come in handy and that is the ArtisanConsole class. This class contains the following methods.
- Success -> Green
- Warning -> Yellow
- Info -> Blue
- Error -> Red
You pass a message and it will be printed in the console with the color in front of each method and then the color which has been set before the method will be set again on the Console.ForgroundColor and that the END!
I wish you all happy coding and let me know about your ideas and suggestions or if anyone is up for developing a dotnet cli artisan tool 😉