Skip to content

Instantly share code, notes, and snippets.

@carloswm85
Created January 17, 2025 12:02
Show Gist options
  • Save carloswm85/d73d9941c287ae45af368bbfda0d67f3 to your computer and use it in GitHub Desktop.
Save carloswm85/d73d9941c287ae45af368bbfda0d67f3 to your computer and use it in GitHub Desktop.
Comprehensive guide for beginners learning ASP.NET Core MVC, covering essential topics like application setup, web server hosting, routing, dependency injection, and page views. It delves into advanced features, including Entity Framework Core, authentication with ASP.NET Core Identity, role and claims-based authorization, error handling, and cl…

Kudvenkat (the teacher)


ASP.NET Core MVC For Beginners

Introduction

WEB SERVER HOSTING

Web Server

  • InProcess Hosting 📺 - Part 06 📑
    • WebApplication.CreateBuilder(args); - One web server: Kestrel or IIS Express
      • IIS worker process (w3wp.exe or iisexpress.exe)
      • No proxy request penalties
  • OutOfProcess Hosting (default) 📺 - Part 07 📑
    • dotnet.exe process
    • Internal server: Kestrel
    • External web server (or reverse proxy server): IIS (Express), Nginx or Apache

WEB APP CONFIGURATION

  • launchsettings.json file 📺 - Part 08 📑
  • IConfiguration service:
    • appsettings.json 📺 - Part 09 📑
    • Reading order: appsettings.json, appsettings.{Environment}.json, User secrets, Environment variables, lastly, CLI arguments.
  • Middlewares introduction 📺 - Part 10 📑
    • Pipeline configuration 📺 - Part 11 📑
  • Static files and default files 📺 - Part 12 📑
  • Developer Exception Page 📺 - Part 13 📑
  • Development environments: Environment variables from OS 📺 - Part 14 📑
    • Development, Staging, Production
    • ASPNETCORE_ENVIRONMENT for selecting the run environment.
  • Using libman 📺 - Part 34 📑
    • Use LibMan with ASP.NET Core in Visual Studio 📑

MVC

  • MVC Design 📺 - Part 15 📑
    • MVC Model = Model class and class repository
  • NET Core MVC project set up (2.2 version) 📺 - Part 16 📑
  • MVC Implementation:
    • AddMvc Vs AddMvcCore 📺 - Part 17 📑
      • It works differently with older versions of NET Core.
    • Model 📺 - Part 18 📑
      • And simple use case for Dependency Injection
    • Part 19 - See Dependency Injection section.
    • Controller 📺 - Part 20 📑
      • Using Telerik Fiddler, receiving XML format
    • View 📺 - Part 21 📑
      • Contains logic to display the Model data
      • Customize view discovery 📺 - Part 22 📑
  • Passing data from controller to view:
    • Looslie typed views:
      • ViewData 📺 - Part 23 📑
        • Dictionary of weakly typed objects as ViewData["PageTitle"]
      • ViewBag 📺 - Part 24 📑
        • Use dynamic properties of type ViewBag.PageTitle
      • Features:
        • ViewBag is a wrapper to ViewData
        • Dynamically resolved at runtime. No type checking at compile time nor intellisense.
    • Strongly typed view 📺 - Part 25 📑
    • ViewModels 📺 - Part 26 📑
      • We create a ViewModel when a Model object does not contain all the data a view needs.

DEPENDENCY INJECTION

  • Dependency Injection 📺 - Part 19 📑
    • Benefits: Loose coupling, Easier unit testing
    • Lifetime service registration 📺 - Part 44 📑
      • Notes 📺 🖼️ - Consider: Service instance within current HTTP request.
      • builder.Services.AddSingleton() - Creates a single instance of the service when it is first requested, and reuses that same instance in all the places where that service is needed - 3 4 5 6 7... So on and so foth.
      • builder.Services.AddScoped() - A new instance of a Scoped service is created once per request within the scope. For example, in a web application it creates 1 instance per each http request but uses the same instance in the other calls within that same web request. - 3 4 4 4 4 4... So on and so foth.
      • builder.Services.AddTransient() - A new instance of a Transient service is created each time it is requested. - 3 3 3 3 3... So on and so foth.

