├── .gitignore ├── Chapter01 ├── .editorconfig ├── IMyOtherService.cs ├── IMyService.cs ├── Middleware.cs ├── MyGenericService.cs ├── MyOtherService.cs ├── MyService.cs ├── MyType.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── StartupDevelopment.cs ├── StartupProduction.cs ├── StartupStaging.cs ├── appsettings.Development.json ├── appsettings.json ├── chapter01.csproj └── chapter01.sln ├── Chapter02 ├── .editorconfig ├── Controllers │ └── HomeController.cs ├── LogLevelSettings.cs ├── LoggingSettings.cs ├── MyFeatureFilter.cs ├── MySettings.cs ├── PostConfigureLoggingSettings.cs ├── PreConfigureLoggingSettings.cs ├── PreConfigureNamedLoggingSettings.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── RedirectDisabledFeatureHandler.cs ├── RegistryConfigurationExtensions.cs ├── RegistryConfigurationProvider.cs ├── RegistryConfigurationSource.cs ├── Startup.cs ├── Views │ ├── Home │ │ └── Index.cshtml │ └── _ViewImports.cshtml ├── appsettings.Development.json ├── appsettings.json ├── chapter02.csproj └── chapter02.sln ├── Chapter03 ├── Controllers │ ├── Calculation.cs │ ├── CalculatorController.cs │ ├── ErrorController.cs │ └── HomeController.cs ├── CustomDeveloperPageExceptionFilter.cs ├── EvenIntRouteConstraint.cs ├── ITranslator.cs ├── IsAuthenticatedRouteConstraint.cs ├── MyConstraint.cs ├── MyMetadata1.cs ├── MyMetadata2.cs ├── MyTranslator.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── ResponseMiddleware.cs ├── Startup.cs ├── TranslateRouteValueTransformer.cs ├── Views │ ├── Error │ │ ├── Error.cshtml │ │ └── Error404.cshtml │ └── Home │ │ ├── Error401.cshtml │ │ └── Index.cshtml ├── chapter03.csproj ├── chapter03.sln └── wwwroot │ └── index.html ├── Chapter04 ├── Controllers │ └── HomeController.cs ├── Models │ ├── ErrorViewModel.cs │ └── Model.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── ValidateModelStateAttribute.cs ├── Views │ ├── Home │ │ ├── Index.cshtml │ │ └── Invalid.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ ├── Web.config │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── chapter04.csproj ├── chapter04.sln └── wwwroot │ └── js │ └── script.js ├── Chapter05 ├── Controllers │ └── HomeController.cs ├── CustomRazorPageActivator.cs ├── ICustomInitializable.cs ├── IMyService.cs ├── MyPage.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Resources │ └── Views │ │ └── Home │ │ ├── Index.en.resx │ │ └── Index.pt.resx ├── Startup.cs ├── ThemesViewLocationExpander.cs ├── Views │ └── Home │ │ ├── Index.cshtml │ │ └── MyPage.cshtml ├── chapter05.csproj └── chapter05.sln ├── Chapter06 ├── AjaxOnlyAttribute.cs ├── Controllers │ ├── HomeController.cs │ └── RepositoryController.cs ├── HtmlHelperExtensions.cs ├── IsEvenAttribute.cs ├── IsEvenClientModelValidator.cs ├── IsEvenClientModelValidatorProvider.cs ├── IsEvenModelValidator.cs ├── IsEvenModelValidatorProvider.cs ├── Models │ ├── ContactModel.cs │ ├── ContactModelMetadata.cs │ ├── Gender.cs │ ├── GenderModelBinder.cs │ ├── Location.cs │ └── ProductOrder.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── ValidationMethods.cs ├── Views │ ├── Home │ │ ├── Create.cshtml │ │ └── Index.cshtml │ ├── Shared │ │ ├── DisplayTemplates │ │ │ └── Location.cshtml │ │ ├── EditorTemplates │ │ │ └── Location.cshtml │ │ └── _Layout.cshtml │ ├── Web.config │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── chapter06.csproj ├── chapter06.sln └── wwwroot │ └── lib │ ├── jquery.js │ ├── jquery.validate.js │ └── jquery.validate.unobtrusive.js ├── Chapter07 ├── Areas │ ├── Admin │ │ └── Pages │ │ │ └── Index.cshtml │ ├── HR │ │ └── Pages │ │ │ └── Index.cshtml │ └── Orders │ │ └── Pages │ │ └── Index.cshtml ├── IMyService.cs ├── MyService.cs ├── Pages │ ├── HelloWorld.cshtml │ ├── HelloWorld.cshtml.cs │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── chapter11.csproj └── chapter11.sln ├── Chapter08 ├── Configuration │ ├── OrderConfiguration.cs │ └── ProductConfiguration.cs ├── Controllers │ ├── ApiController.cs │ ├── HomeController.cs │ ├── OrdersController.cs │ ├── PetController.cs │ └── ProductsController.cs ├── Models │ ├── Model.cs │ ├── Order.cs │ ├── Pet.cs │ └── Product.cs ├── ODataSwaggerOperationFilter.cs ├── ODataSwaggerOptions.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── appsettings.Development.json ├── appsettings.json ├── chapter08.csproj ├── chapter08.sln └── chapter08.xml ├── Chapter09 ├── ClassLibrary │ ├── Class1.cs │ └── ClassLibrary.csproj ├── Controllers │ └── HomeController.cs ├── HelloWorldTagHelperComponent.cs ├── Models │ └── ErrorViewModel.cs ├── MyViewComponent.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── RazorClassLibrary │ ├── RazorClassLibrary.csproj │ └── wwwroot │ │ └── script.js ├── Startup.cs ├── TimeTagHelper.cs ├── Views │ ├── Home │ │ ├── Index.cshtml │ │ ├── PartialView.cshtml │ │ └── Privacy.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ ├── Web.config │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── chapter09.csproj └── chapter09.sln ├── Chapter10 ├── CacheFilter.cs ├── CacheResourceFilter.cs ├── Controllers │ └── HomeController.cs ├── ErrorFilter.cs ├── FirstFilter.cs ├── LogActionAttribute.cs ├── LogFilter.cs ├── Models │ └── ErrorViewModel.cs ├── NotFoundAttribute.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── Views │ ├── Home │ │ ├── Index.cshtml │ │ └── Privacy.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ ├── Web.config │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── chapter10.csproj └── chapter10.sln ├── Chapter11 ├── ApplicationBuilderExtensions.cs ├── ApplicationDbContext.cs ├── ApplicationRole.cs ├── ApplicationUser.cs ├── Controllers │ ├── AccountController.cs │ └── HomeController.cs ├── DayOfWeekAuthorizationHandler.cs ├── DayOfWeekRequirement.cs ├── LocalIpHandler.cs ├── LocalIpRequirement.cs ├── Migrations │ ├── 20200528194317_Initial.Designer.cs │ ├── 20200528194317_Initial.cs │ ├── 20200528211211_Personal Data.Designer.cs │ ├── 20200528211211_Personal Data.cs │ └── ApplicationDbContextModelSnapshot.cs ├── Models │ ├── ErrorViewModel.cs │ └── LoginModel.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── ProtectedPathOptions.cs ├── ProtectedPathsMiddleware.cs ├── Startup.cs ├── Views │ ├── Account │ │ ├── Create.cshtml │ │ ├── Forbidden.cshtml │ │ └── Login.cshtml │ ├── Home │ │ ├── Index.cshtml │ │ ├── Privacy.cshtml │ │ └── Private.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ ├── _Layout.cshtml │ │ └── _ValidationScriptsPartial.cshtml │ ├── Web.config │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── appsettings.Development.json ├── appsettings.json ├── chapter07.csproj ├── chapter07.sln └── wwwroot │ ├── css │ └── site.css │ ├── favicon.ico │ ├── js │ └── site.js │ └── lib │ ├── bootstrap │ ├── LICENSE │ └── dist │ │ ├── css │ │ ├── bootstrap-grid.css │ │ ├── bootstrap-grid.css.map │ │ ├── bootstrap-grid.min.css │ │ ├── bootstrap-grid.min.css.map │ │ ├── bootstrap-reboot.css │ │ ├── bootstrap-reboot.css.map │ │ ├── bootstrap-reboot.min.css │ │ ├── bootstrap-reboot.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ │ └── js │ │ ├── bootstrap.bundle.js │ │ ├── bootstrap.bundle.js.map │ │ ├── bootstrap.bundle.min.js │ │ ├── bootstrap.bundle.min.js.map │ │ ├── bootstrap.js │ │ ├── bootstrap.js.map │ │ ├── bootstrap.min.js │ │ └── bootstrap.min.js.map │ ├── jquery-validation-unobtrusive │ ├── LICENSE.txt │ ├── jquery.validate.unobtrusive.js │ └── jquery.validate.unobtrusive.min.js │ ├── jquery-validation │ ├── LICENSE.md │ └── dist │ │ ├── additional-methods.js │ │ ├── additional-methods.min.js │ │ ├── jquery.validate.js │ │ └── jquery.validate.min.js │ └── jquery │ ├── LICENSE.txt │ └── dist │ ├── jquery.js │ ├── jquery.min.js │ └── jquery.min.map ├── Chapter12 ├── Controllers │ └── HomeController.cs ├── FileLogger.cs ├── FileLoggerProvider.cs ├── LogElapsedUrlEventSource.cs ├── LoggerAttribute.cs ├── LoggerFactoryExtensions.cs ├── LoggingMiddleware.cs ├── MiddlewareExtensions.cs ├── Models │ └── ErrorViewModel.cs ├── MyDbContext.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── TraceDiagnosticListener.cs ├── TraceIdentifierMessageHandler.cs ├── Views │ ├── Home │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ ├── Web.config │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── WebHealthCheck.cs ├── appsettings.json ├── chapter12.csproj └── chapter12.sln ├── Chapter13 ├── Controllers │ └── HomeController.cs ├── Models │ └── ErrorViewModel.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── UnitTests │ ├── CalculatorTest.cs │ ├── ControllerTests.cs │ ├── IMyFeature.cs │ ├── IMyService.cs │ ├── IntegrationTests.cs │ ├── MyCustomWebApplicationFactory.cs │ ├── MyFeatureImplementation.cs │ ├── MyServiceImplementation.cs │ ├── MyTests.cs │ ├── RequestCookieCollection.cs │ ├── SharedData.cs │ ├── UITests.cs │ ├── UnitTest1.cs │ └── UnitTests.csproj ├── Views │ ├── Home │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ ├── Web.config │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── chapter13.csproj └── chapter13.sln ├── Chapter14 ├── ClientApp │ ├── Algebra.js │ └── index.js ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── chapter14.csproj ├── chapter14.sln ├── libman.json ├── package-lock.json ├── package.json └── wwwroot │ └── lib │ ├── core.js │ ├── jquery.js │ ├── jquery.min.js │ ├── jquery.min.map │ ├── jquery.slim.js │ ├── jquery.slim.min.js │ ├── jquery.slim.min.map │ ├── jquery.validate.unobtrusive.js │ └── jquery.validate.unobtrusive.min.js ├── Chapter15 ├── Controllers │ └── HomeController.cs ├── Models │ └── ErrorViewModel.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── Views │ ├── Home │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ ├── Web.config │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── chapter15.csproj ├── chapter15.sln └── coreprofiler.json ├── Chapter16 ├── Controllers │ ├── ChatController.cs │ └── HomeController.cs ├── Hubs │ ├── ChatHub.cs │ └── TimerHub.cs ├── Models │ └── ErrorViewModel.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── Views │ ├── Home │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ ├── Web.config │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── chapter16.csproj ├── chapter16.sln ├── package-lock.json ├── package.json └── wwwroot │ └── lib │ ├── msgpack5 │ ├── msgpack5.js │ └── msgpack5.min.js │ └── signalr │ ├── signalr-protocol-msgpack.js │ ├── signalr-protocol-msgpack.min.js │ ├── signalr.js │ └── signalr.min.js ├── Chapter17 ├── App.razor ├── Data │ ├── WeatherForecast.cs │ └── WeatherForecastService.cs ├── Pages │ ├── Clock.razor │ ├── ContainerComponent.razor │ ├── Counter.razor │ ├── Error.razor │ ├── FetchData.razor │ ├── Index.razor │ ├── Index.razor.cs │ ├── Page.razor │ ├── Search.razor │ ├── SimpleComponent.razor │ ├── SimpleComponent.razor.cs │ ├── Timer.razor │ └── _Host.cshtml ├── Program.cs ├── Properties │ └── launchSettings.json ├── Shared │ ├── MainLayout.razor │ ├── NavMenu.razor │ └── SurveyPrompt.razor ├── Startup.cs ├── _Imports.razor ├── appsettings.Development.json ├── appsettings.json ├── chapter17.csproj ├── chapter17.sln └── wwwroot │ ├── css │ ├── bootstrap │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ ├── open-iconic │ │ ├── FONT-LICENSE │ │ ├── ICON-LICENSE │ │ ├── README.md │ │ └── font │ │ │ ├── css │ │ │ └── open-iconic-bootstrap.min.css │ │ │ └── fonts │ │ │ ├── open-iconic.eot │ │ │ ├── open-iconic.otf │ │ │ ├── open-iconic.svg │ │ │ ├── open-iconic.ttf │ │ │ └── open-iconic.woff │ └── site.css │ └── favicon.ico ├── Chapter18 ├── Areas │ └── Admin │ │ ├── Controllers │ │ └── ManageController.cs │ │ └── Views │ │ └── Manage │ │ └── Index.cshtml ├── BackgroundHostedService.cs ├── Controllers │ ├── BlogController.cs │ ├── HomeController.cs │ └── WeatherController.cs ├── CustomConvention.cs ├── CustomFilter.cs ├── CustomHostingStartup.cs ├── IOpenWeatherMap.cs ├── Migrations │ ├── 20200603160649_Initial.Designer.cs │ ├── 20200603160649_Initial.cs │ ├── Blog │ │ ├── 20200603161532_Initial.Designer.cs │ │ ├── 20200603161532_Initial.cs │ │ └── BlogContextModelSnapshot.cs │ └── OrdersContextModelSnapshot.cs ├── Models │ ├── BlogContext.cs │ ├── ErrorViewModel.cs │ └── OrdersContext.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Protos │ ├── Greet.proto │ └── pingpong.proto ├── Services │ ├── LogInterceptor.cs │ └── PingPongService.cs ├── Startup.cs ├── UserIdHandler.cs ├── Views │ ├── Home │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ ├── Web.config │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── appsettings.json ├── chapter18.csproj ├── chapter18.sln ├── embeddedfile.html └── wwwroot │ ├── file.html │ └── folder │ └── document.html ├── LICENSE └── README.md /Chapter01/IMyOtherService.cs: -------------------------------------------------------------------------------- 1 | namespace chapter01 2 | { 3 | public interface IMyOtherService 4 | { 5 | void MyOtherOperation(); 6 | } 7 | } -------------------------------------------------------------------------------- /Chapter01/IMyService.cs: -------------------------------------------------------------------------------- 1 | namespace chapter01 2 | { 3 | public interface IMyService 4 | { 5 | void MyOperation(); 6 | } 7 | } -------------------------------------------------------------------------------- /Chapter01/Middleware.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.Http; 3 | 4 | namespace chapter01 5 | { 6 | public class Middleware 7 | { 8 | private readonly RequestDelegate _next; 9 | 10 | public Middleware(RequestDelegate next) => _next = next; 11 | 12 | public async Task Invoke(HttpContext context) 13 | { 14 | await context.Response.WriteAsync("This is a middleware class!"); 15 | await _next(context); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter01/MyGenericService.cs: -------------------------------------------------------------------------------- 1 | namespace chapter01 2 | { 3 | public class MyGenericService 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Chapter01/MyOtherService.cs: -------------------------------------------------------------------------------- 1 | namespace chapter01 2 | { 3 | public class MyOtherService : IMyOtherService 4 | { 5 | public void MyOtherOperation() 6 | { 7 | 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter01/MyService.cs: -------------------------------------------------------------------------------- 1 | namespace chapter01 2 | { 3 | public class MyService : IMyService 4 | { 5 | private readonly IMyOtherService _other; 6 | 7 | public MyService(IMyOtherService other) => _other = other; 8 | 9 | public void MyOperation() 10 | { 11 | //do something 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Chapter01/MyType.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | 3 | namespace chapter01 4 | { 5 | public class MyType 6 | { 7 | private readonly HttpContext httpContext; 8 | public MyType(IHttpContextAccessor httpContextAccessor) => httpContext = httpContextAccessor.HttpContext; 9 | } 10 | } -------------------------------------------------------------------------------- /Chapter01/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:61721", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter01": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter01/StartupDevelopment.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace chapter01 6 | { 7 | public class StartupDevelopment 8 | { 9 | public IConfiguration Configuration { get; } 10 | 11 | public StartupDevelopment(IConfiguration configuration) => Configuration = configuration; 12 | 13 | public void ConfigureServices(IServiceCollection services) 14 | { 15 | } 16 | 17 | public void Configure(IApplicationBuilder app) 18 | { 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter01/StartupProduction.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace chapter01 6 | { 7 | public class StartupProduction 8 | { 9 | public IConfiguration Configuration { get; } 10 | 11 | public StartupProduction(IConfiguration configuration) => Configuration = configuration; 12 | 13 | public void ConfigureServices(IServiceCollection services) 14 | { 15 | } 16 | 17 | public void Configure(IApplicationBuilder app) 18 | { 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter01/StartupStaging.cs: -------------------------------------------------------------------------------- 1 | namespace chapter01 2 | { 3 | public class StartupStaging 4 | { 5 | 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Chapter01/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter01/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "AllowedHosts": "*" 8 | } 9 | -------------------------------------------------------------------------------- /Chapter01/chapter01.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Chapter01/chapter01.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2016 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chapter01", "chapter01.csproj", "{4499A93A-269F-4769-879F-17A93B67E7B1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B51FC4D8-EDD6-40A6-998A-9F792B794681} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Chapter02/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.Extensions.Options; 4 | using Microsoft.FeatureManagement; 5 | using Microsoft.FeatureManagement.Mvc; 6 | 7 | namespace chapter02.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | private readonly LoggingSettings _settings; 12 | private readonly IFeatureManager _featureManager; 13 | 14 | public HomeController(IOptionsSnapshot settings, IFeatureManager featureManager) 15 | { 16 | _settings = settings.Value; 17 | 18 | _featureManager = featureManager; 19 | 20 | var consoleSettings = settings.Get("Console"); 21 | } 22 | 23 | public async Task Index() 24 | { 25 | var isEnabled = await _featureManager.IsEnabledAsync("MyFeature"); 26 | 27 | return View(); 28 | } 29 | 30 | [FeatureGate("MyFeature")] 31 | public IActionResult Check() => Json(new { MyFeature = true }); 32 | } 33 | } -------------------------------------------------------------------------------- /Chapter02/LogLevelSettings.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | 3 | namespace chapter02 4 | { 5 | public class LogLevelSettings 6 | { 7 | public LogLevel Default { get; set; } 8 | public LogLevel System { get; set; } 9 | public LogLevel Microsoft { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /Chapter02/LoggingSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Microsoft.Extensions.Logging; 3 | 4 | namespace chapter02 5 | { 6 | public class LoggingSettings 7 | { 8 | public Dictionary LogLevel { get; set; } = new Dictionary(); 9 | } 10 | } -------------------------------------------------------------------------------- /Chapter02/MyFeatureFilter.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.Http; 3 | using Microsoft.FeatureManagement; 4 | 5 | namespace chapter02 6 | { 7 | [FilterAlias("MyFeature")] 8 | public class MyFeatureFilter : IFeatureFilter 9 | { 10 | private readonly HttpContext _httpContext; 11 | 12 | public MyFeatureFilter(IHttpContextAccessor httpContextAccessor) => _httpContext = httpContextAccessor.HttpContext; 13 | 14 | public Task EvaluateAsync(FeatureFilterEvaluationContext context) => Task.FromResult(true); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter02/MySettings.cs: -------------------------------------------------------------------------------- 1 | namespace chapter02 2 | { 3 | public class MySettings 4 | { 5 | public string A { get; set; } 6 | public int B { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Chapter02/PostConfigureLoggingSettings.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | 3 | namespace chapter02 4 | { 5 | public class PostConfigureLoggingSettings : IPostConfigureOptions 6 | { 7 | public void PostConfigure(string name, LoggingSettings options) 8 | { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Chapter02/PreConfigureLoggingSettings.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | 3 | namespace chapter02 4 | { 5 | public class PreConfigureLoggingSettings : IConfigureOptions 6 | { 7 | public void Configure(LoggingSettings options) 8 | { 9 | //act upon the configured instance 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Chapter02/PreConfigureNamedLoggingSettings.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | 3 | namespace chapter02 4 | { 5 | public class PreConfigureNamedLoggingSettings : IConfigureNamedOptions 6 | { 7 | public void Configure(string name, LoggingSettings options) 8 | { 9 | //act upon the configured instance 10 | } 11 | 12 | public void Configure(LoggingSettings options) 13 | { 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Chapter02/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:61721", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter02": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter02/RedirectDisabledFeatureHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Microsoft.AspNetCore.Mvc; 4 | using Microsoft.AspNetCore.Mvc.Filters; 5 | using Microsoft.FeatureManagement.Mvc; 6 | 7 | namespace chapter02 8 | { 9 | public sealed class RedirectDisabledFeatureHandler : IDisabledFeaturesHandler 10 | { 11 | public RedirectDisabledFeatureHandler(string url) => Url = url; 12 | 13 | public string Url { get; } 14 | 15 | public Task HandleDisabledFeatures(IEnumerable features, ActionExecutingContext context) 16 | { 17 | context.Result = new RedirectResult(Url); 18 | return Task.CompletedTask; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter02/RegistryConfigurationExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Win32; 3 | 4 | namespace chapter02 5 | { 6 | public static class RegistryConfigurationExtensions 7 | { 8 | public static IConfigurationBuilder AddRegistry(this IConfigurationBuilder builder, RegistryHive hive = RegistryHive.CurrentUser) => builder.Add(new RegistryConfigurationSource { Hive = hive }); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter02/RegistryConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Win32; 3 | 4 | namespace chapter02 5 | { 6 | public sealed class RegistryConfigurationSource : IConfigurationSource 7 | { 8 | public RegistryHive Hive { get; set; } = RegistryHive.CurrentUser; 9 | 10 | public IConfigurationProvider Build(IConfigurationBuilder builder) => new RegistryConfigurationProvider(this); 11 | } 12 | } -------------------------------------------------------------------------------- /Chapter02/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @using chapter02 2 | @using Microsoft.Extensions.Options 3 | @using Microsoft.FeatureManagement 4 | 5 | @inject IOptions LoggingSettings 6 | @inject IFeatureManager FeatureManager 7 | 8 | 9 | 10 | 11 | 12 | Index 13 | 14 | 15 |

Default log level: @LoggingSettings.Value.LogLevel["Default"]

16 | 17 | @if (await FeatureManager.IsEnabledAsync("MyFeature")) 18 | { 19 |

MyFeature is enabled!

20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /Chapter02/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Hosting 2 | @using Microsoft.Extensions.Options 3 | @using Microsoft.Extensions.Configuration 4 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 5 | -------------------------------------------------------------------------------- /Chapter02/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter02/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Warning", 6 | "System": "Information", 7 | "Microsoft": "Information" 8 | } 9 | }, 10 | "AllowedHosts": "*", 11 | "ConnectionStrings": { 12 | "DefaultConnection": "Server=(localdb)mssqllocaldb; Database=aspnetcore" 13 | }, 14 | "A": { 15 | "B": { 16 | "C": "value" 17 | } 18 | }, 19 | "FeatureManagement": { 20 | "MyFeature": true, 21 | //"EnabledFor": [ 22 | //{ 23 | //"Name": "MyFeature", 24 | //"Parameters": { 25 | //"A": "AAAAA", 26 | //"B": 10 27 | //} 28 | //}, 29 | //] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Chapter03/Controllers/Calculation.cs: -------------------------------------------------------------------------------- 1 | namespace chapter03.Controllers 2 | { 3 | public class Calculation 4 | { 5 | public int B { get; set; } 6 | public int A { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /Chapter03/Controllers/CalculatorController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using System; 3 | 4 | namespace chapter03.Controllers 5 | { 6 | public class CalculatorController : Controller 7 | { 8 | //Calculator/CalculateDirectly 9 | [HttpGet(Name = "CalculateDirectly")] 10 | public IActionResult Calculate(int a, int b) 11 | { 12 | return Json(new { Result = a + b }); 13 | } 14 | 15 | //Calculator/CalculateByKey 16 | [HttpGet(Name = "CalculateById")] 17 | public IActionResult Calculate(Guid calculationId) 18 | { 19 | return Json(new { Result = calculationId.GetHashCode() }); 20 | } 21 | 22 | //POST Calculator/Calculate 23 | [HttpPost] 24 | public IActionResult Calculate([FromBody] Calculation calculation) 25 | { 26 | return Json(new { Result = calculation.A + calculation.B }); 27 | } 28 | 29 | [HttpGet("")] 30 | public IActionResult Default() 31 | { 32 | return Json(new { Ok = true }); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Chapter03/Controllers/ErrorController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace chapter03.Controllers 5 | { 6 | public class ErrorController : Controller 7 | { 8 | [Route("error/404")] 9 | public IActionResult Error404() 10 | { 11 | this.Response.StatusCode = StatusCodes.Status404NotFound; 12 | return this.View(); 13 | } 14 | 15 | 16 | [Route("error/{statusCode:int}")] 17 | public IActionResult Error(int statusCode) 18 | { 19 | this.Response.StatusCode = statusCode; 20 | this.ViewBag.StatusCode = statusCode; 21 | return this.View(); 22 | } 23 | 24 | [HttpGet("{*url}", Order = int.MaxValue)] 25 | public IActionResult CatchAll() 26 | { 27 | this.Response.StatusCode = StatusCodes.Status404NotFound; 28 | return this.View(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Chapter03/CustomDeveloperPageExceptionFilter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Diagnostics; 2 | using Microsoft.AspNetCore.Http; 3 | using System; 4 | using System.Data.Common; 5 | using System.Threading.Tasks; 6 | 7 | namespace chapter03 8 | { 9 | class CustomDeveloperPageExceptionFilter : IDeveloperPageExceptionFilter 10 | { 11 | public async Task HandleExceptionAsync(ErrorContext errorContext, Func next) 12 | { 13 | if (errorContext.Exception is DbException) 14 | { 15 | await errorContext.HttpContext.Response.WriteAsync("Error connecting to the DB"); 16 | } 17 | else 18 | { 19 | await next(errorContext); 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Chapter03/EvenIntRouteConstraint.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.AspNetCore.Routing; 3 | 4 | namespace chapter03 5 | { 6 | public class EvenIntRouteConstraint : IRouteConstraint 7 | { 8 | public bool Match( 9 | HttpContext httpContext, 10 | IRouter route, 11 | string routeKey, 12 | RouteValueDictionary values, 13 | RouteDirection routeDirection) 14 | { 15 | if ((values.ContainsKey(routeKey) == false) || (values[routeKey] == null)) 16 | { 17 | return false; 18 | } 19 | 20 | var value = values[routeKey].ToString(); 21 | 22 | if (int.TryParse(value, out var intValue) == false) 23 | { 24 | return false; 25 | } 26 | 27 | return (intValue % 2) == 0; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Chapter03/ITranslator.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace chapter03 4 | { 5 | public interface ITranslator 6 | { 7 | Task Translate(string sourceLanguage, string term); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter03/IsAuthenticatedRouteConstraint.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.AspNetCore.Routing; 3 | 4 | namespace chapter03 5 | { 6 | public class IsAuthenticatedRouteConstraint : IRouteConstraint 7 | { 8 | public bool Match( 9 | HttpContext httpContext, 10 | IRouter route, 11 | string routeKey, 12 | RouteValueDictionary values, 13 | RouteDirection routeDirection) 14 | { 15 | return httpContext.Request.Cookies.ContainsKey("auth"); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter03/MyConstraint.cs: -------------------------------------------------------------------------------- 1 | namespace chapter03 2 | { 3 | internal class MyConstraint 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Chapter03/MyMetadata1.cs: -------------------------------------------------------------------------------- 1 | namespace chapter03 2 | { 3 | public class MyMetadata1 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Chapter03/MyMetadata2.cs: -------------------------------------------------------------------------------- 1 | namespace chapter03 2 | { 3 | public class MyMetadata2 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /Chapter03/MyTranslator.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace chapter03 4 | { 5 | internal class MyTranslator : ITranslator 6 | { 7 | public Task Translate(string sourceLanguage, string term) 8 | { 9 | //does nothing, just return the original term 10 | return Task.FromResult(term); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Chapter03/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | 4 | namespace chapter03 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IWebHostBuilder CreateHostBuilder(string[] args) => 14 | WebHost 15 | .CreateDefaultBuilder(args) 16 | .UseStartup(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter03/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:50139/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter03": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:5000/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter03/ResponseMiddleware.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using System.Threading.Tasks; 3 | 4 | namespace chapter03 5 | { 6 | internal class ResponseMiddleware 7 | { 8 | private readonly RequestDelegate _next; 9 | 10 | public ResponseMiddleware(RequestDelegate next) 11 | { 12 | this._next = next; 13 | } 14 | 15 | public async Task Invoke(HttpContext ctx) 16 | { 17 | await ctx.Response.WriteAsync("Hello, from a middleware!"); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Chapter03/Views/Error/Error.cshtml: -------------------------------------------------------------------------------- 1 |  2 | @{ 3 | Layout = null; 4 | } 5 | 6 | 7 | 8 | 9 | 10 | 11 | Error: @ViewBag.StatusCode 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Chapter03/Views/Error/Error404.cshtml: -------------------------------------------------------------------------------- 1 |  2 | @{ 3 | Layout = null; 4 | } 5 | 6 | 7 | 8 | 9 | 10 | 11 | Error 404: Not Found 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Chapter03/Views/Home/Error401.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Error401 6 | 7 | 8 |

Unauthorized

9 | 10 | 11 | -------------------------------------------------------------------------------- /Chapter03/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 |  2 | @{ 3 | Layout = null; 4 | } 5 | 6 | 7 | 8 | 9 | 10 | 11 | Index 12 | 13 | 14 |

Hello, World!

15 | 16 | 17 | -------------------------------------------------------------------------------- /Chapter03/chapter03.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Chapter03/chapter03.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2016 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chapter03", "chapter03.csproj", "{4499A93A-269F-4769-879F-17A93B67E7B1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B51FC4D8-EDD6-40A6-998A-9F792B794681} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Chapter03/wwwroot/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 |

This is the fallback page!

9 | 10 | -------------------------------------------------------------------------------- /Chapter04/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using chapter04.Models; 2 | using Microsoft.AspNetCore.Mvc; 3 | using System; 4 | using System.Net.Http; 5 | using System.Text.Json; 6 | using System.Threading.Tasks; 7 | 8 | namespace chapter04.Controllers 9 | { 10 | public class HomeController : Controller 11 | { 12 | public IActionResult Index() 13 | { 14 | return View(); 15 | } 16 | 17 | public IActionResult Error() 18 | { 19 | return View(); 20 | } 21 | 22 | public IActionResult Invalid() 23 | { 24 | return View(); 25 | } 26 | 27 | [HttpPost] 28 | public IActionResult Process([FromForm] Model model) 29 | { 30 | return Ok(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Chapter04/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace chapter04.Models 2 | { 3 | public class ErrorViewModel 4 | { 5 | public string RequestId { get; set; } 6 | 7 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter04/Models/Model.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace chapter04.Models 4 | { 5 | public class Model 6 | { 7 | [Required] 8 | public string RequiredProperty { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter04/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration.Json; 4 | using Microsoft.Extensions.Hosting; 5 | using System; 6 | using System.IO; 7 | 8 | namespace chapter04 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | CreateHostBuilder(args).Build().Run(); 15 | } 16 | 17 | public static IHostBuilder CreateHostBuilder(string[] args) => 18 | Host 19 | .CreateDefaultBuilder(args) 20 | .ConfigureWebHostDefaults(builder => 21 | { 22 | builder.UseStartup(); 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter04/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:29835/", 7 | "sslPort": 44356 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter04": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter04/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 

Hello, World!

2 | 3 | @using (Html.BeginForm("Process", "Home", FormMethod.Post)) 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /Chapter04/Views/Home/Invalid.cshtml: -------------------------------------------------------------------------------- 1 | 

Invalid model!

2 |
-------------------------------------------------------------------------------- /Chapter04/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /Chapter04/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | chapter04 - @ViewData["Title"] 7 | 8 | 9 | 10 | @RenderBody() 11 | 12 | 13 | -------------------------------------------------------------------------------- /Chapter04/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Chapter04/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using chapter04 2 | @using chapter04.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Chapter04/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Chapter04/chapter04.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Chapter04/chapter04.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2016 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chapter04", "chapter04.csproj", "{4499A93A-269F-4769-879F-17A93B67E7B1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B51FC4D8-EDD6-40A6-998A-9F792B794681} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Chapter04/wwwroot/js/script.js: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /Chapter05/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace chapter05.Controllers 4 | { 5 | public class HomeController : Controller 6 | { 7 | public IActionResult Index() 8 | { 9 | return View(); 10 | } 11 | 12 | public IActionResult MyPage() 13 | { 14 | return View(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter05/ICustomInitializable.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Razor; 2 | using Microsoft.AspNetCore.Mvc.Rendering; 3 | 4 | namespace chapter05 5 | { 6 | public interface ICustomInitializable : IRazorPage 7 | { 8 | void Init(ViewContext context); 9 | } 10 | } -------------------------------------------------------------------------------- /Chapter05/IMyService.cs: -------------------------------------------------------------------------------- 1 | namespace chapter05 2 | { 3 | public interface IMyService 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Chapter05/MyPage.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Razor; 2 | using Microsoft.AspNetCore.Mvc.Rendering; 3 | using System.Threading.Tasks; 4 | 5 | namespace chapter05 6 | { 7 | public partial class MyPage : RazorPage, ICustomInitializable 8 | { 9 | public MyPage() 10 | { 11 | 12 | } 13 | public override Task ExecuteAsync() 14 | { 15 | return Task.CompletedTask; 16 | } 17 | 18 | public void Init(ViewContext context) 19 | { 20 | 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter05/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | 4 | namespace chapter05 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateWebHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 14 | WebHost 15 | .CreateDefaultBuilder(args) 16 | .UseStartup(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter05/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:19591/", 7 | "sslPort": 44325 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter05": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter05/ThemesViewLocationExpander.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Razor; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace chapter05 6 | { 7 | public class ThemesViewLocationExpander : IViewLocationExpander 8 | { 9 | public ThemesViewLocationExpander(string theme) 10 | { 11 | this.Theme = theme; 12 | } 13 | 14 | public string Theme { get; } 15 | 16 | public IEnumerable ExpandViewLocations( 17 | ViewLocationExpanderContext context, 18 | IEnumerable viewLocations) 19 | { 20 | var theme = context.Values["theme"]; 21 | 22 | return viewLocations 23 | .Select(x => x.Replace("/Views/", "/Views/" + theme + "/")) 24 | .Concat(viewLocations); 25 | } 26 | 27 | public void PopulateValues(ViewLocationExpanderContext context) 28 | { 29 | context.Values["theme"] = this.Theme; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter05/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Mvc.Localization 2 | @inject IViewLocalizer Localizer 3 |

@Localizer["Hello"]

4 | -------------------------------------------------------------------------------- /Chapter05/Views/Home/MyPage.cshtml: -------------------------------------------------------------------------------- 1 | @inherits chapter05.MyPage 2 | @{ 3 | } 4 |

My Page

-------------------------------------------------------------------------------- /Chapter05/chapter05.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Chapter05/chapter05.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2016 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chapter05", "chapter05.csproj", "{4499A93A-269F-4769-879F-17A93B67E7B1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B51FC4D8-EDD6-40A6-998A-9F792B794681} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Chapter06/AjaxOnlyAttribute.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.AspNetCore.Mvc.Filters; 4 | using System; 5 | 6 | namespace chapter06 7 | { 8 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 9 | public sealed class AjaxOnlyAttribute : Attribute, IResourceFilter 10 | { 11 | public void OnResourceExecuted(ResourceExecutedContext context) 12 | { 13 | } 14 | 15 | public void OnResourceExecuting(ResourceExecutingContext context) 16 | { 17 | if (context.HttpContext.Request.Headers["X-Requested-With"] != "XMLHttpRequest") 18 | { 19 | context.Result = new StatusCodeResult(StatusCodes.Status404NotFound); 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter06/Controllers/RepositoryController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace chapter06.Controllers 5 | { 6 | public class RepositoryController : Controller 7 | { 8 | [AcceptVerbs("Get", "Post")] 9 | public IActionResult CheckEmailExists(string email) 10 | { 11 | //if (this._repository.CheckEmailExists(email)) 12 | //{ 13 | // return this.Json(false); 14 | //} 15 | 16 | return Json(true); 17 | } 18 | 19 | [HttpPost("[controller]/[action]")] 20 | public IActionResult SaveForm(IFormFile file) 21 | { 22 | var length = file.Length; 23 | var name = file.Name; 24 | //do something with the file 25 | return View(); 26 | } 27 | 28 | [AjaxOnly] 29 | public IActionResult AjaxOnly() 30 | { 31 | return Json(true); 32 | } 33 | 34 | public IActionResult Save() 35 | { 36 | return View(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Chapter06/IsEvenAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace chapter06 5 | { 6 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)] 7 | public sealed class IsEvenAttribute : ValidationAttribute 8 | { 9 | protected override ValidationResult IsValid(object value, ValidationContext validationContext) 10 | { 11 | if (value != null) 12 | { 13 | try 14 | { 15 | var convertedValue = Convert.ToDouble(value); 16 | var isValid = (convertedValue % 2) == 0; 17 | 18 | if (!isValid) 19 | { 20 | return new ValidationResult(this.ErrorMessage, 21 | new[] { validationContext.MemberName }); 22 | } 23 | } 24 | catch { } 25 | } 26 | 27 | return ValidationResult.Success; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter06/IsEvenClientModelValidator.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; 2 | using System.Linq; 3 | 4 | namespace chapter06 5 | { 6 | public sealed class IsEvenClientModelValidator : IClientModelValidator 7 | { 8 | public void AddValidation(ClientModelValidationContext context) 9 | { 10 | context.Attributes["data-val"] = true.ToString().ToLowerInvariant(); 11 | context.Attributes["data-val-iseven"] = this.GetErrorMessage(context); 12 | } 13 | 14 | private string GetErrorMessage(ClientModelValidationContext context) 15 | { 16 | var attr = context 17 | .ModelMetadata 18 | .ValidatorMetadata 19 | .OfType() 20 | .SingleOrDefault(); 21 | 22 | var msg = attr.FormatErrorMessage(context.ModelMetadata.PropertyName); 23 | 24 | return msg; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter06/IsEvenModelValidator.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace chapter06 6 | { 7 | public sealed class IsEvenModelValidator : IModelValidator 8 | { 9 | public IEnumerable Validate(ModelValidationContext context) 10 | { 11 | if (context.Model != null) 12 | { 13 | try 14 | { 15 | var value = Convert.ToDouble(context.Model); 16 | if ((value % 2) == 0) 17 | { 18 | yield break; 19 | } 20 | } 21 | catch { } 22 | } 23 | 24 | yield return new ModelValidationResult( 25 | context.ModelMetadata.PropertyName, 26 | $"{context.ModelMetadata.PropertyName} is not even."); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter06/Models/ContactModel.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using System; 3 | 4 | namespace chapter06.Models 5 | { 6 | [ModelMetadataType(typeof(ContactModelMetadata))] 7 | [Bind("Email", "WorkEmail", "Birthday", "Gender")] 8 | public class ContactModel 9 | { 10 | public int Id { get; set; } 11 | public string Email { get; set; } 12 | public string WorkEmail { get; set; } 13 | public DateTime? Birthday { get; set; } 14 | public string Gender { get; set; } 15 | public bool IsActive { get; set; } = true; 16 | public Location Location { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter06/Models/ContactModelMetadata.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace chapter06.Models 6 | { 7 | internal abstract class ContactModelMetadata 8 | { 9 | [HiddenInput(DisplayValue = false)] 10 | public int Id { get; set; } 11 | [EmailAddress] 12 | [Required] 13 | [CustomValidation(typeof(ValidationMethods), "ValidateEmail")] 14 | public string Email { get; set; } 15 | [Display(Name = "Work Email", Description = "The work email", Prompt = "Please enter the work email")] 16 | [EmailAddress] 17 | public string WorkEmail { get; set; } 18 | [DisplayFormat(NullDisplayText = "No birthday supplied", DataFormatString = "{0:yyyyMMdd}")] 19 | [DataType(DataType.Date)] 20 | public DateTime? Birthday { get; set; } 21 | [ModelBinder(typeof(GenderModelBinder), Name = "Gender")] 22 | [Display(Name = "Gender")] 23 | public string Gender { get; set; } 24 | [HiddenInput(DisplayValue = false)] 25 | public bool IsActive { get; set; } 26 | [UIHint("Location")] 27 | public Location Location { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /Chapter06/Models/Gender.cs: -------------------------------------------------------------------------------- 1 | namespace chapter06.Models 2 | { 3 | public enum Gender 4 | { 5 | Unspecified = 0, 6 | Male, 7 | Female 8 | } 9 | } -------------------------------------------------------------------------------- /Chapter06/Models/GenderModelBinder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.ModelBinding; 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace chapter06.Models 6 | { 7 | public class GenderModelBinder : IModelBinder 8 | { 9 | public Task BindModelAsync(ModelBindingContext bindingContext) 10 | { 11 | var modelName = bindingContext.ModelName; 12 | 13 | var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName); 14 | 15 | if (valueProviderResult != ValueProviderResult.None) 16 | { 17 | bindingContext.ModelState.SetModelValue(modelName, valueProviderResult); 18 | 19 | var value = valueProviderResult.FirstValue; 20 | 21 | if (!string.IsNullOrWhiteSpace(value)) 22 | { 23 | if (Enum.TryParse(value, true, out var gender)) 24 | { 25 | bindingContext.Result = ModelBindingResult.Success(gender.ToString()); 26 | } 27 | else 28 | { 29 | bindingContext.ModelState.TryAddModelError(modelName, "Invalid gender."); 30 | } 31 | } 32 | } 33 | 34 | return Task.CompletedTask; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /Chapter06/Models/Location.cs: -------------------------------------------------------------------------------- 1 | namespace chapter06.Models 2 | { 3 | public class Location 4 | { 5 | public decimal Latitude { get; set; } 6 | public decimal Longitude { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Chapter06/Models/ProductOrder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace chapter06.Models 6 | { 7 | public class ProductOrder : IValidatableObject 8 | { 9 | public int Id { get; set; } 10 | public DateTime Timestamp { get; set; } 11 | public int ProductId { get; set; } 12 | public int Quantity { get; set; } 13 | public decimal Price { get; set; } 14 | 15 | public IEnumerable Validate(ValidationContext context) 16 | { 17 | if (this.Id <= 0) 18 | { 19 | yield return new ValidationResult("Missing id", new[] { "Id" }); 20 | } 21 | 22 | if (this.ProductId <= 0) 23 | { 24 | yield return new ValidationResult("Invalid product", new[] { "ProductId" }); 25 | } 26 | 27 | if (this.Quantity <= 0) 28 | { 29 | yield return new ValidationResult("Invalid quantity", new[] { "Quantity" }); 30 | } 31 | 32 | if (this.Timestamp > DateTime.Now) 33 | { 34 | yield return new ValidationResult("Order date is in the future", new[] { "Timestamp" }); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter06/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace chapter06 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateWebHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateWebHostBuilder(string[] args) => 14 | Host 15 | .CreateDefaultBuilder(args) 16 | .ConfigureWebHostDefaults(builder => 17 | { 18 | builder.UseStartup(); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter06/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:19591/", 7 | "sslPort": 44325 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter06": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter06/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace chapter06 7 | { 8 | public class Startup 9 | { 10 | public Startup(IConfiguration configuration) 11 | { 12 | this.Configuration = configuration; 13 | } 14 | 15 | public IConfiguration Configuration { get; } 16 | 17 | public void ConfigureServices(IServiceCollection services) 18 | { 19 | services 20 | .AddMvc() 21 | .AddViewOptions(options => 22 | { 23 | options.ClientModelValidatorProviders.Add(new IsEvenClientModelValidatorProvider()); 24 | }) 25 | .AddRazorRuntimeCompilation() 26 | .SetCompatibilityVersion(CompatibilityVersion.Version_3_0); 27 | } 28 | 29 | public void Configure(IApplicationBuilder app) 30 | { 31 | app.UseStaticFiles(); 32 | app.UseRouting(); 33 | app.UseEndpoints(endpoints => 34 | { 35 | endpoints.MapDefaultControllerRoute(); 36 | }); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Chapter06/ValidationMethods.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace chapter06 5 | { 6 | public static class ValidationMethods 7 | { 8 | public static ValidationResult ValidateEmail(string email, ValidationContext context) 9 | { 10 | if (!string.IsNullOrWhiteSpace(email)) 11 | { 12 | if (!Regex.IsMatch(email, @"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$")) 13 | { 14 | return new ValidationResult("Invalid email", new[] { context.MemberName }); 15 | } 16 | } 17 | 18 | return ValidationResult.Success; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter06/Views/Home/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model chapter06.Models.ContactModel 2 | 3 |
4 | 5 | @using (Html.BeginForm("Create", "Home")) 6 | { 7 | @Html.EditorForModel() 8 | 9 |
10 | @Html.EditorFor(x => x.Location) 11 |
12 | 13 | } -------------------------------------------------------------------------------- /Chapter06/Views/Shared/DisplayTemplates/Location.cshtml: -------------------------------------------------------------------------------- 1 | @model chapter06.Models.Location 2 |
3 | Latitude: @Model.Latitude - Longitude: @Model.Longitude 4 |
-------------------------------------------------------------------------------- /Chapter06/Views/Shared/EditorTemplates/Location.cshtml: -------------------------------------------------------------------------------- 1 | @model chapter06.Models.Location 2 |
3 | Latitude: @Html.TextBoxFor(x => x.Latitude) 4 | Longitude: @Html.TextBoxFor(x => x.Longitude) 5 |
-------------------------------------------------------------------------------- /Chapter06/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | } 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 34 | 35 | 36 | @RenderBody() 37 | 38 | -------------------------------------------------------------------------------- /Chapter06/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using chapter06 2 | @using chapter06.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Chapter06/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Chapter06/chapter06.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | PreserveNewest 22 | 23 | 24 | PreserveNewest 25 | 26 | 27 | PreserveNewest 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Chapter06/chapter06.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2016 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chapter06", "chapter06.csproj", "{4499A93A-269F-4769-879F-17A93B67E7B1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B51FC4D8-EDD6-40A6-998A-9F792B794681} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Chapter07/Areas/Admin/Pages/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | -------------------------------------------------------------------------------- /Chapter07/Areas/HR/Pages/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | -------------------------------------------------------------------------------- /Chapter07/Areas/Orders/Pages/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | -------------------------------------------------------------------------------- /Chapter07/IMyService.cs: -------------------------------------------------------------------------------- 1 | namespace chapter11 2 | { 3 | public interface IMyService 4 | { 5 | void DoSomething(); 6 | } 7 | } -------------------------------------------------------------------------------- /Chapter07/MyService.cs: -------------------------------------------------------------------------------- 1 | namespace chapter11 2 | { 3 | public class MyService : IMyService 4 | { 5 | public void DoSomething() 6 | { 7 | //not much 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /Chapter07/Pages/HelloWorld.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model chapter11.Pages.HelloWorldModel 3 | 4 | 5 | 6 | Hello World 7 | 8 | 9 |
10 |

@Html.Raw("Hello, World!")

11 |

Message: @Model.Message

12 | 13 | 14 | 15 | 16 |
17 | 18 | -------------------------------------------------------------------------------- /Chapter07/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 2 | @addTagHelper *, chapter11 3 | -------------------------------------------------------------------------------- /Chapter07/Pages/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | var s = ""; 3 | } -------------------------------------------------------------------------------- /Chapter07/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration.Json; 4 | using Microsoft.Extensions.Hosting; 5 | using System; 6 | using System.IO; 7 | 8 | namespace chapter11 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | CreateWebHostBuilder(args).Build().Run(); 15 | } 16 | 17 | public static IHostBuilder CreateWebHostBuilder(string[] args) => 18 | Host 19 | .CreateDefaultBuilder(args) 20 | .ConfigureWebHostDefaults(builder => 21 | { 22 | builder.UseStartup(); 23 | }); 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter07/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:54240/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter11": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:54241/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter07/chapter11.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | $(IncludeRazorContentInPack) 22 | 23 | 24 | $(IncludeRazorContentInPack) 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Chapter07/chapter11.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2016 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chapter11", "chapter11.csproj", "{4499A93A-269F-4769-879F-17A93B67E7B1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B51FC4D8-EDD6-40A6-998A-9F792B794681} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Chapter08/Configuration/OrderConfiguration.cs: -------------------------------------------------------------------------------- 1 | using chapter08.Models; 2 | using Microsoft.AspNet.OData.Builder; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace chapter08.Configuration 6 | { 7 | public class OrderConfiguration : IModelConfiguration 8 | { 9 | public void Apply(ODataModelBuilder builder, ApiVersion apiVersion) 10 | { 11 | var orders = builder.EntitySet("Orders").EntityType.HasKey(p => p.Id); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter08/Configuration/ProductConfiguration.cs: -------------------------------------------------------------------------------- 1 | using chapter08.Models; 2 | using Microsoft.AspNet.OData.Builder; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace chapter08.Configuration 6 | { 7 | public class ProductConfiguration : IModelConfiguration 8 | { 9 | public void Apply(ODataModelBuilder builder, ApiVersion apiVersion) 10 | { 11 | var products = builder.EntitySet("Products").EntityType.HasKey(p => p.Id); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter08/Controllers/OrdersController.cs: -------------------------------------------------------------------------------- 1 | using chapter08.Models; 2 | using Microsoft.AspNet.OData; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.AspNetCore.Mvc; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace chapter08.Controllers 10 | { 11 | /// 12 | /// Controller that deals with orders. 13 | /// 14 | [ApiVersion("1.0")] 15 | //[ODataRoutePrefix("Orders")] 16 | public class OrdersController : ODataController 17 | { 18 | private static Order[] _orders = new[] 19 | { 20 | new Order { Id = 1, Timestamp = DateTime.Today, Products = new List { new Product { Id = 1, Name = "A", Price = 10.5M } } } 21 | }; 22 | 23 | /// 24 | /// Retrieves all orders. 25 | /// 26 | /// All available orders. 27 | /// Orders successfully retrieved. 28 | [EnableQuery] 29 | [Produces("application/json")] 30 | [ProducesResponseType(typeof(ODataValue>), StatusCodes.Status200OK)] 31 | [HttpGet] 32 | public IQueryable Get() 33 | { 34 | return _orders.AsQueryable(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Chapter08/Controllers/PetController.cs: -------------------------------------------------------------------------------- 1 | using chapter08.Models; 2 | using Microsoft.AspNetCore.Mvc; 3 | using System.Threading.Tasks; 4 | 5 | namespace chapter08.Controllers 6 | { 7 | [Route("api/[controller]")] 8 | [ApiController] 9 | [ApiConventionType(typeof(DefaultApiConventions))] 10 | public class PetController : ControllerBase 11 | { 12 | [HttpPost] 13 | public IActionResult Post([FromBody] Pet pet) 14 | { 15 | return new JsonResult(new { Ok = true }); 16 | } 17 | 18 | [ApiConventionMethod(typeof(DefaultApiConventions), nameof(DefaultApiConventions.Put))] 19 | [HttpPut("{id}")] 20 | public async Task> PutPet(int id, Pet pet) 21 | { 22 | return Ok(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter08/Models/Model.cs: -------------------------------------------------------------------------------- 1 | namespace chapter08.Controllers.Controllers.Models 2 | { 3 | public class Model 4 | { 5 | public int Id { get; set; } 6 | public string Name { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /Chapter08/Models/Order.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace chapter08.Models 5 | { 6 | public class Order 7 | { 8 | public int Id { get; set; } 9 | public DateTime Timestamp { get; set; } 10 | public virtual List Products { get; set; } = new List(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter08/Models/Pet.cs: -------------------------------------------------------------------------------- 1 | namespace chapter08.Models 2 | { 3 | public class Pet 4 | { 5 | public string Name { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Chapter08/Models/Product.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace chapter08.Models 4 | { 5 | public class Product 6 | { 7 | public int Id { get; set; } 8 | public string Name { get; set; } 9 | public virtual List Orders { get; set; } 10 | public decimal Price { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter08/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace chapter08 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Chapter08/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:1265", 7 | "sslPort": 44309 8 | } 9 | }, 10 | "$schema": "http://json.schemastore.org/launchsettings.json", 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "http://localhost:1265/odata/v1.0/", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "chapter08": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "launchUrl": "http://localhost:5000/odata/v1.0/", 24 | "environmentVariables": { 25 | "ASPNETCORE_ENVIRONMENT": "Development" 26 | }, 27 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Chapter08/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter08/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /Chapter08/chapter08.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | chapter08.xml 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Chapter08/chapter08.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30204.135 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "chapter08", "chapter08.csproj", "{C6D2610F-930E-4044-A999-500A354C418B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {C6D2610F-930E-4044-A999-500A354C418B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {C6D2610F-930E-4044-A999-500A354C418B}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {C6D2610F-930E-4044-A999-500A354C418B}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {C6D2610F-930E-4044-A999-500A354C418B}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {77C5EE93-062C-424E-8733-1FC2027B8318} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Chapter08/chapter08.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | chapter08 5 | 6 | 7 | 8 | 9 | Controller that deals with orders. 10 | 11 | 12 | 13 | 14 | Retrieves all orders. 15 | 16 | All available orders. 17 | Orders successfully retrieved. 18 | 19 | 20 | 21 | Controller that deals with products. 22 | 23 | 24 | 25 | 26 | Retrieves all products. 27 | 28 | All available products. 29 | Products successfully retrieved. 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Chapter09/ClassLibrary/Class1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ClassLibrary 6 | { 7 | class Class1 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter09/ClassLibrary/ClassLibrary.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter09/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace chapter09.Controllers 4 | { 5 | public class HomeController : Controller 6 | { 7 | public IActionResult Index() 8 | { 9 | return View(); 10 | } 11 | 12 | public IActionResult Privacy() 13 | { 14 | return View(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter09/HelloWorldTagHelperComponent.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Razor.TagHelpers; 2 | using System.Threading.Tasks; 3 | 4 | namespace chapter09 5 | { 6 | public class HelloWorldTagHelperComponent : TagHelperComponent 7 | { 8 | public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) 9 | { 10 | if (context.TagName.ToLowerInvariant() == "head") 11 | { 12 | output.Content.AppendHtml(""); 13 | } 14 | return Task.CompletedTask; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Chapter09/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace chapter09.Models 2 | { 3 | public class ErrorViewModel 4 | { 5 | public string RequestId { get; set; } 6 | 7 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter09/MyViewComponent.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using System.Threading.Tasks; 3 | 4 | namespace chapter09 5 | { 6 | [ViewComponent(Name = "MyView")] 7 | public class MyViewComponent : ViewComponent 8 | { 9 | public async Task InvokeAsync(int parameter, bool otherParameter) 10 | { 11 | return this.Content("This is a view component"); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter09/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace chapter09 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host 15 | .CreateDefaultBuilder(args) 16 | .ConfigureWebHostDefaults(builder => 17 | { 18 | builder.UseStartup(); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter09/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:19591/", 7 | "sslPort": 44325 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter09": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter09/RazorClassLibrary/RazorClassLibrary.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | true 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Chapter09/RazorClassLibrary/wwwroot/script.js: -------------------------------------------------------------------------------- 1 | window.alert('Hello from a Razor Class Library!'); -------------------------------------------------------------------------------- /Chapter09/TimeTagHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Rendering; 2 | using Microsoft.AspNetCore.Mvc.ViewFeatures; 3 | using Microsoft.AspNetCore.Razor.TagHelpers; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Globalization; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace chapter09 11 | { 12 | public class TimeTagHelper : TagHelper 13 | { 14 | public string Format { get; set; } 15 | 16 | [ViewContext] 17 | public ViewContext ViewContext { get; set; } 18 | 19 | public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) 20 | { 21 | var content = await output.GetChildContentAsync(); 22 | var stringContent = content.GetContent(); 23 | var time = DateTime.Now.ToString(this.Format); 24 | 25 | output.TagName = "span"; 26 | output.Content.Append(string.Format(CultureInfo.InvariantCulture, stringContent, time)); 27 | 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter09/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Home Page"; 3 | } 4 | 5 | 6 | 7 |
8 |

Welcome

9 |

Learn about building Web apps with ASP.NET Core.

10 | 11 | 12 | @await Component.InvokeAsync("MyView", new { Parameter = 4, OtherParameter = true }); 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | @await Html.PartialAsync("PartialView"); 23 |
24 | -------------------------------------------------------------------------------- /Chapter09/Views/Home/PartialView.cshtml: -------------------------------------------------------------------------------- 1 | 

This is a partial view!

-------------------------------------------------------------------------------- /Chapter09/Views/Home/Privacy.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Privacy Policy"; 3 | } 4 |

@ViewData["Title"]

5 | 6 |

Use this page to detail your site's privacy policy.

7 | -------------------------------------------------------------------------------- /Chapter09/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /Chapter09/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | chapter09 - @ViewData["Title"] 7 | 8 | 9 | 10 | 11 |
12 | 22 |
23 |
24 |
25 | @RenderBody() 26 |
27 |
28 | 29 |
30 |
31 | © 2020 - chapter10 - Privacy 32 |
33 |
34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter09/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Chapter09/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using chapter09 2 | @using chapter09.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | @addTagHelper *, chapter09 5 | -------------------------------------------------------------------------------- /Chapter09/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Chapter09/chapter09.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Chapter10/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Mvc; 3 | using System; 4 | 5 | namespace chapter10.Controllers 6 | { 7 | //[LogAction] 8 | [ServiceFilter(typeof(LogFilter), Order = 1)] 9 | public class HomeController : Controller 10 | { 11 | public IActionResult Index() 12 | { 13 | return View(); 14 | } 15 | 16 | [Authorize] 17 | public IActionResult Forbidden() 18 | { 19 | return View(); 20 | } 21 | 22 | public IActionResult Privacy() 23 | { 24 | return View(); 25 | } 26 | 27 | public IActionResult Throw() 28 | { 29 | throw new Exception("Just to test the error filter!"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter10/ErrorFilter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.AspNetCore.Mvc.Filters; 3 | using System.Threading.Tasks; 4 | 5 | namespace chapter10 6 | { 7 | public sealed class ErrorFilter : IAsyncExceptionFilter 8 | { 9 | public async Task OnExceptionAsync(ExceptionContext context) 10 | { 11 | context.ExceptionHandled = true; 12 | await context.HttpContext.Response.WriteAsync($"An error occurred: {context.Exception.Message}"); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter10/FirstFilter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Filters; 2 | 3 | namespace chapter10 4 | { 5 | public class FirstFilter : IActionFilter 6 | { 7 | public void OnActionExecuting(ActionExecutingContext context) { } 8 | 9 | public void OnActionExecuted(ActionExecutedContext context) 10 | { 11 | context.HttpContext.Items["WasFirstFilterExecuted"] = true; 12 | } 13 | } 14 | 15 | public class SecondFilter : IActionFilter 16 | { 17 | public void OnActionExecuted(ActionExecutedContext context) { } 18 | 19 | public void OnActionExecuting(ActionExecutingContext context) 20 | { 21 | if (context.HttpContext.Items["WasFirstFilterExecuted"] is bool parameter && parameter) 22 | { 23 | //proceed accordingly 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter10/LogActionAttribute.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Filters; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace chapter10 6 | { 7 | public class LogActionAttribute : ActionFilterAttribute 8 | { 9 | public override void OnActionExecuting(ActionExecutingContext context) 10 | { 11 | var loggerFactory = context.HttpContext.RequestServices.GetRequiredService(); 12 | var logger = loggerFactory.CreateLogger(context.Controller.GetType()); 13 | logger.LogTrace($"Before {context.ActionDescriptor.DisplayName}"); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Chapter10/LogFilter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Filters; 2 | using Microsoft.Extensions.Logging; 3 | using System.Threading.Tasks; 4 | 5 | namespace chapter10 6 | { 7 | public class LogFilter : IAsyncActionFilter 8 | { 9 | private readonly ILoggerFactory _loggerFactory; 10 | 11 | public LogFilter(ILoggerFactory loggerFactory) 12 | { 13 | this._loggerFactory = loggerFactory; 14 | } 15 | 16 | public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) 17 | { 18 | var logger = this._loggerFactory.CreateLogger(context.Controller.GetType()); 19 | logger.LogTrace($"{context.ActionDescriptor.DisplayName} action called"); 20 | return next(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Chapter10/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace chapter10.Models 2 | { 3 | public class ErrorViewModel 4 | { 5 | public string RequestId { get; set; } 6 | 7 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter10/NotFoundAttribute.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Mvc.Filters; 3 | using System; 4 | 5 | namespace chapter10 6 | { 7 | [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)] 8 | public sealed class NotFoundAttribute : Attribute, IAlwaysRunResultFilter 9 | { 10 | public void OnResultExecuted(ResultExecutedContext context) 11 | { 12 | if (context.Result is ObjectResult objectResult && objectResult.Value == null) 13 | { 14 | objectResult.Value = new { Empty = true }; 15 | } 16 | } 17 | 18 | public void OnResultExecuting(ResultExecutingContext context) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter10/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace chapter10 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateWebHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateWebHostBuilder(string[] args) => 14 | Host 15 | .CreateDefaultBuilder(args) 16 | .ConfigureWebHostDefaults(builder => 17 | { 18 | builder.UseStartup(); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter10/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:19591/", 7 | "sslPort": 44325 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter10": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter10/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Home Page"; 3 | } 4 | 5 |
6 |

Welcome

7 |

Learn about building Web apps with ASP.NET Core.

8 |
9 | -------------------------------------------------------------------------------- /Chapter10/Views/Home/Privacy.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Privacy Policy"; 3 | } 4 |

@ViewData["Title"]

5 | 6 |

Use this page to detail your site's privacy policy.

7 | -------------------------------------------------------------------------------- /Chapter10/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /Chapter10/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | chapter10 - @ViewData["Title"] 7 | 8 | 9 | 10 | 11 |
12 | 25 |
26 |
27 |
28 | @RenderBody() 29 |
30 |
31 | 32 |
33 |
34 | © 2020 - chapter10 - Privacy 35 |
36 |
37 | 38 | 39 | -------------------------------------------------------------------------------- /Chapter10/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Chapter10/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using chapter10 2 | @using chapter10.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Chapter10/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Chapter10/chapter10.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Chapter10/chapter10.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30114.105 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "chapter10", "chapter10.csproj", "{4499A93A-269F-4769-879F-17A93B67E7B1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B51FC4D8-EDD6-40A6-998A-9F792B794681} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Chapter11/ApplicationBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using System.Linq; 3 | 4 | namespace chapter07 5 | { 6 | public static class ApplicationBuilderExtensions 7 | { 8 | public static IApplicationBuilder UseProtectedPaths(this IApplicationBuilder app, params ProtectedPathOptions[] options) 9 | { 10 | foreach (var option in options ?? Enumerable.Empty()) 11 | { 12 | app.UseMiddleware(option); 13 | } 14 | 15 | return app; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter11/ApplicationDbContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace chapter07 5 | { 6 | public class ApplicationDbContext : IdentityDbContext 7 | { 8 | public ApplicationDbContext(DbContextOptions options): base(options) 9 | { 10 | 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Chapter11/ApplicationRole.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | 3 | namespace chapter07 4 | { 5 | public class ApplicationRole : IdentityRole 6 | { 7 | 8 | } 9 | } -------------------------------------------------------------------------------- /Chapter11/ApplicationUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace chapter07 6 | { 7 | public class ApplicationUser : IdentityUser 8 | { 9 | [PersonalData] 10 | [MaxLength(50)] 11 | public string FullName { get; set; } 12 | 13 | [DataType(DataType.Date)] 14 | [PersonalData] 15 | public DateTime? Birthday { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /Chapter11/DayOfWeekAuthorizationHandler.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace chapter07 8 | { 9 | public sealed class DayOfWeekAuthorizationHandler : AuthorizationHandler 10 | { 11 | protected override Task HandleRequirementAsync( 12 | AuthorizationHandlerContext context, 13 | DayOfWeekRequirement requirement) 14 | { 15 | if ((context.Resource is DayOfWeek requestedRequirement) && (requestedRequirement == requirement.DayOfWeek)) 16 | { 17 | context.Succeed(requirement); 18 | } 19 | else 20 | { 21 | context.Fail(); 22 | } 23 | 24 | return Task.CompletedTask; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter11/DayOfWeekRequirement.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using System; 3 | 4 | namespace chapter07 5 | { 6 | public sealed class DayOfWeekRequirement : IAuthorizationRequirement 7 | { 8 | public const string Name = "DayOfWeek"; 9 | 10 | public DayOfWeekRequirement(DayOfWeek dow) 11 | { 12 | this.DayOfWeek = dow; 13 | } 14 | 15 | public DayOfWeek DayOfWeek { get; } 16 | } 17 | } -------------------------------------------------------------------------------- /Chapter11/LocalIpHandler.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Http; 3 | using System.Net; 4 | using System.Threading.Tasks; 5 | 6 | namespace chapter07 7 | { 8 | public sealed class LocalIpHandler : AuthorizationHandler 9 | { 10 | public LocalIpHandler(IHttpContextAccessor httpContextAccessor) 11 | { 12 | this.HttpContext = httpContextAccessor.HttpContext; 13 | } 14 | 15 | public HttpContext HttpContext { get; } 16 | 17 | protected override Task HandleRequirementAsync( 18 | AuthorizationHandlerContext context, 19 | LocalIpRequirement requirement) 20 | { 21 | var success = IPAddress.IsLoopback(this.HttpContext.Connection.RemoteIpAddress); 22 | 23 | if (success) 24 | { 25 | context.Succeed(requirement); 26 | } 27 | else 28 | { 29 | context.Fail(); 30 | } 31 | 32 | return Task.CompletedTask; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Chapter11/LocalIpRequirement.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace chapter07 7 | { 8 | public sealed class LocalIpRequirement : IAuthorizationRequirement 9 | { 10 | public const string Name = "LocalIp"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter11/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace chapter07.Models 4 | { 5 | public class ErrorViewModel 6 | { 7 | public string RequestId { get; set; } 8 | 9 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Chapter11/Models/LoginModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace chapter07.Models 7 | { 8 | public class LoginModel 9 | { 10 | public string Username { get; set; } 11 | public string Password { get; set; } 12 | public bool IsPersistent { get; set; } 13 | public string ReturnUrl { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter11/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace chapter07 7 | { 8 | public class Program 9 | { 10 | public static void Main(string[] args) 11 | { 12 | CreateHostBuilder(args).Build().Run(); 13 | } 14 | 15 | public static IHostBuilder CreateHostBuilder(string[] args) => 16 | Host 17 | .CreateDefaultBuilder(args) 18 | .ConfigureLogging((ctx, builder) => 19 | { 20 | if (ctx.HostingEnvironment.IsDevelopment()) 21 | { 22 | builder 23 | .AddConsole() 24 | .AddDebug(); 25 | } 26 | }) 27 | .ConfigureAppConfiguration((ctx, builder) => 28 | { 29 | 30 | }) 31 | .ConfigureWebHostDefaults(builder => 32 | { 33 | builder.UseStartup(); 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Chapter11/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:19591/", 7 | "sslPort": 44325 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter07": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter11/ProtectedPathOptions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace chapter07 8 | { 9 | public class ProtectedPathOptions 10 | { 11 | public PathString Path { get; set; } 12 | public string PolicyName { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter11/Views/Account/Create.cshtml: -------------------------------------------------------------------------------- 1 | @using chapter07.Controllers 2 | 3 | @{ 4 | ViewData["Title"] = "Create User"; 5 | } 6 | 7 | @using (Html.BeginForm(nameof(AccountController.PerformCreate), "Account", FormMethod.Post)) 8 | { 9 |
10 |
11 |

Username:

12 |

13 |

Full Name:

14 |

15 |

Birthday:

16 |

17 |

Email:

18 |

19 |

Password:

20 |

21 |

Repeat Password:

22 |

23 | 24 |
25 | } -------------------------------------------------------------------------------- /Chapter11/Views/Account/Forbidden.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Forbidden"; 3 | } 4 |

Forbidden!

-------------------------------------------------------------------------------- /Chapter11/Views/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | @using chapter07.Controllers 2 | @model chapter07.Models.LoginModel 3 | 4 | @{ 5 | ViewData["Title"] = "Login"; 6 | } 7 | 8 | 9 | @using (Html.BeginForm(nameof(AccountController.PerformLogin), "Account", FormMethod.Post)) 10 | { 11 | @*
12 |

Username:

13 |

14 |

Password:

15 |

16 |

Remember me:

17 | 18 | 19 |
*@ 20 |
21 |

Username:

22 |

@Html.TextBoxFor(x => x.Username)

23 |

Password:

24 |

@Html.PasswordFor(x => x.Password)

25 |

Remember me: @Html.CheckBoxFor(x => x.IsPersistent, true)

26 | @Html.HiddenFor(x => x.ReturnUrl) 27 | 28 |
29 | } 30 | -------------------------------------------------------------------------------- /Chapter11/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Home Page"; 3 | } 4 | 5 |
6 |

Welcome

7 |

Learn about building Web apps with ASP.NET Core.

8 |
9 | -------------------------------------------------------------------------------- /Chapter11/Views/Home/Privacy.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Privacy Policy"; 3 | } 4 |

@ViewData["Title"]

5 | 6 |

Use this page to detail your site's privacy policy.

7 | -------------------------------------------------------------------------------- /Chapter11/Views/Home/Private.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Private"; 3 | } 4 |

This is a private view!

5 |

User: @User.Identity.Name

6 | -------------------------------------------------------------------------------- /Chapter11/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /Chapter11/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /Chapter11/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Chapter11/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using chapter07 2 | @using chapter07.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Chapter11/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Chapter11/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter11/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "ConnectionStrings": { 10 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-chapter07-2AF3F755-0DFD-4E20-BBA4-9B9C3F56378B;Trusted_Connection=True;MultipleActiveResultSets=true" 11 | }, 12 | "AllowedHosts": "*" 13 | } 14 | -------------------------------------------------------------------------------- /Chapter11/chapter07.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | all 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Chapter11/chapter07.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2016 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chapter07", "chapter07.csproj", "{4499A93A-269F-4769-879F-17A93B67E7B1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B51FC4D8-EDD6-40A6-998A-9F792B794681} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Chapter11/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Modern-Web-Development-with-ASP.NET-Core-3-Second-Edition/aa8b7b7ce02099e511fde07f986178243bffd6a0/Chapter11/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Chapter11/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | // for details on configuring this project to bundle and minify static web assets. 3 | 4 | // Write your JavaScript code. 5 | -------------------------------------------------------------------------------- /Chapter11/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2018 Twitter, Inc. 4 | Copyright (c) 2011-2018 The Bootstrap Authors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Chapter11/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) .NET Foundation. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | these files except in compliance with the License. You may obtain a copy of the 5 | License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software distributed 10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | specific language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /Chapter11/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Chapter12/FileLoggerProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace chapter12 8 | { 9 | public sealed class FileLoggerProvider : ILoggerProvider 10 | { 11 | private readonly Func _func; 12 | 13 | public FileLoggerProvider(Func func) 14 | { 15 | this._func = func; 16 | } 17 | 18 | public FileLoggerProvider(LogLevel minimumLogLevel) : 19 | this((category, logLevel) => logLevel >= minimumLogLevel) 20 | { 21 | } 22 | 23 | public ILogger CreateLogger(string categoryName) 24 | { 25 | return new FileLogger(categoryName, this._func); 26 | } 27 | 28 | public void Dispose() 29 | { 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter12/LogElapsedUrlEventSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.Tracing; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace chapter12 8 | { 9 | [EventSource(Name = SourceName)] 10 | public sealed class LogElapsedUrlEventSource : EventSource 11 | { 12 | private readonly EventCounter _counter; 13 | 14 | public static readonly LogElapsedUrlEventSource Instance = new LogElapsedUrlEventSource(); 15 | 16 | private const int SourceId = 1; 17 | private const string SourceName = "LogElapsedUrl"; 18 | 19 | private LogElapsedUrlEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) 20 | { 21 | this._counter = new EventCounter(SourceName, this); 22 | } 23 | 24 | [Event(SourceId, Message = "Elapsed Time for URL {0}: {1}", Level = EventLevel.Informational)] 25 | public void LogElapsed(string url, float time) 26 | { 27 | this.WriteEvent(SourceId, url, time); 28 | this._counter.WriteMetric(time); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Chapter12/LoggerFactoryExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using System; 3 | 4 | namespace chapter12 5 | { 6 | public static class LoggerFactoryExtensions 7 | { 8 | public static ILoggerFactory AddFile(this ILoggerFactory loggerFactory, Func func) 9 | { 10 | loggerFactory.AddProvider(new FileLoggerProvider(func)); 11 | return loggerFactory; 12 | } 13 | 14 | public static ILoggerFactory AddFile(this ILoggerFactory loggerFactory, LogLevel minimumLogLevel) 15 | { 16 | return AddFile(loggerFactory, (category, logLevel) => logLevel >= minimumLogLevel); 17 | } 18 | 19 | public static ILoggingBuilder AddFile(this ILoggingBuilder loggingBuilder, Func func) 20 | { 21 | return loggingBuilder.AddProvider(new FileLoggerProvider(func)); 22 | } 23 | 24 | public static ILoggingBuilder AddFile(this ILoggingBuilder loggingBuilder, LogLevel minimumLogLevel) 25 | { 26 | return AddFile(loggingBuilder, (category, logLevel) => logLevel >= minimumLogLevel); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter12/LoggingMiddleware.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.Extensions.Logging; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace chapter12 9 | { 10 | public class LoggingMiddleware 11 | { 12 | private readonly RequestDelegate _next; 13 | private readonly ILoggerFactory _loggerFactory; 14 | 15 | public LoggingMiddleware(RequestDelegate next, ILoggerFactory loggerFactory) 16 | { 17 | this._next = next; 18 | this._loggerFactory = loggerFactory; 19 | } 20 | 21 | public async Task InvokeAsync(HttpContext context) 22 | { 23 | var logger = this._loggerFactory.CreateLogger(); 24 | using (logger.BeginScope(this)) 25 | { 26 | logger.LogInformation("Before request"); 27 | await this._next.Invoke(context); 28 | logger.LogInformation("After request"); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter12/MiddlewareExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Http; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace chapter12 9 | { 10 | public static class MiddlewareExtensions 11 | { 12 | public static IApplicationBuilder UseConventionalMiddleware(this IApplicationBuilder builder, params object[] args) 13 | { 14 | return builder.UseMiddleware(args); 15 | } 16 | 17 | public static IApplicationBuilder UseFactoryActivatedMiddleware(this IApplicationBuilder builder, params object[] args) where T : IMiddleware 18 | { 19 | return builder.UseMiddleware(args); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter12/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace chapter12.Models 2 | { 3 | public class ErrorViewModel 4 | { 5 | public string RequestId { get; set; } 6 | 7 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter12/MyDbContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Design; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.Configuration.Json; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | 8 | namespace chapter12 9 | { 10 | public class MyDbContext : DbContext, IDesignTimeDbContextFactory 11 | { 12 | public MyDbContext(DbContextOptions options) : base(options) 13 | { 14 | } 15 | 16 | public MyDbContext() 17 | { 18 | 19 | } 20 | 21 | public MyDbContext CreateDbContext(string[] args) 22 | { 23 | var configuration = new ConfigurationBuilder() 24 | .SetBasePath(Directory.GetCurrentDirectory()) 25 | .AddJsonFile("appsettings.json", false, true) 26 | .Build(); 27 | 28 | var connectionString = configuration.GetConnectionString("DefaultConnection"); 29 | var options = new DbContextOptionsBuilder() 30 | .UseSqlServer(connectionString) 31 | .Options; 32 | 33 | return new MyDbContext(options); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Chapter12/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | using Microsoft.Extensions.Logging; 4 | using System.Diagnostics; 5 | 6 | namespace chapter12 7 | { 8 | public class Program 9 | { 10 | public static void Main(string[] args) 11 | { 12 | CreateHostBuilder(args).Build().Run(); 13 | } 14 | 15 | public static IHostBuilder CreateHostBuilder(string[] args) => 16 | Host 17 | .CreateDefaultBuilder(args) 18 | .ConfigureLogging(builder => 19 | { 20 | builder 21 | .AddConsole() 22 | .AddDebug(); 23 | 24 | }) 25 | .ConfigureWebHostDefaults(builder => 26 | { 27 | Activity.DefaultIdFormat = ActivityIdFormat.W3C; 28 | Activity.ForceDefaultIdFormat = true; 29 | 30 | builder.UseIISIntegration(); 31 | builder.UseKestrel(options => 32 | { 33 | options.AllowSynchronousIO = true; 34 | }); 35 | builder.UseStartup(); 36 | }); 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Chapter12/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:54240/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter11": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:54241/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter12/TraceDiagnosticListener.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.Extensions.DiagnosticAdapter; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace chapter12 9 | { 10 | public class TraceDiagnosticListener 11 | { 12 | [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareStarting")] 13 | public virtual void OnMiddlewareStarting(HttpContext httpContext, string name) 14 | { 15 | //called when the middleware is starting 16 | } 17 | 18 | [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareException")] 19 | public virtual void OnMiddlewareException(Exception exception, string name) 20 | { 21 | //called when there is an exception while processing a middleware component 22 | } 23 | 24 | [DiagnosticName("Microsoft.AspNetCore.MiddlewareAnalysis.MiddlewareFinished")] 25 | public virtual void OnMiddlewareFinished(HttpContext httpContext, string name) 26 | { 27 | //called when the middleware execution finishes 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter12/TraceIdentifierMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net.Http; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace chapter12 10 | { 11 | public class TraceIdentifierMessageHandler : DelegatingHandler 12 | { 13 | private readonly IHttpContextAccessor _httpContextAccessor; 14 | 15 | public TraceIdentifierMessageHandler(IHttpContextAccessor httpContextAccessor) 16 | { 17 | this._httpContextAccessor = httpContextAccessor; 18 | } 19 | 20 | protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 21 | { 22 | var httpContext = this._httpContextAccessor.HttpContext; 23 | request.Headers.Add("Request-Id", httpContext.TraceIdentifier); 24 | request.Headers.Add("X-SessionId", httpContext.Session.Id); 25 | 26 | return base.SendAsync(request, cancellationToken); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Chapter12/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 

Hello, World!

-------------------------------------------------------------------------------- /Chapter12/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /Chapter12/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | chapter11 - @ViewData["Title"] 7 | 8 | 9 | 10 | 11 | @RenderBody() 12 | 13 | 14 | -------------------------------------------------------------------------------- /Chapter12/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Chapter12/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using chapter12 2 | @using chapter12.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Chapter12/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Chapter12/WebHealthCheck.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Diagnostics.HealthChecks; 2 | using System; 3 | using System.Net; 4 | using System.Net.Http; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace chapter12 9 | { 10 | public class WebHealthCheck : IHealthCheck 11 | { 12 | public WebHealthCheck(string url) 13 | { 14 | if (string.IsNullOrWhiteSpace(url)) 15 | { 16 | throw new ArgumentNullException(nameof(url)); 17 | } 18 | 19 | this.Url = url; 20 | } 21 | 22 | public string Url { get; } 23 | 24 | public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default(CancellationToken)) 25 | { 26 | var client = new HttpClient(); 27 | var response = await client.GetAsync(this.Url); 28 | 29 | if (response.StatusCode < HttpStatusCode.BadRequest) 30 | { 31 | return HealthCheckResult.Healthy("The URL is up and running"); 32 | } 33 | 34 | return HealthCheckResult.Unhealthy("The URL is inaccessible"); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /Chapter12/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=master;" 4 | } 5 | } -------------------------------------------------------------------------------- /Chapter12/chapter12.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2016 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chapter12", "chapter12.csproj", "{4499A93A-269F-4769-879F-17A93B67E7B1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B51FC4D8-EDD6-40A6-998A-9F792B794681} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Chapter13/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace chapter13.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | public IActionResult Index() 12 | { 13 | return View(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter13/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace chapter13.Models 2 | { 3 | public class ErrorViewModel 4 | { 5 | public string RequestId { get; set; } 6 | 7 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter13/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration.Json; 4 | using Microsoft.Extensions.Hosting; 5 | using System; 6 | using System.IO; 7 | 8 | namespace chapter13 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | CreateHostBuilder(args).Build().Run(); 15 | } 16 | 17 | public static IHostBuilder CreateHostBuilder(string[] args) => 18 | Host 19 | .CreateDefaultBuilder(args) 20 | .ConfigureWebHostDefaults(builder => 21 | { 22 | builder.UseStartup(); 23 | }); 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter13/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:54240/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter13": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:54241/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter13/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.AspNetCore.Mvc.ApplicationModels; 6 | using Microsoft.Extensions.Hosting; 7 | 8 | namespace chapter13 9 | { 10 | public class Startup 11 | { 12 | public Startup(IConfiguration configuration) 13 | { 14 | this.Configuration = configuration; 15 | } 16 | 17 | public IConfiguration Configuration { get; } 18 | 19 | public void ConfigureServices(IServiceCollection services) 20 | { 21 | services.AddMvc(); 22 | } 23 | 24 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 25 | { 26 | if (env.IsDevelopment()) 27 | { 28 | app.UseDeveloperExceptionPage(); 29 | } 30 | 31 | app.UseAuthentication(); 32 | app.UseRouting(); 33 | app.UseEndpoints(endpoints => 34 | { 35 | endpoints.MapDefaultControllerRoute(); 36 | }); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Chapter13/UnitTests/CalculatorTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Xunit; 5 | 6 | namespace UnitTests 7 | { 8 | public class CalculatorTest 9 | { 10 | [Theory] 11 | [InlineData(1, 2, 3)] 12 | [InlineData(1, 1, 2)] 13 | public void Calculate(int a, int b, int c) 14 | { 15 | Assert.Equal(c, a + b); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter13/UnitTests/IMyFeature.cs: -------------------------------------------------------------------------------- 1 | namespace UnitTests 2 | { 3 | internal interface IMyFeature 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Chapter13/UnitTests/IMyService.cs: -------------------------------------------------------------------------------- 1 | namespace UnitTests 2 | { 3 | internal interface IMyService 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Chapter13/UnitTests/IntegrationTests.cs: -------------------------------------------------------------------------------- 1 | using chapter13; 2 | using Microsoft.AspNetCore.Mvc.Testing; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Xunit; 8 | 9 | namespace UnitTests 10 | { 11 | public class IntegrationTests : IClassFixture> 12 | { 13 | private readonly WebApplicationFactory _factory; 14 | 15 | public IntegrationTests(WebApplicationFactory factory) 16 | { 17 | this._factory = factory; 18 | } 19 | 20 | [Theory] 21 | [InlineData("/")] 22 | public async Task CanCallHome(string url) 23 | { 24 | //Arrange 25 | var client = this._factory.CreateClient(); 26 | 27 | //Act 28 | var response = await client.GetAsync(url); 29 | 30 | //Assert 31 | response.EnsureSuccessStatusCode(); 32 | 33 | var content = await response.Content.ReadAsStringAsync(); 34 | 35 | Assert.Contains("Welcome", content); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter13/UnitTests/MyCustomWebApplicationFactory.cs: -------------------------------------------------------------------------------- 1 | using chapter13; 2 | using Microsoft.AspNetCore.Mvc.Testing; 3 | using Microsoft.Extensions.DependencyInjection.Extensions; 4 | using Microsoft.Extensions.Hosting; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | 9 | namespace UnitTests 10 | { 11 | class MyCustomWebApplicationFactory : WebApplicationFactory 12 | { 13 | protected override IHostBuilder CreateHostBuilder() 14 | { 15 | return base 16 | .CreateHostBuilder() 17 | .ConfigureServices(services => 18 | { 19 | services.RemoveAll(); 20 | }); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter13/UnitTests/MyFeatureImplementation.cs: -------------------------------------------------------------------------------- 1 | namespace UnitTests 2 | { 3 | internal class MyFeatureImplementation : IMyFeature 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Chapter13/UnitTests/MyServiceImplementation.cs: -------------------------------------------------------------------------------- 1 | namespace UnitTests 2 | { 3 | internal class MyServiceImplementation : IMyService 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Chapter13/UnitTests/MyTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Xunit; 5 | 6 | namespace UnitTests 7 | { 8 | public class MyTests : IClassFixture 9 | { 10 | private readonly SharedData _data; 11 | 12 | public MyTests(SharedData data) 13 | { 14 | this._data = data; 15 | } 16 | 17 | [Fact(Skip = "Not implemented yet")] 18 | public void TestSomething() 19 | { 20 | //will be ignored 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Chapter13/UnitTests/RequestCookieCollection.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace UnitTests 8 | { 9 | class RequestCookieCollection : IRequestCookieCollection 10 | { 11 | private readonly Dictionary _cookies; 12 | 13 | public RequestCookieCollection(Dictionary cookies) 14 | { 15 | this._cookies = cookies; 16 | } 17 | 18 | public string this[string key] => _cookies[key]; 19 | 20 | public int Count => _cookies.Count; 21 | 22 | public ICollection Keys => _cookies.Keys; 23 | 24 | public bool ContainsKey(string key) 25 | { 26 | return _cookies.ContainsKey(key); 27 | } 28 | 29 | public IEnumerator> GetEnumerator() 30 | { 31 | return _cookies.GetEnumerator(); 32 | } 33 | 34 | public bool TryGetValue(string key, out string value) 35 | { 36 | return _cookies.TryGetValue(key, out value); 37 | } 38 | 39 | IEnumerator IEnumerable.GetEnumerator() 40 | { 41 | return this.GetEnumerator(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Chapter13/UnitTests/SharedData.cs: -------------------------------------------------------------------------------- 1 | namespace UnitTests 2 | { 3 | public class SharedData 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Chapter13/UnitTests/UITests.cs: -------------------------------------------------------------------------------- 1 | using OpenQA.Selenium; 2 | using OpenQA.Selenium.Chrome; 3 | using OpenQA.Selenium.Support.UI; 4 | using System; 5 | using Xunit; 6 | 7 | namespace UnitTests 8 | { 9 | public class UITests 10 | { 11 | [Fact] 12 | public void CanFindSearchButton() 13 | { 14 | using (var driver = (IWebDriver)new ChromeDriver(Environment.CurrentDirectory)) 15 | { 16 | driver 17 | .Navigate() 18 | .GoToUrl("http://www.google.com"); 19 | 20 | var elm = driver.FindElement(By.Name("q")); 21 | 22 | Assert.NotNull(elm); 23 | 24 | elm.SendKeys("asp.net"); 25 | 26 | var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5)); 27 | 28 | var btn = wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementIsVisible(By.Name("btnK"))); 29 | 30 | Assert.NotNull(btn); 31 | 32 | btn.Click(); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Chapter13/UnitTests/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace UnitTests 5 | { 6 | public class UnitTest1 7 | { 8 | [Fact] 9 | public void Test1() 10 | { 11 | 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter13/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 

Welcome to testing!

-------------------------------------------------------------------------------- /Chapter13/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /Chapter13/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | chapter11 - @ViewData["Title"] 7 | 8 | 9 | 10 | 11 | @RenderBody() 12 | 13 | 14 | -------------------------------------------------------------------------------- /Chapter13/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Chapter13/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using chapter13 2 | @using chapter13.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Chapter13/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Chapter13/chapter13.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | $(IncludeRazorContentInPack) 22 | 23 | 24 | $(IncludeRazorContentInPack) 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Chapter14/ClientApp/Algebra.js: -------------------------------------------------------------------------------- 1 | module.exports = function (callback, a, b) { 2 | var result = a + b; 3 | callback(null, result); 4 | }; -------------------------------------------------------------------------------- /Chapter14/ClientApp/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const port = 3000; 4 | 5 | process.title = 'chapter14'; 6 | 7 | app.get('/', (req, res) => res.send('Hello World!')); 8 | 9 | app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`)); -------------------------------------------------------------------------------- /Chapter14/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration.Json; 4 | using Microsoft.Extensions.Hosting; 5 | using System; 6 | using System.IO; 7 | 8 | namespace chapter14 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | CreateHostBuilder(args).Build().Run(); 15 | } 16 | 17 | public static IHostBuilder CreateHostBuilder(string[] args) => 18 | Host 19 | .CreateDefaultBuilder(args) 20 | .ConfigureWebHostDefaults(builder => 21 | { 22 | builder.UseStartup(); 23 | }); 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter14/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:54240/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter14": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "launchUrl": "https://localhost:5001", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | }, 25 | "applicationUrl": "http://localhost:5000;https://localhost:5001" 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Chapter14/chapter14.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Chapter14/chapter14.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30114.105 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "chapter14", "chapter14.csproj", "{4499A93A-269F-4769-879F-17A93B67E7B1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B51FC4D8-EDD6-40A6-998A-9F792B794681} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Chapter14/libman.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "defaultProvider": "cdnjs", 4 | "libraries": [ 5 | { 6 | "library": "jquery@3.4.1", 7 | "destination": "wwwroot/lib" 8 | }, 9 | { 10 | "library": "jquery-validation-unobtrusive@3.2.11", 11 | "destination": "wwwroot/lib" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /Chapter14/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chapter14", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "", 6 | "scripts": { 7 | "start": "node ClientApp/index.js", 8 | "stop": "node node_modules/pkill/index.js --signal SIGINT chapter14" 9 | }, 10 | "author": "Ricardo Peres", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "4.19.2", 14 | "pkill": "2.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter15/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using CoreProfiler; 6 | using Microsoft.AspNetCore.Mvc; 7 | 8 | namespace chapter15.Controllers 9 | { 10 | public class HomeController : Controller 11 | { 12 | public IActionResult Index() 13 | { 14 | using (ProfilingSession.Current.Step("/Home")) 15 | { 16 | using (ProfilingSession.Current.Step(() => "Return View")) 17 | { 18 | return View(); 19 | } 20 | } 21 | 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter15/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace chapter15.Models 2 | { 3 | public class ErrorViewModel 4 | { 5 | public string RequestId { get; set; } 6 | 7 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter15/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration.Json; 4 | using Microsoft.Extensions.Hosting; 5 | using System; 6 | using System.IO; 7 | 8 | namespace chapter15 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | CreateHostBuilder(args).Build().Run(); 15 | } 16 | 17 | public static IHostBuilder CreateHostBuilder(string[] args) => 18 | Host 19 | .CreateDefaultBuilder(args) 20 | .ConfigureWebHostDefaults(builder => 21 | { 22 | builder.UseStartup(); 23 | }); 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter15/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:54240/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter15": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:54241/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter15/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 

Welcome to testing!

-------------------------------------------------------------------------------- /Chapter15/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /Chapter15/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | chapter15 - @ViewData["Title"] 7 | 8 | 9 | @RenderBody() 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Chapter15/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Chapter15/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using chapter15 2 | @using chapter15.Models 3 | @using StackExchange.Profiling 4 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 5 | @addTagHelper *, MiniProfiler.AspNetCore.Mvc 6 | -------------------------------------------------------------------------------- /Chapter15/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Chapter15/chapter15.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | PreserveNewest 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter15/coreprofiler.json: -------------------------------------------------------------------------------- 1 | { 2 | "circularBufferSize": 200, 3 | "filters": [ 4 | { 5 | "key": "/coreprofiler", 6 | "value": "/coreprofiler", 7 | "type": "CoreProfiler.ProfilingFilters.NameContainsProfilingFilter, CoreProfiler" 8 | }, 9 | { 10 | "key": "static files", 11 | "value": "ico,jpg,js,css,svg,json,ttf,woff,woff2,eot", 12 | "type": "CoreProfiler.ProfilingFilters.FileExtensionProfilingFilter, CoreProfiler" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /Chapter16/Controllers/ChatController.cs: -------------------------------------------------------------------------------- 1 | using chapter16.Hubs; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.AspNetCore.SignalR; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace chapter16.Controllers 10 | { 11 | public class ChatController : Controller 12 | { 13 | private readonly IHubContext _context; 14 | 15 | public ChatController(IHubContext context) 16 | { 17 | this._context = context; 18 | } 19 | 20 | [HttpGet("Send/{message}")] 21 | public async Task Send(string message) 22 | { 23 | await this._context.Clients.All.SendAsync("message", this.User.Identity.Name, message); 24 | return Json(new { Message = message }); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter16/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace chapter16.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | public IActionResult Index() 12 | { 13 | return View(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter16/Hubs/ChatHub.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.SignalR; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace chapter16.Hubs 8 | { 9 | public class ChatHub : Hub 10 | { 11 | public async Task Send(string message) 12 | { 13 | var value = this.Context.GetHttpContext().Request.Query["key"].SingleOrDefault(); 14 | var connectionId = this.Context.ConnectionId; 15 | 16 | await this.Clients.All.SendAsync("message", this.Context.User.Identity.Name, message); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter16/Hubs/TimerHub.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.SignalR; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace chapter16.Hubs 8 | { 9 | public class TimerHub : Hub 10 | { 11 | public async Task Notify() 12 | { 13 | await this.Clients.All.SendAsync("notify"); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter16/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace chapter16.Models 2 | { 3 | public class ErrorViewModel 4 | { 5 | public string RequestId { get; set; } 6 | 7 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter16/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration.Json; 4 | using Microsoft.Extensions.Hosting; 5 | using System; 6 | using System.IO; 7 | 8 | namespace chapter16 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | CreateHostBuilder(args).Build().Run(); 15 | } 16 | 17 | public static IHostBuilder CreateHostBuilder(string[] args) => 18 | Host 19 | .CreateDefaultBuilder(args) 20 | .ConfigureWebHostDefaults(builder => 21 | { 22 | builder.UseStartup(); 23 | }); 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter16/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:54240/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter16": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:54241/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter16/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 
2 |
3 |

Message:

4 |

5 |
-------------------------------------------------------------------------------- /Chapter16/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /Chapter16/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Chapter16/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using chapter16 2 | @using chapter16.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Chapter16/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Chapter16/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chapter16", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "", 6 | "scripts": {}, 7 | "author": "", 8 | "license": "ISC", 9 | "dependencies": { 10 | "@microsoft/signalr": "^7.0.7", 11 | "@aspnet/signalr-protocol-msgpack": "^1.1.0", 12 | "msgpack5": "^4.5.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter17/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 |

Sorry, there's nothing at this address.

9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /Chapter17/Data/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace chapter17.Data 4 | { 5 | public class WeatherForecast 6 | { 7 | public DateTime Date { get; set; } 8 | 9 | public int TemperatureC { get; set; } 10 | 11 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 12 | 13 | public string Summary { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter17/Data/WeatherForecastService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | 5 | namespace chapter17.Data 6 | { 7 | public class WeatherForecastService 8 | { 9 | private static readonly string[] Summaries = new[] 10 | { 11 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 12 | }; 13 | 14 | public Task GetForecastAsync(DateTime startDate) 15 | { 16 | var rng = new Random(); 17 | return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast 18 | { 19 | Date = startDate.AddDays(index), 20 | TemperatureC = rng.Next(-20, 55), 21 | Summary = Summaries[rng.Next(Summaries.Length)] 22 | }).ToArray()); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter17/Pages/Clock.razor: -------------------------------------------------------------------------------- 1 | 

Clock

2 | 3 | @code { 4 | [Parameter] 5 | public TimeSpan Time { get; set; } 6 | } 7 |

Time: @Time

8 | -------------------------------------------------------------------------------- /Chapter17/Pages/ContainerComponent.razor: -------------------------------------------------------------------------------- 1 | @code { 2 | [Parameter] 3 | public RenderFragment ChildContent { get; set; } 4 | } 5 | 6 |
7 |     
8 |     @ChildContent
9 | 
-------------------------------------------------------------------------------- /Chapter17/Pages/Counter.razor: -------------------------------------------------------------------------------- 1 | @page "/counter" 2 | 3 |

Counter

4 | 5 |

Current count: @currentCount

6 | 7 | 8 | 9 | @code { 10 | private int currentCount = 0; 11 | 12 | private void IncrementCount() 13 | { 14 | currentCount++; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter17/Pages/Error.razor: -------------------------------------------------------------------------------- 1 | @page "/error" 2 | 3 | 4 |

Error.

5 |

An error occurred while processing your request.

6 | 7 |

Development Mode

8 |

9 | Swapping to Development environment will display more detailed information about the error that occurred. 10 |

11 |

12 | The Development environment shouldn't be enabled for deployed applications. 13 | It can result in displaying sensitive information from exceptions to end users. 14 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 15 | and restarting the app. 16 |

-------------------------------------------------------------------------------- /Chapter17/Pages/FetchData.razor: -------------------------------------------------------------------------------- 1 | @page "/fetchdata" 2 | 3 | @using chapter17.Data 4 | @inject WeatherForecastService ForecastService 5 | 6 |

Weather forecast

7 | 8 |

This component demonstrates fetching data from a service.

9 | 10 | @if (forecasts == null) 11 | { 12 |

Loading...

13 | } 14 | else 15 | { 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | @foreach (var forecast in forecasts) 27 | { 28 | 29 | 30 | 31 | 32 | 33 | 34 | } 35 | 36 |
DateTemp. (C)Temp. (F)Summary
@forecast.Date.ToShortDateString()@forecast.TemperatureC@forecast.TemperatureF@forecast.Summary
37 | } 38 | 39 | @code { 40 | private WeatherForecast[] forecasts; 41 | 42 | protected override async Task OnInitializedAsync() 43 | { 44 | forecasts = await ForecastService.GetForecastAsync(DateTime.Now); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Chapter17/Pages/Index.razor.cs: -------------------------------------------------------------------------------- 1 | using chapter17.Shared; 2 | using Microsoft.AspNetCore.Components; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace chapter17.Pages 9 | { 10 | //[Route("/")] 11 | [Layout(typeof(MainLayout))] 12 | public partial class Index : ComponentBase 13 | { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter17/Pages/Page.razor: -------------------------------------------------------------------------------- 1 | @page "/Page/{PageNumber:int}" 2 | 3 | @code 4 | { 5 | [Parameter] 6 | public int PageNumber { get; set; } 7 | } 8 | 9 |

Page: @PageNumber

-------------------------------------------------------------------------------- /Chapter17/Pages/Search.razor: -------------------------------------------------------------------------------- 1 | @page "/Search/{product}" 2 | 3 | @code 4 | { 5 | [Parameter] 6 | public string Product { get; set; } 7 | } 8 |

Searching for: @Product

-------------------------------------------------------------------------------- /Chapter17/Pages/SimpleComponent.razor: -------------------------------------------------------------------------------- 1 | 

SimpleComponent

2 | @implements IDisposable 3 | 4 | @code { 5 | [Parameter] 6 | public string Text { get; set; } = "Initial value"; 7 | 8 | [Parameter(CaptureUnmatchedValues = true)] 9 | public Dictionary Attributes { get; set; } = new Dictionary(); 10 | 11 | 12 | public void Dispose() 13 | { 14 | //dispose the component 15 | //this method will be called automatically by the framework 16 | } 17 | } 18 |

Text: @Text

19 |

Attributes:

20 |
21 | @string.Join("\n", Attributes.Select((kv) => $"{kv.Key}={kv.Value}"))
22 | 
-------------------------------------------------------------------------------- /Chapter17/Pages/SimpleComponent.razor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace chapter17.Pages 8 | { 9 | public partial class SimpleComponent : ComponentBase 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Chapter17/Pages/Timer.razor: -------------------------------------------------------------------------------- 1 | @using System 2 | @using System.Timers 3 | 4 | @implements IDisposable 5 | 6 | @code 7 | { 8 | private System.Timers.Timer _timer; 9 | 10 | [Parameter] 11 | public TimeSpan Delay { get; set; } 12 | 13 | [Parameter] 14 | public Action OnElapsed { get; set; } 15 | 16 | [Parameter] 17 | public bool Repeat { get; set; } 18 | 19 | protected override void OnParametersSet() 20 | { 21 | this._timer = new System.Timers.Timer(this.Delay.TotalMilliseconds); 22 | this._timer.Elapsed += this.OnTimerElapsed; 23 | this._timer.Enabled = true; 24 | 25 | base.OnParametersSet(); 26 | } 27 | 28 | private void OnTimerElapsed(object sender, ElapsedEventArgs e) 29 | { 30 | this.OnElapsed?.Invoke(); 31 | 32 | if (!this.Repeat) 33 | { 34 | this._timer.Elapsed -= this.OnTimerElapsed; 35 | this._timer.Enabled = false; 36 | } 37 | } 38 | 39 | void IDisposable.Dispose() 40 | { 41 | if (this._timer != null) 42 | { 43 | this._timer.Dispose(); 44 | this._timer = null; 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /Chapter17/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Hosting; 10 | using Microsoft.Extensions.Logging; 11 | 12 | namespace chapter17 13 | { 14 | public class Program 15 | { 16 | public static void Main(string[] args) 17 | { 18 | CreateHostBuilder(args).Build().Run(); 19 | } 20 | 21 | public static IHostBuilder CreateHostBuilder(string[] args) => 22 | Host.CreateDefaultBuilder(args) 23 | .ConfigureWebHostDefaults(webBuilder => 24 | { 25 | webBuilder.UseStartup(); 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter17/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:31340", 7 | "sslPort": 44303 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter17": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Chapter17/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 | 6 | 7 |
8 |
9 | About 10 |
11 | 12 |
13 |
This is a layout
14 |
Body goes here:
15 | @Body 16 |
17 |
18 | -------------------------------------------------------------------------------- /Chapter17/Shared/SurveyPrompt.razor: -------------------------------------------------------------------------------- 1 |  11 | 12 | @code { 13 | // Demonstrates how a parent component can supply parameters 14 | [Parameter] 15 | public string Title { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter17/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Authorization 3 | @using Microsoft.AspNetCore.Components.Authorization 4 | @using Microsoft.AspNetCore.Components.Forms 5 | @using Microsoft.AspNetCore.Components.Routing 6 | @using Microsoft.AspNetCore.Components.Web 7 | @using Microsoft.JSInterop 8 | @using chapter17 9 | @using chapter17.Shared 10 | -------------------------------------------------------------------------------- /Chapter17/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter17/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /Chapter17/chapter17.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Chapter17/chapter17.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30128.74 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chapter17", "chapter17.csproj", "{211E606A-EAC3-4F7A-88F8-0D3383F44B7A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {211E606A-EAC3-4F7A-88F8-0D3383F44B7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {211E606A-EAC3-4F7A-88F8-0D3383F44B7A}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {211E606A-EAC3-4F7A-88F8-0D3383F44B7A}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {211E606A-EAC3-4F7A-88F8-0D3383F44B7A}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {DA1872F6-BBE9-4014-83B8-CD57BCCB9C93} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Chapter17/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /Chapter17/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Modern-Web-Development-with-ASP.NET-Core-3-Second-Edition/aa8b7b7ce02099e511fde07f986178243bffd6a0/Chapter17/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /Chapter17/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Modern-Web-Development-with-ASP.NET-Core-3-Second-Edition/aa8b7b7ce02099e511fde07f986178243bffd6a0/Chapter17/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /Chapter17/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Modern-Web-Development-with-ASP.NET-Core-3-Second-Edition/aa8b7b7ce02099e511fde07f986178243bffd6a0/Chapter17/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /Chapter17/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Modern-Web-Development-with-ASP.NET-Core-3-Second-Edition/aa8b7b7ce02099e511fde07f986178243bffd6a0/Chapter17/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /Chapter17/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Modern-Web-Development-with-ASP.NET-Core-3-Second-Edition/aa8b7b7ce02099e511fde07f986178243bffd6a0/Chapter17/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Chapter18/Areas/Admin/Controllers/ManageController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace chapter18.Admin.Controllers 8 | { 9 | [Area("Admin")] 10 | public class ManageController : Controller 11 | { 12 | public IActionResult Index() 13 | { 14 | return View(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter18/Areas/Admin/Views/Manage/Index.cshtml: -------------------------------------------------------------------------------- 1 | 

Hello, world from admin!

-------------------------------------------------------------------------------- /Chapter18/BackgroundHostedService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Hosting; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace chapter18 9 | { 10 | public class BackgroundHostedService : BackgroundService 11 | { 12 | protected override Task ExecuteAsync(CancellationToken cancellationToken) 13 | { 14 | while (!cancellationToken.IsCancellationRequested) 15 | { 16 | //do something 17 | 18 | Task.Delay(1000, cancellationToken); 19 | } 20 | 21 | return Task.CompletedTask; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter18/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace chapter18.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | public IActionResult Index() 12 | { 13 | return View(); 14 | } 15 | 16 | public IActionResult Error() 17 | { 18 | return View(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter18/Controllers/WeatherController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace chapter18.Controllers 8 | { 9 | public class WeatherController : Controller 10 | { 11 | private readonly IOpenWeatherMap _openWeatherMap; 12 | 13 | public WeatherController(IOpenWeatherMap openWeatherMap) 14 | { 15 | this._openWeatherMap = openWeatherMap; 16 | } 17 | 18 | [HttpGet("[controller]/[action]/{id}")] 19 | public async Task GetByCity(int id) 20 | { 21 | var data = await this._openWeatherMap.GetByCity(id); 22 | 23 | return Json(data); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Chapter18/CustomConvention.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.ApplicationModels; 2 | 3 | namespace chapter18 4 | { 5 | internal class CustomConvention : IApplicationModelConvention 6 | { 7 | public void Apply(ApplicationModel application) 8 | { 9 | application.Filters.Add(new CustomFilter()); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Chapter18/CustomFilter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Filters; 2 | 3 | namespace chapter18 4 | { 5 | internal class CustomFilter : IActionFilter 6 | { 7 | public void OnActionExecuted(ActionExecutedContext context) 8 | { 9 | 10 | } 11 | 12 | public void OnActionExecuting(ActionExecutingContext context) 13 | { 14 | 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Chapter18/CustomHostingStartup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | 3 | [assembly:HostingStartup(typeof(chapter18.CustomHostingStartup))] 4 | 5 | namespace chapter18 6 | { 7 | public class CustomHostingStartup : IHostingStartup 8 | { 9 | public void Configure(IWebHostBuilder builder) 10 | { 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Chapter18/Models/BlogContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace chapter18.Models 6 | { 7 | public class BlogContext : DbContext 8 | { 9 | public BlogContext(DbContextOptions options) : base(options) 10 | { 11 | } 12 | 13 | public DbSet Blogs { get; set; } 14 | } 15 | 16 | public class Blog 17 | { 18 | public int Id { get; set; } 19 | public string Name { get; set; } 20 | public string Url { get; set; } 21 | 22 | public virtual List Posts { get; set; } 23 | } 24 | 25 | public class Post 26 | { 27 | public int Id { get; set; } 28 | public DateTime Timestamp { get; set; } 29 | public string Title { get; set; } 30 | public string Body { get; set; } 31 | public string Url { get; set; } 32 | public virtual Blog Blog { get; set; } 33 | } 34 | } -------------------------------------------------------------------------------- /Chapter18/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace chapter18.Models 2 | { 3 | public class ErrorViewModel 4 | { 5 | public string RequestId { get; set; } 6 | 7 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter18/Models/OrdersContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace chapter18.Models 6 | { 7 | public class OrdersContext : DbContext 8 | { 9 | public OrdersContext(DbContextOptions options) : base(options) 10 | { 11 | 12 | } 13 | 14 | public DbSet Customer { get; set; } 15 | public DbSet Orders { get; set; } 16 | public DbSet Products { get; set; } 17 | } 18 | 19 | public class Product 20 | { 21 | public int Id { get; set; } 22 | public string Name { get; set; } 23 | public virtual List Orders { get; set; } = new List(); 24 | } 25 | 26 | public class Order 27 | { 28 | public int Id { get; set; } 29 | public DateTime Timestamp { get; set; } 30 | public virtual Product Product { get; set; } 31 | public virtual Customer Customer { get; set; } 32 | } 33 | 34 | public class Customer 35 | { 36 | public int Id { get; set; } 37 | public string Name { get; set; } 38 | public string Email { get; set; } 39 | public DateTime? Birthday { get; set; } 40 | public virtual List Orders { get; set; } = new List(); 41 | } 42 | } -------------------------------------------------------------------------------- /Chapter18/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:54240/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "chapter18": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:54241/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Chapter18/Protos/Greet.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option csharp_namespace = "Greet"; 4 | 5 | package Greet; 6 | 7 | enum Ok 8 | { 9 | No = 0; 10 | Yes = 1; 11 | }; 12 | 13 | service Greeter 14 | { 15 | rpc SayHello (HelloRequest) returns (HelloReply); 16 | }; 17 | 18 | message HelloRequest 19 | { 20 | string name = 1; 21 | }; 22 | 23 | message HelloReply 24 | { 25 | string message = 1; 26 | Ok ok = 2; 27 | }; -------------------------------------------------------------------------------- /Chapter18/Protos/pingpong.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option csharp_namespace = "PingPong"; 4 | 5 | package PingPong; 6 | 7 | message PingRequest 8 | { 9 | string name = 1; 10 | }; 11 | 12 | message PongResponse 13 | { 14 | string message = 1; 15 | Ok ok = 2; 16 | }; 17 | 18 | enum Ok 19 | { 20 | No = 0; 21 | Yes = 1; 22 | }; 23 | 24 | service PingPongService 25 | { 26 | rpc Ping(PingRequest) returns (PongResponse); 27 | 28 | rpc LotsOfPongs(PingRequest) returns (stream PongResponse); 29 | 30 | rpc LotsOfPings(stream PingRequest) returns (PongResponse); 31 | 32 | rpc BidiPingPong(stream PingRequest) returns (stream PongResponse); 33 | }; -------------------------------------------------------------------------------- /Chapter18/Services/PingPongService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace chapter18.Services 7 | { 8 | using Grpc.Core; 9 | using Microsoft.Extensions.Logging; 10 | using PingPong; 11 | 12 | public class PingPongService : PingPong.PingPongService.PingPongServiceBase 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public PingPongService(ILogger logger) 17 | { 18 | this._logger = logger; 19 | } 20 | 21 | public async override Task Ping(PingRequest request, ServerCallContext context) 22 | { 23 | this._logger.LogInformation("Ping received"); 24 | 25 | return new PongResponse 26 | { 27 | Message = "Pong " + request.Name, 28 | Ok = Ok.Yes 29 | }; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter18/UserIdHandler.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Net.Http; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace chapter18 10 | { 11 | public class UserIdHandler : DelegatingHandler 12 | { 13 | public UserIdHandler(IHttpContextAccessor httpContextAccessor) 14 | { 15 | this.HttpContext = httpContextAccessor.HttpContext; 16 | } 17 | 18 | protected HttpContext HttpContext { get; } 19 | 20 | protected override Task SendAsync(HttpRequestMessage request, 21 | CancellationToken cancellationToken) 22 | { 23 | request.Headers.Add("UserId", this.HttpContext.User.Identity.Name); 24 | 25 | return base.SendAsync(request, cancellationToken); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Chapter18/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 

Hello, world!

2 | 3 | Administration 4 | 5 | @Html.ActionLink( 6 | linkText: "Administration", 7 | actionName: "Index", 8 | controllerName: "Manage", 9 | routeValues: new { area = "Admin" }) -------------------------------------------------------------------------------- /Chapter18/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /Chapter18/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | chapter18 - @ViewData["Title"] 7 | 8 | 9 | @RenderBody() 10 | 11 | 12 | -------------------------------------------------------------------------------- /Chapter18/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Chapter18/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using chapter18 2 | @using chapter18.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Chapter18/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Chapter18/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb; Database=chapter18" 4 | }, 5 | "Services": { 6 | "Service1": { 7 | "Url": "" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter18/chapter18.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30114.105 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "chapter18", "chapter18.csproj", "{4499A93A-269F-4769-879F-17A93B67E7B1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4499A93A-269F-4769-879F-17A93B67E7B1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B51FC4D8-EDD6-40A6-998A-9F792B794681} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Chapter18/embeddedfile.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Embedded File 6 | 7 | 8 |

This is an embedded file

9 | 10 | -------------------------------------------------------------------------------- /Chapter18/wwwroot/file.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Static File 6 | 7 | 8 |

This is a static file

9 | 10 | -------------------------------------------------------------------------------- /Chapter18/wwwroot/folder/document.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 |

Default document

9 | 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------