Closed anitsh closed 1 year ago
An easy way to authorize resource was adding [Authorize]
to the class or function.
After adding it to MoviesController
without implementing required authentication and authorization, error is thrown:
An unhandled exception occurred while processing the request.
InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).
ASP.NET Core MVC provided an easy way to add login, authentication and authorization features. Below are the steps to adding required packages and steps to scaffold necessary files.
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.AspNetCore.Identity.UI
dotnet aspnet-codegenerator identity --useDefaultUI : Setup identity with the default UI and the minimum number of files
dotnet aspnet-codegenerator identity -dc MvcMovie.Data.MvcMovieContext --files "Account.Register;Account.Login" : Setup identity with the default UI and the minimum number of files
dotnet aspnet-codegenerator identity: Generates all the files
dotnet ef migrations add CreateIdentitySchema : Create schema
dotnet ef database update
ASP.NET Core provides ASP.NET Core Identity as a Razor Class Library. Applications that include Identity can apply the scaffolder to selectively add the source code contained in the Identity Razor Class Library (RCL). You might want to generate source code so you can modify the code and change the behavior. For example, you could instruct the scaffolder to generate the code used in registration. Generated code takes precedence over the same code in the Identity RCL.
The Authorize attribute here is only requiring the user to be logged in to perform a certain action, but the attribute can take properties to have a more fine grained control of authorisation. For example, using the Roles attribute, we can specify which role is allowed to perform a certain action.
[Authorize(Roles = "Manager")]
Need to go through official tutorials on Authentication and Authorization for more deeper understanding.
Previous steps to understand .NET Core MVC
dotnet new mvc -o MvcMovie
: Creates a new ASP.NET Core MVC project in the MvcMovie folder.
dotnet run
: Run project
Models
: Classes that represent the data of the app. The model classes use validation logic to enforce business rules for that data. Typically, model objects retrieve and store model state in a database.
Views
: Views are the components that display the app's user interface (UI). Generally, this UI displays the model data.
Controllers
: Classes that: Handle browser requests, Retrieve model data, Call view templates that return a response.
Movie model retrieves movie data from a database, provides it to the view or updates it. Updated data is written to a database.
Model classes are used with Entity Framework Core (EF Core) to work with a database. EF Core is an object-relational mapping (ORM) framework that simplifies the data access code that we have to write.
The model classes created are known as POCO classes, from Plain Old CLR Objects. POCO classes don't have any dependency on EF Core. They only define the properties of the data to be stored in the database.
Model classes are created first and EF Core creates the database.
Add tools and dependent packages.
dotnet tool uninstall --global dotnet-aspnet-codegenerator
dotnet tool install --global dotnet-aspnet-codegenerator
dotnet tool uninstall --global dotnet-ef
dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SQLite
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
Use the scaffolding tool to produce Create, Read, Update, and Delete (CRUD) pages for the movie model.
export PATH=$HOME/.dotnet/tools:$PATH`
dotnet aspnet-codegenerator controller -name MoviesController -m Movie -dc MvcMovie.Data.MvcMovieContext --relativeFolderPath Controllers --useDefaultLayout --referenceScriptLibraries -sqlite
-m The name of the model. -dc The data context. --relativeFolderPath The relative output folder path to create the files. --useDefaultLayout|-udl The default layout should be used for the views. --referenceScriptLibraries Adds _ValidationScriptsPartial to Edit and Create pages. -sqlite Flag to specify if DbContext should use SQLite instead of SQL Server.
Scaffolding updates the following:
Scaffolding creates the following:
dotnet ef migrations add InitialCreate
dotnet ef database update
ef migrations add InitialCreate
: Generates a Migrations/{timestamp}_InitialCreate.cs migration file.
The InitialCreate argument is the migration name. Any name can be used, but by convention, a name is selected that describes the migration. This is the first migration, so the generated class contains code to create the database schema. The database schema is based on the model specified in the MvcMovieContext class, in the Data/MvcMovieContext.cs file.
ef database update
: Updates the database to the latest migration, which the previous command created. This command runs the Up method in the Migrations/{time-stamp}_InitialCreate.cs file, which creates the database.
When EF Code First is used to automatically create a database, Code First:
When a change is made in the model, run both commands to track the changes.
A controller can pass data or objects to a view using the ViewData dictionary. The ViewData dictionary is a dynamic object that provides a convenient late-bound way to pass information to a view.
MVC provides the ability to pass strongly typed model objects to a view. This strongly typed approach enables compile time code checking.
The @model statement at the top of the view file specifies the type of object that the view expects. When the movie controller was created, the following @model statement was included.
This @model directive allows access to the movie that the controller passed to the view. The Model object is strongly typed.
The validation support provided by MVC and Entity Framework Core Code First is a good example of the DRY principle in action. We can declaratively specify validation rules in one place (in the model class) and the rules are enforced everywhere in the app.
The DataAnnotations namespace provides a set of built-in validation attributes that are applied declaratively to a class or property. DataAnnotations also contains formatting attributes like DataType that help with formatting and don't provide any validation.
The common language runtime (CLR) requires overloaded methods to have a unique parameter signature (same method name but different list of parameters).
ASP.NET maps segments of a URL to action methods by name, and if we rename a method, routing normally wouldn't be able to find that method.
A common work around for methods that have identical names and signatures is to artificially change the signature of the POST method to include an extra (unused) parameter.
The MVC scaffolding engine that created the action method adds a comment showing an HTTP request that invokes the method.
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
As the application that needs migration uses MySQL, we want to implement MySQL.
dotnet tool update --global dotnet-ef
: upgrade Entity Framework Core.
dotnet add package Pomelo.EntityFrameworkCore.MySql --version=7.0.0-alpha.1
: As our .NET Core version is 7.0.0, the latest release was used although that is in alpha.
dotnet ef migrations add UseMySQL
: Generate migrations to use with MySQL and it's database context.
dotnet ef database update
: Update database changes with the newly generated migrations.
When ever any change is made, new migration needs to be generated and applied to database.
Here we are using Pomelo as the Entity Framework Core provider for MySQL. It is choosen primarily because:
https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql https://www.nuget.org/packages/Pomelo.EntityFrameworkCore.MySql
Create Model scaffold from database:
dotnet ef dbcontext scaffold "Server=localhost;User=root;Password=1234;Database=ef" "Pomelo.EntityFrameworkCore.MySql"
Or, generate models from database tables.
Other official option : https://www.nuget.org/packages/MySql.EntityFrameworkCore
Prior, the database connection string was set on appsettings.json file and or was hardcoded on Program.cs.
The connection string is fetched via environment variable.
Store the envionment variable permanently in localfiles like ~/.bashrc
or simply export temporarily via export
.
export CONNECTION_STRING='Server=localhost;User=root;Password=1234;Database=ef;Port=3306
Port is optional if the MySQL Sever is publicy accessile at port 3306.
By default, application runs in Development environmet.
dotnet run --environment Production --urls http://localhost:8080
: Set environment and port.
Deployment needs to be researched further. https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx
https://learn.microsoft.com/en-us/ef/core/cli/dotnet#dotnet-ef-dbcontext-scaffold
dotnet ef dbcontext scaffold "Server=XXX;Database=XXX;User=XXX;Password=XXX;Port=XXX" "Pomelo.EntityFrameworkCore.MySql" -o Models -t User
: Generate User model
dotnet aspnet-codegenerator controller -name UsersController -m User -dc MvcMovie.Data.MvcMovieContext --relativeFolderPath Controllers --useDefaultLayout
: Generate Users Controller and View
When to use a solution file to manage several projects as a single unit.
We want to create separate projects based on their concerns and create modular units as projects.
dotnet new sln --name aspdonetcore-example
dotnet new classlib -o BusinessLogic/BusinessLogic -n BusinessLogic
dotnet new nunit --output Test/Unit --name Unit
dotnet new nunit --output Test/Integration --name Integration
dotnet sln add BusinessLogic/BusinessLogic
dotnet sln add Test/Unit
dotnet sln add Test/Integration
dotnet restore
dotnet build aspdonetcore-example.sln
dotnet run -p MvcMovie
dotnet new nunit --output Test/Unit --name Unit
: Adds Nunit testing framework.
dotnet add Test/Unit reference BusinessLogic/BusinessLogic.csproj
: Add BusinessLogic project reference to be unit tested.
dotnet test Test/Unit
: Run Unit test.
dotnet test Test/Unit --no-build
: Run tests on a previous build.
vscode-solution-explorer
https://github.com/fernandoescolar/vscode-solution-explorer
code --list-extensions
code --install-extension ms-vscode.cpptools
code --uninstall-extension ms-vscode.csharp
We don't have to run dotnet restore because it's run implicitly by all commands that require a restore to occur, such as dotnet new
, dotnet build
, dotnet run
, dotnet test
, dotnet publish
, and dotnet pack
.
To disable implicit restore, use the --no-restore
option.
The dotnet restore command is still useful in certain scenarios where explicitly restoring makes sense, such as continuous integration builds or in build systems that need to explicitly control when the restore occurs.
The dotnet restore command uses NuGet to restore dependencies as well as project-specific tools that are specified in the project file. In most cases, you don't need to explicitly use the dotnet restore command, since a NuGet restore is run implicitly if necessary.
As a user I should be able to login to the system.
Movies and Users should only be accessible to a user who is logged in.