PAGE VIEWS

  • ListView 📺 - Part 27 📑
  • Layout View 📺 - Part 28 📑
  • Render Sections in Layout Page 📺 - Part 29 📑
    • For the organization of page elements. They can be optional or mandatory.
  • _ViewStart.cshtml 📺 - Part 30 📑
  • _ViewImports.cshtml 📺 - Part 31 📑
    • Used to include common namespaces.
    • View directives: @addTagHelper @removeTagHelper @tagHelperPrefix @model @inherits @inject

ROUTING

  • Conventional Routing 📺 - Part 32 📑
  • Attribute Routing 📺 - Part 33 📑
    • Applied to the controllers or to the controller actions methods.
    • NOTE: The controller route template is not combined with action method route template, if the route template on the action method begins with / or ~/
    • Tokens in attribute routing: [Route("[controller]/[action]")]
  • Video 34 is above.

TAG HELPERS

  • Notes: Similar to HTML Helpers. Server side components for HTML rendering. Use: Link generation, form creation, asset load, etc.
  • Tag Helpers & HTML Helpers 📺 - Part 35 📑
  • Why use Tag Helpers 📺 - Part 36 📑
  • Image Tag Helper 📺 - Part 37 📑
    • Provide cache-busting behaviour for static image files.
  • Environment Tag Helper 📺 - Part 38 📑
  • Navigation Menu 📺 - Part 39 📑
  • Form Tag Helpers 📺 - Part 40 📑
    • Form Tag Helper, Input Tag Helper, Label Tag Helper, Select Tag Helper, TextArea Tag Helper, Validation Tag Helper

MODELS

  • Model Binding 📺 - Part 41 📑
    • "Model binding maps data in an HTTP request to controller action method parameters. The action parameters say be simple or complext types."
    • name input attribute value is used for mapping.
    • Data available in the HTTP request (with preeminence order): Form valuesRoute valuesQuery strings
  • Update a model:
    • Edit View - GET 📺 - Part 55 📑
      • Edit.cshtml with controller and viewmodel.
    • Edit View - POST 📺 - Part 56 📑
  • Model Binding Not Working with FOREACH loop 📺 - Part 92 📑

SERVER SIDE VALIDATION

  • Model Validation 📺 - Part 42 📑
  • Custom validation attributes 📺 - Part 76 📑
  • Select list validation 📺 - Part 43 📑

ENTITY FRAMEWORK CORE

  • Introduction 📺 - Part 45 📑
  • Notes:
    • ORM, Domain Classes, Code/Database First, Database Provider Models
    • Domain & DBContext ClassesEF CoreDB ProviderActual DB
  • Installation & Multilayer Web Application 📺 - Part 46 📑
    • Presentation LayerBusiness LayerData Access Layer
  • DbContext 📺 - Part 47 📑
  • Using with SQL Server 📺 - Part 48 📑
    • Connection string
  • Repository Pattern 📺 - Part 49 📑
    • Abstraction of the Data Access Layer, for CRUD operations. How to use AddScoped with SQL Server.
  • Migrations 📺 - Part 50 📑
    • Migrations keep the DB schema and app model classes in sync.
    • Commands: get-help about_entityframeworkcore Add-Migration Update-Database
  • Seed Data to Database 📺 - Part 51 📑
  • Keeping domain models and database schema in sync 📺 - Part 52 📑
    • Remove-Migration
    • This video also explains how to remove migration that has already been applied to the database.
  • File upoad 📺 - Part 53 📑
    • IFormFile, the video includes jQuery code for .custom-file-label.
    • Notes:
      • File is saved to the web server location wwwroot/images
      • The file uploaded to the server can be accessed through Model Binding using the IFormFile interface.
    • Upload multiple files at once 📺 - Part 54 📑

Error Handling

  • Handling 404 Not Found Errors:
    • Type 1: Resource with ID not found 📺 - Part 57 📑
    • Type 2: URL does not match any route.
      • Centralized 404 Error Handling (400-599):
        • UseStatusCodePages 📺 - Part 58 📑
        • User facing: UseStatusCodePagesWithRedirects and UseStatusCodePagesWithReExecute 📺 - Part 59 📑
  • Correct Global Exception handling:
    • Not production: UseExceptionHandler 📺 - Part 60 📑
  • Custom Error Page (for ON DELETE NO ACTION) 📺 - Part 90 📑

Logging

  • Basics, Logging from console, Built-in Logging Providers 📺 - Part 61 📑
  • Logging Exceptions 📺 - Part 62 📑
  • Logging to a file 📺 - Part 63 📑
  • LogLevel configuration 📺 - Part 64 📑

ASP.NET Core Identity - Authentication & Authorization

  • Google search 🔎
  • Official documentation 📑

IDENTITY SET UP

  • Inherit from IdentityDbContext, add services, add middleware, generate tables 📺 - Part 65 📑
  • Register new user 📺 - Part 66 📑
  • Services: UserManager and SignInManager 📺 - Part 67 📑
  • Password complexity 📺 - Part 68 📑
  • Show/hide view elements using @if (SignInManager.IsSignedIn(User)) { } 📺 - Part 69 📑
  • Implementing log in functionality 📺 - Part 70 📑
    • LoginViewModel, Login View, Login Actions in Account Controller.
  • Authorizacion implementation - Types: Simple authorization, Role based, Claims based, Policy based.
    • Implementation as a service, Simple Authorization 📺 - Part 71 📑
    • Redirection after login 📺 - Part 72 📑
      • NOTE: Security risk - Open redirect attack/vulnerability 📺 - Part 73 📑
  • Extend IdentityUser class 📺 - Part 77 📑

ROLES

  • Create Roles 📺 - Part 78 📑
  • Get list of roles 📺 - Part 79 📑
  • Edit existing role 📺 - Part 80 📑
  • Add or remove users 📺 - Part 81 📑
    • Tables for: Users, Roles, UserRoles
  • Role based authorization (RBAC) 📺 - Part 82 📑
    • Show or hide navigation menu based on user 📺 - Part 83 📑
      • See part-94 for more.
  • User role membership: Add/remove roles for user 📺

USERS

  • List users, register new user and redirect correctly 📺 - Part 84 📑
  • Edit user information, roles and claims 📺 - Part 85 📑
  • Delete user 📺 - Part 86 📑
    • Display delete confirmation 📺 - Part 87 📑
  • Delete role 📺 - Part 88 📑
  • Manager user roles 📺 - Part 91 📑

CLAIMS

  • Manage User Claims 📺 - Part 93 📑
    • "Claim": Name-value pair used for making access control decisions.
    • They are a piece of information about the user, NOT what the user can or cannot do.
    • Claims are "policy based".
  • Claims Based Authorization (CBAC) 📺 - Part 94 📑
    • What are they?Services.AddAuthorizationAddPolicyRequireClaim • Use in controllers and actions • Combination of roles and policies.
  • Role Based Authorization (RBAC) Vs Claim Base Authorization (CBAC) 📺 - Part 95 📑
    • [Authorize(Roles = "Admin")] is role based.
    • [Authorize(Policy = "DeleteRolePolicy")] is claim based.
  • Authorization in views 📺 - Part 96 📑
    • Claim based authorization checks in views.
    • See part-83 for related information.

AUTHORIZATION POLICY

  • Using "claim type" and "claim value" in policy based authorization 📺 - Part 98 📑
  • Create custom authorization policy (Policy with multiple requirements) 📺 - Part 99 📑
    • See "Part 100 Func delegate in C#" for related information.
  • Custom authorization requirements and handlers - EXPLANATION 📺 - Part 100 📑
    1. BUILT-IN Authorization Requirement
      1. Policies with one requirement. → RequireClaim
      2. Policies with multiple requirements:
        1. Simple relationships → RequireClaim + RequireRole
        2. Complex relationships → RequireAssertion
    2. CUSTOM Authorization Requirement
      1. Implement IAuthorizationRequirementIAuthorizationHandler<T> where T is the requirement
  • Custom authorization requirements and handlers - EXAMPLE 📺 - Part 101 📑
  • Multiple authorization handlers for a requirement 📺 - Part 102 📑
  • Custom authorization handler: SUCCESS Vs FAILURE, and NOTHING (Task.CompletedTask) 📺 - Part 103 📑

EXTERNAL IDENTITY PROVIDERS - Google, Facebook, etc

Google

Facebook

Email Management

  • Why email confirmation is important for app security 📺 - Part 111 📑
  • Block log in if email is not confirmed 📺 - Part 112 📑
  • Email confirmation for internal accounts 📺 - Part 113 📑
    • Using token providers.
  • External login email confirmation 📺 - Part 114 📑
    • External registration is allowed, but external login is blocked until email confirmation is performed.

PASSWORD/TOKENS/ENCRYPTION/DECRYPTION MANAGEMENT

  • Password:
  • Tokens:
    • How Tokens are generated and validated 📺 - Part 117 📑
      • Generated token contains:
        • (Token Creation Time + User ID + Token Purpose + Security Stamp) ← Encrypted and then Base64 Encoded
    • Password reset token lifetime (built-in method) 📺 - Part 118 📑
    • Password reset token lifetime (CUSTOM method) 📺 - Part 119 📑
  • Encryption and Decryption:
    • Encryption and Decryption Examples 📺 - Part 120 📑
  • Change Password 📺 - Part 121 📑
    • With block user access to action controller example.
  • Add password to local account linked to external login (Facebook, Google) 📺 - Part 122 📑
  • Account lockout 📺 - Part 123 📑
  • ASP.NET Core MVC Course Wrap Up 📺 - Part 124 📑

CLIENT SIDE VALIDATION

  • Client side validation implementation 📺 - Part 74 📑
    • Requirements (in this order): jquery.js, jquery.validate.js, jquery.validate.unobtrusive.js
  • Remote validation 📺 - Part 75 📑

MSSQL SERVER

  • Enforce ON DELETE NO ACTION 📺 - Part 89 📑

Other

  • Change default access denied route 📺 - Part 97 📑
    • Cascading referential integrity constraint
  • Secret Manager in ASP.NET Core 📺 - Part 110 📑
    • Use: "Keep production secrets like database connection string, API and encryption keys out of source control."

C# Programming Language

Videos and tutorials mentioned in this course.

Text version of the following tutorials, may be found in the video description.

C# Tutorial For Beginners

Full tutorial 📺

  • Some topics related to the main tutorial of this file:
    • Delegates 📺 - Part 36
    • Lambda Expressions 📺 - Part 99
    • Task, async, await 📺 - Part 101
      • Thread, Action 📺 - Part 102
    • Func Delegates 📺 - Part 100

LINQ Tutorials

LINQ Tutorial 📺 LINQ to SQL 📺 LINQ to XML 📺

  • Extension methods 📺

SQL Tutorials


Other Topics


NOTES

Libraries

Delete Rule At SQL Server & EF Core

SQL Server EF Core Behavior
Delete rule enum DeleteBehavior The enumeration representing the delete behavior in EF Core.
NoAction .ClientSetNull(0) If a parent entity is deleted, the dependent entity's foreign key is set to null in the client memory but throws if the database disallows it.
- .Restrict(1) Prevents deletion of the parent entity if related entities exist.
SetNull .SetNull(2) When a parent entity is deleted, foreign keys in dependent entities are set to null.
Cascade .Cascade(3) DEFAULT. When a parent entity is deleted, related child entities are also deleted.
- .ClientCascade(4) The dependent entities are deleted in client-side memory but require a save to propagate to the database.
NoAction .NoAction(5) EF Core does not perform any action, and the database enforces referential integrity constraints.
SetDefault .ClientNoAction(6) No action is performed on the dependent entities in the client; the database handles SET DEFAULT.

Proxy Variables Example

  • For Windows enviroment variables:
HTTP_PROXY = http://10.1.33.254:80
HTTPS_PROXY = https://10.1.33.254:80
NO_PROXY = localhost,127.0.0.1,::1,LOCALHOST

Configuration Sources

Configuration Source Course Part Override Order
appsettings.json 9 1st
appsettings.{env.EnvironmentName}.json - 2nd
User secrets 110 3rd
Environment variables 14 4th
Command-line arguments - 5th
  • env.EnvironmentName: Development

System Variables

  • Environment variables are configured at operating system level.
  • Example:
    • Variable name: ConnectionString:EmployeeDBConnection
    • Variable value: Server=localhost;Database=EmployeeDB;Trusted_Connection=True;MultipleActiveResultSets=true;TrustServerCertificate=True;Encrypt=False

Framework Update/Upgrade

// Configuration for netcore 8.0
using EmployeeManagement.Models;
using EmployeeManagement.Security;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore;
using NLog;
using NLog.Web;
// Early init of NLog to allow startup and exception logging, before host is built
var logger = NLog.LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
logger.Debug("init main");
try
{
#region BUILDER
// What is `builder`?
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddDbContextPool<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("EmployeeDBConnection")
?? throw new InvalidOperationException("Connection string 'EmployeeDBConnection' not found.")));
/**
* IDENTITY
* https://youtu.be/kC9qrUcy2Js?list=PL6n9fhu94yhVkdrusLaQsfERmL_Jh4XmU&t=199
*/
builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Password.RequiredLength = 10;
options.Password.RequiredUniqueChars = 3;
options.SignIn.RequireConfirmedEmail = true;
options.Tokens.EmailConfirmationTokenProvider = "CustomEmailConfirmation";
// https://youtu.be/jHRWR36UC2s?list=PL6n9fhu94yhVkdrusLaQsfERmL_Jh4XmU
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.DefaultLockoutTimeSpan= TimeSpan.FromMinutes(15);
})
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders()
// CUSTOM TOKEN PROVIDER OPTIONS
.AddTokenProvider<CustomEmailConfirmationTokenProvider
<ApplicationUser>>("CustomEmailConfirmation")
;
// BUILT-IN TOKEN PROVIDER OPTIONS
builder.Services.Configure<DataProtectionTokenProviderOptions>(options => {
// Set the lifespan of ALL tokens to 5 hours
options.TokenLifespan = TimeSpan.FromHours(5);
});
// CUSTOM TOKEN PROVIDER OPTIONS
builder.Services.Configure<CustomEmailConfirmationTokenProviderOptions>(options => {
// Set the lifespan of EMAIL tokens to...
options.TokenLifespan = TimeSpan.FromDays(3);
});
// Add services to the container. This is where you configure services to be used by the app.
builder.Services
.AddControllersWithViews(options =>
{
// GLOBAL AUTHORIZATION is implemented for all user
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
}) // In this case, MVC services with views are added.
.AddXmlDataContractSerializerFormatters() //
;
builder.Services.ConfigureApplicationCookie(options => {
options.AccessDeniedPath = new PathString("/Administration/AccessDenied");
});
//---------------------------------------- CLAIMS POLICY BASED AUTHORIZATION
builder.Services.AddAuthorizationBuilder();
builder.Services.AddAuthorization(options =>
{
// FOR CLAIMS
// User for protecting controllers or routes
// NOTE: The DeleteRolePolicy requires this 2 claims
options.AddPolicy("DeleteRolePolicy",
policy => policy.RequireClaim("Delete Role"));
// Explanation: 3 conditions are met
/*
options.AddPolicy("EditRolePolicy",
policy => policy.RequireClaim("Edit Role", "true")
.RequireRole("Admin")
.RequireRole("Super Admin"));
*/
// Explanation: One condition or the other
options.AddPolicy("EditRolePolicy", // CUSTOM POLICY using Func type
// Custom handler registry
policy => policy.AddRequirements(new ManageAdminRolesAndClaimsRequirement()));
options.AddPolicy("AllowedCountryPolicy",
// "allowed values" is an array of string
policy => policy.RequireClaim("Country", "USA", "India", "UK"));
// FOR ROLES
// Require multiple roles
options.AddPolicy("AdminRolePolicy",
policy => policy.RequireRole("Admin", "OtherRole"));
options.AddPolicy("SuperAdminPolicy", policy =>
policy.RequireRole("Admin", "User", "Manager"));
});
// >> Remember to generate your own Ids and secrets <<
builder.Services.AddAuthentication()
// Microsoft.AspNetCore.Authentication.Google
.AddGoogle(options => {
options.ClientId = "847703839060-mjpji359cp8og2dig5130lnmp9i75vud.apps.googleusercontent.com";
//options.ClientId = Environment.GetEnvironmentVariable("google:clientid");
options.ClientSecret = "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";
//options.ClientSecret = Environment.GetEnvironmentVariable("google:clientsecret");
//options.UserInformationEndpoint = "https://www.googleapis.com/oauth2/v2/userinfo";
//options.CallbackPath = "";
}).AddFacebook(options =>
{
options.AppId = "640033055116902";
options.AppSecret = "6ed6111c4cc29d9b92386153c8c1ec8e";
});
//builder.Services.AddSingleton<IEmployeeRepository, MockEmployeeRepository>();
builder.Services.AddScoped<IEmployeeRepository, SQLEmployeeRepository>();
// Custom handler registries
builder.Services.AddSingleton<IAuthorizationHandler, CanEditOnlyOtherAdminRolesAndClaimsHandler>();
builder.Services.AddSingleton<IAuthorizationHandler, SuperAdminHandler>();
builder.Services.AddSingleton<DataProtectionPurposeStrings>();
//--------------------------------------------------------------------- NLog
builder.Logging.ClearProviders();
builder.Host.UseNLog();
#endregion
// What is `app`?
var app = builder.Build();
#region justSomeText
// Sample text and application-specific information are concatenated here.
var text = "Hello World!";
var processName = System.Diagnostics.Process.GetCurrentProcess().ProcessName; // Gets the name of the current process.
var mySettings = new MySettings();
builder.Configuration.GetRequiredSection(nameof(MySettings)).Bind(mySettings); // Binds the configuration section to the MySettings object.
var environment = app.Environment.EnvironmentName; // Gets the current environment name (e.g., Development, Production).
var name = mySettings.Name; // Example: "Bob"
var counter = mySettings.Counter; // Example: 100
// Combine text and variables into a single string.
var justSomeText = $"JUST SOME TEXT: {text} {processName} {name} {counter} {environment}";
#endregion
if (app.Environment.IsDevelopment())
{
// Enable the Developer Exception Page in the development environment.
app.UseDeveloperExceptionPage();
}
else
{
// Use a custom error handling page for production.
// app.UseExceptionHandler("/Home/Error");
app.UseExceptionHandler("/Error");
// REMEMBER THIS WORKS ONLY WITH:
// "ASPNETCORE_ENVIRONMENT": "Production"
// Returns error as plain text
// app.UseStatusCodePages(); // (1)
// Intersect error and return a view
// {0} is a placeholder for the status code
// app.UseStatusCodePagesWithRedirects("/Error/{0}"); // (2) Redirect to the string controller
app.UseStatusCodePagesWithReExecute("/Error/{0}"); // (3) Re-executes the pipeline
// Enable HTTP Strict Transport Security (HSTS) for enhanced security in production.
// The default duration is 30 days; you can adjust this value based on your requirements.
app.UseHsts();
}
// Redirect HTTP requests to HTTPS to enforce secure communication.
app.UseHttpsRedirection();
// The FileServer middleware combines DefaultFiles, StaticFiles, and optionally DirectoryBrowser functionalities.
// It serves files from the wwwroot folder (or another specified folder) with default settings for static file handling.
app.UseFileServer();
//app.UseDefaultFiles(); // 1: Enables serving a default file (e.g., index.html) when a directory is accessed.
// This middleware doesn't serve the file; it only rewrites the URL to include the default file.
app.UseStaticFiles(); // 2: Serves static files (e.g., CSS, JS, images) from the wwwroot folder (or another specified folder).
// This middleware is required to actually serve the files to the client.
//app.UseDirectoryBrowser(); // 3: Enables directory browsing, allowing users to view the directory's file listing in the browser.
// This feature is disabled by default and must be explicitly enabled for security reasons.
app.UseAuthentication();
// Note: When using app.UseFileServer(), it includes the functionality of the above three middlewares:
// 1. DefaultFiles is enabled by default.
// 2. StaticFiles is always enabled.
// 3. DirectoryBrowser is optional and must be explicitly configured via FileServerOptions if needed.
// Uncomment the following line to simulate an exception for testing purposes.
// app.MapGet("/", () => { throw new Exception("hola"); });
// Add middleware for routing to endpoints (e.g., controllers, actions).
app.UseRouting();
// Add middleware for authorization. This is used to enforce security policies on requests.
app.UseAuthorization();
//
// app.UseMvcWithDefaultRoute();
//
// app.UseMvc();
// Define the default route for controllers.
// It maps URLs to controllers and actions with an optional "id" parameter.
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"
);
// Example of an outdated `UseMvc` block (NOT RECOMMENDED in .NET Core 8):
/*
app.UseMvc(routes => {
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"
);
});
*/
// Define a route for the root path, which returns the justSomeText variable.
//app.MapGet("/", () => justSomeText);
// Start the application and listen for incoming requests.
app.Run();
}
catch (Exception exception)
{
// NLog: catch setup errors
logger.Error(exception, "Stopped program because of exception");
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
NLog.LogManager.Shutdown();
}
bool AuthorizeAccess(AuthorizationHandlerContext context)
{
return context.User.IsInRole("Admin") &&
context.User.HasClaim(claim => claim.Type == "Edit Role" && claim.Value == "true") ||
context.User.IsInRole("Super Admin");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment