ASP.NET Coreradar.zhaw.ch/~rege/dnet_fs20/dnet2_10.pdf · ASP.NET Core ASP.NET Core Key Concepts...

Click here to load reader

  • date post

    12-Aug-2020
  • Category

    Documents

  • view

    6
  • download

    0

Embed Size (px)

Transcript of ASP.NET Coreradar.zhaw.ch/~rege/dnet_fs20/dnet2_10.pdf · ASP.NET Core ASP.NET Core Key Concepts...

  • ASP.NET Core

    ■ ASP.NET Core Key Concepts

    ■ Benefits of the Use of ASP.NET Core

    ■ Tech Stack to build APS.NET Core Apps

    ■ MVC and MVVM Model

    ■ APIs for Web Services

  • 3 von 109School of Engineering © K. Rege, ZHAW

    ASP.NET Core

    ■ ASP.NET Core is a complete rewrite of the ASP.NET Library

    https://docs.microsoft.com/en-us/aspnet/core/?view=aspnetcore-2.2

  • 4 von 109School of Engineering © K. Rege, ZHAW

    … ASP.NET Core

    ■ Is part - as its name suggest - Core Library

  • 5 von 109School of Engineering © K. Rege, ZHAW

    ASP.NETWeb API

    ASP.NETWeb API

    ActiveServerPages

    (ClassicASP)

    ActiveServerPages

    (ClassicASP)

    ASP.NET(Web

    Forms)

    ASP.NET(Web

    Forms)

    ASP.NETMVC

    1/2/3/4/5

    ASP.NETMVC

    1/2/3/4/5

    ASP.NETWeb PagesASP.NET

    Web Pages

    Evolution of ASP and ASP.NET

    ASP.NETMVC 6

    Core MVC1/2/3

    UnifiedMVC,

    Web APIand Web

    Pages

    ASP.NETMVC 6

    Core MVC1/2/3

    UnifiedMVC,

    Web APIand Web

    Pages

  • 6 von 109School of Engineering © K. Rege, ZHAW

    ASP.NET MVC Version History

    ■ Since 2009 new Versions in

    a high frequency

    ■ New versions partially with fundamental

    and breaking changes■ even project files may not be imported

    ■ Since 2016 6.0 -> Core 1.0

    ■ Differences MVC vs MVC Core

    ■ Yes, Cocaine is still illegal in Washington

    https://www.youtube.com/watch?v=79UWvR734wI

    faster, easier,betterfaster, easier,better

    https://www.maxeylaw.com/blog/2018/02/understanding-cocaine-laws-in-washington.shtml

  • 7 von 109School of Engineering © K. Rege, ZHAW

    … ASP.NET MVC Version Future

    ■ Next Versions MS LTS -> 3aUbuntu LTS ~ 10a

    MS LTS -> 3aUbuntu LTS ~ 10a

    https://www.drugs.com/illicit/speed.html

  • 8 von 109School of Engineering © K. Rege, ZHAW

    What is ASP.NET Core

    ■ Key Concepts of APS.NET Core

    Cross PlatformCross Platform TestabilityTestability

    One ProgrammingModel for MVC and

    Web API

    One ProgrammingModel for MVC and

    Web APIOpen-SourceOpen-Source

    DependencyInjection

    DependencyInjection Modular

    Modular

  • 9 von 109School of Engineering © K. Rege, ZHAW

    https://www.youtube.com/watch?v=4IgC2Q5-yDE

    https://www.tutorialspoint.com/asp.net_core/index.htm

    What is ASP.NET Core

    ASP.NET Core is a cross-platform, high performance, open-source framework for building modern, cloud-based, Internet-connected applications

    ASP.NET Core is a complete redesign of ASP.NET 4.x

  • 10 von 109School of Engineering © K. Rege, ZHAW

    Benefits of ASP.NET Core - Cross Platform

    Asp.NET Core Applications can be developed and run on any platform

    ■ Windows

    ■ macOS

    ■ Linux

    APS.NET Core applications can be hosted on

    ■ IIS

    ■ Apache

    ■ Docker

    ■ Self-host in a process

  • 11 von 109School of Engineering © K. Rege, ZHAW

    … Benefits of ASP.NET Core

    One Unified Programming Model for MVC and Web API

    ■ Both the MVC Controller class and the ASP.NET Web API Controller class

    inherits from the same Controller base class and returns IActionResult

    https://exceptionnotfound.net/asp-net-core-demystified-action-results/

    ViewResultViewResultActionResultActionResult

    IActionResultIActionResult

    ViewResultViewResult

    For WEB APIFor WEB API For MVC PageFor MVC Page

  • 12 von 109School of Engineering © K. Rege, ZHAW

    … Benefits of ASP.NET Core

    Middleware Components allow for Modularity

    ■ ASP.NET Core Provides Modularity with Middleware Components

    ■ Both the request and response pipelines are composed using the middleware

    components

    ■ A rich set of built-in middleware components are provided out of the box

    ■ Custom Middleware Components can also be created

  • 13 von 109School of Engineering © K. Rege, ZHAW

    Summary: Why to use ASP.NET Core

    ■ A unified model for building web UI and web APIs.

    ■ Razor Pages makes coding page-focused scenarios easier and more productive.

    ■ Ability to develop and run on Windows, macOS, and Linux.

    ■ Open-source and community-focused.

    ■ Integration of modern, client-side frameworks and development workflows.

    ■ A cloud-ready, environment-based configuration system.

    ■ Built-in dependency injection.

    ■ A lightweight, high-performance, and modular HTTP request pipeline.

    ■ Ability to host on IIS, Apache, Docker, Nginx, or self-host in your own process.

    ■ Side-by-side App versioning when targeting .NET Core.

    ■ Tooling that simplifies modern web development.

    ■ Architected for testability.

  • 14 von 109School of Engineering © K. Rege, ZHAW

    Installation

    ■ VS 19 with .NET Core 3.1 Development Tools

    ■ To Install newer Version go to Download Link below (chose SDK)■ we use Version 3.1 here

  • 15 von 109School of Engineering © K. Rege, ZHAW

    ASP.NET Core

  • 16 von 109School of Engineering © K. Rege, ZHAW

    To Create a New Project

    ■ ■ Step 1. Create a new Project■ type APS.NET Core as Web Plaform

    ■ Step 2. Configuration■ give reasonable name

    ■ rest simply choose defaults

  • 17 von 109School of Engineering © K. Rege, ZHAW

    … To Create a New Project

    ■ Step 3. Define Project Type

    Generatesminimum ofadditional files

    Generatesminimum ofadditional files

    Generates MVCCode Samples,CSS, HTML

    Generates MVCCode Samples,CSS, HTML

    Generates RESTHTTP Server, i.e.Controllers Folder

    Generates RESTHTTP Server, i.e.Controllers Folder

    Generates RazorPages APPMVVM

    Generates RazorPages APPMVVM

    Legacy ;-) WebApplication support

    Legacy ;-) WebApplication support

  • 18 von 109School of Engineering © K. Rege, ZHAW

    ASP.NET Core "Universe"

    Hosting Model Middleware

    Services for DependencyInjection

    Configuration

    MVC

    Routing Web API

    Razor PageView

    Razor ClassLibrary

    Start

    Razor Pages AppMVVM

  • 19 von 109School of Engineering © K. Rege, ZHAW

    Hello World

  • 20 von 109School of Engineering © K. Rege, ZHAW

    Hello Word Project

    ■ Create an New .NET Core -> APS.NET Empty Project

    ■ Choose Empty as Web Application Type

    uncheck for easydebugging

    uncheck for easydebugging

    Generatesminimum ofadditional files

    Generatesminimum ofadditional files

  • 21 von 109School of Engineering © K. Rege, ZHAW

    Hello World in CLI

    ■ In CLI Type in new Directory

    dotnet new web

    ■ The same three Files are generated

    dotnet run

    ■ Start Browser on indicated Port, e.g. 5000C:\tmp\asp_net>dotnet new webThe template "ASP.NET Core Empty" was created successfully.C:\tmp\asp_net>dotnet runUsing launch settings from C:\tmp\asp_net\Properties\launchSettings.json...Hosting environment: DevelopmentContent root path: C:\tmp\asp_netNow listening on: https://localhost:5001Now listening on: http://localhost:5000Application started. Press Ctrl+C to shut down.info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] Request starting HTTP/1.1 GET http://localhost:5000/info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2] Request finished in 11.2679ms 200info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] Request starting HTTP/1.1 GET http://localhost:5000/favicon.icoinfo: Microsoft.AspNetCore.Hosting.Internal.WebHost[2] Request finished in 0.156ms 200

  • 22 von 109School of Engineering © K. Rege, ZHAW

    Generated Files

    ■ Generated Files and Directory Structure ■ Program.cs■ Main Program of the App

    ■ Startup.cs■ Initialization of the App

    ■ .csproj■ Dependencies, Hosting Model

    ■ appsetting.json■ Settings that are specific to the application

    ■ launchSetting.json■ project specific settings■ associated with each profile environment

    variables that should be used.

  • 23 von 109School of Engineering © K. Rege, ZHAW

    Program.cs: The Web Apps Main Program

    ■ The Main Programm: the Host Builder Class

    ■ The Startup class is specified by calling■ UseStartup method out your host builder (main) Class

    ■ ASP.NET Core apps use a Startup class (name by conventions)■ To further configure the apps

    namespace WebApplication1{ public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) => Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => {

    webBuilder.UseStartup();});

    }}

    public class Startup { ...

    Startup class is defined via the GenericType; this pattern is used, to allow fordependency injection in theConstructor. Values that should beinjected are Constructor parameters ofthe Startup class

    Startup class is defined via the GenericType; this pattern is used, to allow fordependency injection in theConstructor. Values that should beinjected are Constructor parameters ofthe Startup class

  • 24 von 109School of Engineering © K. Rege, ZHAW

    Startup.cs: The Startup Class

    ■ ConfigureServices, called by Runtime■ To configure the app's services. Services are configured - also described as registered - in

    ConfigureServices and consumed across the app via dependency injection

    ■ Configure, called by Runtime■ to build the Apps Host

    namespace WebApplication1{ public class Startup { public void ConfigureServices(IServiceCollection services) {}

    public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()){ app.UseDeveloperExceptionPage(); } app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); } }}

    Use this method to addservices to the container.

    Use this method to addservices to the container.

    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/startup?view=aspnetcore-3.1

    Use this method to configure theHTTP request pipeline akaMiddleware.

    Use this method to configure theHTTP request pipeline akaMiddleware.

    Middleware that is calledMiddleware that is called

  • 25 von 109School of Engineering © K. Rege, ZHAW

    Configuration FilesHosting Definitions

  • 26 von 109School of Engineering © K. Rege, ZHAW

    launchsettings json

    ■ set specific properties for the

    environments

    ■ iisSettings with two profiles

    ■ Profile IIS Express■ when started in VS with e.g. F5■ ASPNETCORE_ENVIRONMET: Develop.

    ■ WebAapplication1 i.e. Name of Project■ used when CLI is used dotnet run■ or VS configuration run

    { "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": http://localhost:49741", "sslPort": 0 } }, "profiles": { "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "WebApplication1": { "commandName": "Project", "launchBrowser": true, "applicationUrl": "http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Azure Dev Spaces": { "commandName": "AzureDevSpaces", "launchBrowser": true }}}

    //Startup.csif (env.IsDevelopment()){ ...}

    or staging,production

    or staging,production

    can be read byIConfiguration (see later)

    can be read byIConfiguration (see later)

    defines hostingmodel

    defines hostingmodel

    launchsettings json

  • 27 von 109School of Engineering © K. Rege, ZHAW

    .csproj Files

    ■ TargetFramework■ which framework should be used■ HostingModel

    ■ Internal: Web Server thathosts .NET Core App

    ■ Use External Web Server thatdispatches calls - as forewardProxy "full blown" .net core

    WebServer

    "full blown" .net coreWebServer

    Development WebServerDevelopment WebServer

    ProjectDebugger

    IIS Express

    netcoreapp3.1

  • 28 von 109School of Engineering © K. Rege, ZHAW

    Kestrel

    ■ ASP.NET Core project templates use Kestrel by default.■ Kestrel used as an Internet-facing web server

    ■ In a reverse proxy configuration

    ■ In Program.cs, the ConfigureWebHostDefaults method calls UseKestrel:

    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-3.1

    public static void Main(string[] args){ CreateHostBuilder(args).Build().Run();}

    public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); });

  • 29 von 109School of Engineering © K. Rege, ZHAW

    appsetting.json, appsettings.[ENV].json

    ■ One of several Configuration Sources

    ■ stored as key value pairs

    ■ To access it use IConfiguration Services■ Add a Startup-Constructor with IConfiguration as parameter and store it in local variable _config■ The _config Parameter is automatically set via Dependency Injection

    Pre

    ced

    ence

    added new environmentvariable

    added new environmentvariable

    appsettings.json

    Azure Key VaultAzure Key Vault

    Injected Injected

    e.g. security critical e.g. database connection stringe.g. security critical e.g. database connection string

    https://docs.microsoft.com/en-us/aspnet/core/security/key-vault-configuration?view=aspnetcore-3.1

  • 30 von 109School of Engineering © K. Rege, ZHAW

    … appsetting.json, appsettings.[ENV].json

    ■ The Config Value can simply be accessed in a Module via the _config instance

    variable

    ■ also applied to configure Middleware used via env■ e.g. IsDevelopment() returns true if "ASPNETCORE_ENVIRONMENT": "Development"

    if (env.IsDevelopment()){ app.UseDeveloperExceptionPage(); }

  • 31 von 109School of Engineering © K. Rege, ZHAW

    Middleware

  • 32 von 109School of Engineering © K. Rege, ZHAW

    Middleware in ASP.NET Core

    ■ Middleware here is software that is assembled into "processing pipelines"to handle requests and responses. Each component:

    ■ Chooses whether to pass the request to the next component in the pipeline.■ Can perform work before and after the next component in the pipeline.

    ■ Request delegates are configured using one of the following extension methods■ Run: Terminating Middleware i.e. terminates the pipeline■ Use: Intermediate Middleware; next delegate parameter for next Middleware in the pipeline.

    ■ You can typically perform actions before and after the next delegate■ Map: Branches the request pipeline based on matches of the given request path

    Called HTTP handlers inAPS.NET (classic)

    Called HTTP handlers inAPS.NET (classic)

    The Term "Middleware" is usually used for the OSindependent "software layer" in distributed applications

    The Term "Middleware" is usually used for the OSindependent "software layer" in distributed applications

    term influenced bynode.js express

    term influenced bynode.js express

  • 33 von 109School of Engineering © K. Rege, ZHAW

    Handles a Requests (terminating)

    ■ The Middleware Components are specified in the Configure Method of theStartup class

    ■ by passing a Method (Lambda Expression) to app.Run functionality is appendedto the processing pipeline

    ■ All Request are passed to this method, e.g. returning Text "Hello, World"

    ■ Run terminates the processing pipeline, i.e. the following Middlewarecomponents in the pipeline are not called

    public class Startup{ public void Configure(IApplicationBuilder app,IWebHostEnvironment env) { app.Run(async context => { await context.Response.WriteAsync("Hello, World!"); }); }}

  • 34 von 109School of Engineering © K. Rege, ZHAW

    Handles a request and pass to next in Pipeline

    ■ Chain multiple request delegates together with Use.■ The next parameter is set to the next delegate in the pipeline.■ You can typically perform actions both before and after the next delegate

    public class Startup{

    public void Configure(IApplicationBuilder app,IWebHostEnvironment env) { app.Use(async (context, next) => { // Do work before. await context.Response.WriteAsync("before - ");

    await next.Invoke();

    // Do other work after. await context.Response.WriteAsync(" - after"); });

    app.Run(async context => { await context.Response.WriteAsync("Hello from 2nd delegate."); }); }}

  • 35 von 109School of Engineering © K. Rege, ZHAW

    Predefined Middleware: e.g. Use Static Files

    ■ UseStaticFiles is used to server the return of static files■ default: Static files that are stored within your project's web root directory.■ can be configured to handle files in any other directory■ if the file is found, the processing pipeline will be terminated

    public void Configure(IApplicationBuilder app){ app.UseStaticFiles(); // For the wwwroot folder

    app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider( Path.Combine(Directory.GetCurrentDirectory(), "MyStaticFiles")), RequestPath = "/StaticFiles" });}

  • 36 von 109School of Engineering © K. Rege, ZHAW

    Add a Middleware via NuGet Package

    ■ Several ASP.NET Core Middleware Modules are available via NuGet, e.g.

    Microsoft.aspnetcore.diagnostics■ for exception handling, exception display pages,

    and diagnostics information

    ■ Simply add the new Middleware to

    processing pipeline

  • 37 von 109School of Engineering © K. Rege, ZHAW

    Add a Logger Middleware direct in Start Class

    ■ Write Middleware that Logs Requests

    ■ First Add an ILogger Parameter to the Configure Method

    ■ Add another Middleware that logs all requests

    ■ Logger info is shown by default in the output window of visual Studio

    public void Configure(IApplicationBuilder app,IHostingEnvironmentenv,Ilogger logger) {

    will be injectedwill be injected

    using Microsoft.Extensions.Logging;

  • 38 von 109School of Engineering © K. Rege, ZHAW

    Custom Middleware Time Logger

    ■ Write Middleware that measures Request time public class StopwatchMiddleWare { private readonly RequestDelegate _next;

    public StopwatchMiddleWare(RequestDelegate next) { _next = next; }

    public async Task Invoke(HttpContext context) { var s = new Stopwatch(); s.Start(); // execute the rest of the pipeline await _next(context); s.Stop(); //stop measuring var result = s.ElapsedMilliseconds; // write out the milliseconds needed await context.Response.WriteAsync($"Time needed: {result }"); } }

    public static class StopwatchMiddlewareExtension { public static IApplicationBuilder UseStopwatch(this IApplicationBuilder app) { app.UseMiddleware(); return app; }}

    app.UseStopwatch(); inconfigure Method to enable it

    app.UseStopwatch(); inconfigure Method to enable it

    append Text to web pageappend Text to web page

    https://asp.net-hacker.rocks/2018/10/08/customizing-aspnetcore-06-middlewares.html

    as new extensionmethod for theapplication builder

    as new extensionmethod for theapplication builder

    without extension Methoduse this line

    without extension Methoduse this line

  • 39 von 109School of Engineering © K. Rege, ZHAW

    Dependency Injection

  • 40 von 109School of Engineering © K. Rege, ZHAW

    General Principles

    ■ Dependency Injection is used throughout the entire ASP.NET Core system

    ■ If some is provided by a service that should be used via D.I. simply■ Registered that Service via Services.Add■ Add the Interface type of the Service in the Constructor

    ■ E.g. If config values are needed simply inject IConfiguration

    public class MyDependency : IMyDependency {

    public MyDependency(IConfiguration config) { var myStringValue = config["MyStringKey"];

    // Use myStringValue }

    ...}

  • 41 von 109School of Engineering © K. Rege, ZHAW

    Why Dependency Injection

    ■ A dependency is any object that another object requires.

    ■ Example MyDependency class with a WriteMessage method that other classes

    in an app depend upon:

    public class MyDependency { public MyDependency() { }

    public Task WriteMessage(string message) { Console.WriteLine( $"MyDependency.WriteMessage called. Message: {message}"); return Task.FromResult(0); }}

    public class IndexModel : PageModel { MyDependency _dependency = new MyDependency();

    public async Task OnGetAsync() { await _dependency.WriteMessage( "IndexModel.OnGetAsync created this message."); }}

    1)Replace MyDependency witha different implementation, theclass must be modified

    1)Replace MyDependency witha different implementation, theclass must be modified

    2) MyDependency might haveitself dependencies

    2) MyDependency might haveitself dependencies

    3)Difficult to Test/Mockup theClass

    3)Difficult to Test/Mockup theClass

  • 42 von 109School of Engineering © K. Rege, ZHAW

    Dependency Injection Principles

    ■ Registration of the dependency in a service container■ Implement the interface IServiceProvider.■ Services are registered in the app's Startup.ConfigureServices method.■ Injection of the service as parameter of the constructor of the class■ The framework takes on the responsibility of

    ■ creating an instance of the dependency■ disposing of it when it's no longer needed.

    ■ The Framework provides D.I. for several built in Classes■ IHostingEnvironment env■ IConfiguration config■ IApplicationBuilder app■ ILogger■ ILoggerFactory loggerFactory■ ….

  • 43 von 109School of Engineering © K. Rege, ZHAW

    Build a new Service for Dependency Injection

    ■ An Interface defines the method that the service provides to the app

    ■ MyDependency itself is dependent to ILogger

    public interface IMyDependency { Task WriteMessage(string message);}

    public class MyDependency : IMyDependency{ private readonly ILogger _logger;

    public MyDependency(ILogger logger) { _logger = logger; }

    public Task WriteMessage(string message) { _logger.LogInformation( "MyDependency.WriteMessage called. Message: {MESSAGE}", message);

    return Task.FromResult(0); }}

  • 44 von 109School of Engineering © K. Rege, ZHAW

    ...Build a new Service for Dependency Injection

    ■ To Register the new Service add it in the ConfigureService Method■ AddSingleton one Instance per Process■ AddScoped new Instance per Request■ ...

    ■ The D.I. now can be used also e.g. in the Configure Method of the Start Class

    public void ConfigureServices(IServiceCollection services) {

    ... services.AddSingleton(typeof(ILogger), typeof(Logger)); services.AddScoped(); }

    // This method gets called by the runtime. Use this method to configur public void Configure(IApplicationBuilder app, IHostingEnvironment env,

    IMyDependency myDep) { myDep.WriteMessage("hello form MyDep"); ...

    Scoped lifetime services are createdonce per client request (connection).

    Scoped lifetime services are createdonce per client request (connection).

    Singleton lifetime services are created the first time they'rerequested; have to be defined for MyDependeny

    Singleton lifetime services are created the first time they'rerequested; have to be defined for MyDependeny

  • 45 von 109School of Engineering © K. Rege, ZHAW

    MVCOverview

  • 46 von 109School of Engineering © K. Rege, ZHAW

    Hello World MVC in VS and CLI

    ■ Chose Web Application

    static web filesstatic web files

    configuration settingsoverwritten by AZUREKey vault in productionenvironment

    configuration settingsoverwritten by AZUREKey vault in productionenvironment

    c:\> dotnet new mvc

  • 47 von 109School of Engineering © K. Rege, ZHAW

    Generated MVC Startup.CS

    ■ Generated File that contains initialization

    Add Middleware componentsto pipeline

    Add Middleware componentsto pipeline

    Define RoutesDefine Routes

  • 48 von 109School of Engineering © K. Rege, ZHAW

    The MVC Architectural Pattern

    ■ Goal of the Pattern■ Helps to achieve separation of concerns■ Separates an application into three main groups of components: Models, Views, and Controllers■ btw: Introduced by the very first Smalltalk GUI Library -> see PSp Smalltalk lecture

    ■ Model■ Data Container and Processing■ Is responsible to perform user actions■ And/or retrieve results of queries.

    ■ View■ Data display and user interactivity■ Has little or no code behind

    ■ Controller:■ User requests are routed to■ Chooses the View to display to the user■ Provides View with required Model data■ Is responsible for working with the Model

    https://docs.microsoft.com/en-us/aspnet/core/mvc/overview?view=aspnetcore-3.1

  • 49 von 109School of Engineering © K. Rege, ZHAW

    MVC Overview

  • 50 von 109School of Engineering © K. Rege, ZHAW

    Core Concepts of ASP.NET Core MVC

    ■ Controllers

    ■ Routing (to Controllers)

    ■ Views■ View Components■ Razor view engine■ Strongly typed views

    ■ Model■ Binding ■ Model Validation of Data

    ■ Dependency Injection

    ■ Middleware

    ■ Filters

    ■ Tag Helpers

    ■ Web APIs

  • 51 von 109School of Engineering © K. Rege, ZHAW

    Build Web UI using ASP.NET Core MVC

    ■ Use the Model-View-Controller (MVC) pattern■ clear separation of concerns■ make your web APIs and web Apps testable.

    ■ Razor Pages■ is a page-based programming model that simplifies building web UI easier: MVVM Model■ Razor markup provides a syntax for Razor Pages and MVC Razor views.

    ■ Tag Helpers■ enable server-side code to participate in creating and rendering HTML elements in Razor Pages.

    ■ Built-in support for multiple data formats and content negotiation■ lets your web APIs reach a broad range of clients, including browsers and mobile devices.

    ■ Model binding■ automatically maps data from HTTP requests to action method parameters.

    ■ Model validation■ automatically performs client-side and server-side validation.

  • 52 von 109School of Engineering © K. Rege, ZHAW

    Controllers

    ■ Controllers: Classes that handle browser requests.■ They retrieve model data and call view templates that return a response.■ For example, the controller handles route data and query-string values, and passes these values to

    the model.

    ■ Every public method in a controller is callable as an HTTP endpoint.■ such as https://localhost:5001/HelloWorld/Welcome■ In the sample , both methods return a string. Note the comments preceding each method

    ■ Which Controller/method is addressed is determined by Routing

    public class HelloWorldController : Controller { // GET: /HelloWorld/ public string Index() { return "This is my default action..."; }

    // GET: /HelloWorld/Welcome/ public string Welcome() { return "This is the Welcome action method..."; } }

  • 53 von 109School of Engineering © K. Rege, ZHAW

    Routing

    ■ Defines to which controller the request is passed■ Reasoning:

    ■ The application structure should not reflect the URL patterns■ Define application's URL naming patterns

    ■ that work well for search■ Without regard for how the files on your web server are organized.

    ■ Convention-based routing ■ Define the URL formats that your application accepts■ Specific action method on given controller■ The "central" routing engine

    ■ parses the URL and matches it to one of the defined URL formats■ and then calls the associated controller's action method.

    ■ Attribute routing■ specify routing information by decorating your controllers

    and actions with attributes

    routes.MapRoute(name: "Default", template: "{controller=Home}/{action=Index}/{id?}");

    [Route("api/[controller]")]public class ProductsController : Controller [HttpGet("{id}")] public IActionResult GetProduct(int id) { ... }

    Also: Application can beredesigned withoutbreaking existing storedURLs

    Also: Application can beredesigned withoutbreaking existing storedURLs

    as defined in generatedStartup class

    as defined in generatedStartup class

    name of the defaultcontroller

    name of the defaultcontroller

    name of the default actioni.e. method called incontroller

    name of the default actioni.e. method called incontroller

  • 54 von 109School of Engineering © K. Rege, ZHAW

    View: Razor

    ■ ASP.NET Core MVC views use the Razor View Engine to render views.

    ■ Template markup language for defining views using embedded C# code.

    ■ Razor is used to dynamically generate web content on the server.■ You can mix server code with client side content and code.

    ■ A .cshtml markup file maintained within■ stored in the Views folder for "MVC"■ stored in the Pages folder for "Razor Apps"

    @for (int i = 0; i < 5; i++) { List item @i }

    @model IEnumerable

    @foreach (Product p in Model) { @p.Name }

  • 55 von 109School of Engineering © K. Rege, ZHAW

    View: Razor (View) Class Library

    ■ Common Part of the View may be separated and stored in libraries

    ■ To package rendering logic and reuse it throughout the application■ To Break up large markup files into smaller components■ Reduce the duplication of common markup content across markup files

  • 56 von 109School of Engineering © K. Rege, ZHAW

    Models

    ■ Perform user actions and/or retrieve results of queries

    ■ Additional: Check for Data validation■ Decorating your model object with data annotation e.g. validation attributes.■ The validation attributes are checked

    ■ On the client side before values are posted to the server,■ As well as on the server before the controller action is called.

    using System.ComponentModel.DataAnnotations;public class LoginViewModel { [Required] [EmailAddress] public string Email { get; set; }

    [Required] [DataType(DataType.Password)] public string Password { get; set; }

    [Display(Name = "Remember me?")] public bool RememberMe { get; set; }}

  • 57 von 109School of Engineering © K. Rege, ZHAW

    Dependency Injection of Model

    ■ Converts client request data (form values, route data, query string parameters,

    HTTP headers) into objects that are passed to the controller■ Your controller logic doesn't have to do the work of figuring out the incoming request data

    ■ Simply pass the data as parameters to the controller methods.

    public async Task Login(LoginViewModel model, string returnUrl = null) { if (ModelState.IsValid) { // work with the model } // At this point, something failed, redisplay form return View(model);}

    Model is injectedModel is injected Value extracted via RoutingValue extracted via Routing

  • 58 von 109School of Engineering © K. Rege, ZHAW

    Dependency Injection of Model

    ■ Controllers can request needed services through their constructors

    ■ Dependency injection in Razor files, using the @inject directive:

    @inject SomeService ServiceName

    @ServiceName.GetTitle

    @ServiceName.GetTitle

    IMyDependency _dep;public HomeController(IMyDependency dep){ _dep = dep;}

  • 59 von 109School of Engineering © K. Rege, ZHAW

    Filters

    ■ Filters enable running custom pre- and post-processing logic for action methods

    ■ used to encapsulate cross-cutting concerns, like exception handling or

    authorization.

    ■ Several filters (such as Authorize) are included in the framework.■ e.g. [Authorize] is the attribute that is used to create MVC authorization filters.

    [Authorize]public class AccountController :Controller

    https://docs.microsoft.com/en-us/aspnet/core/security/authorization/introduction?view=aspnetcore-3.1

  • 60 von 109School of Engineering © K. Rege, ZHAW

    Tag Helpers

    ■ Tag Helpers enable server side code to participate in creating and rendering

    HTML elements in Razor files.

    ■ Used to define custom tags (for example, ) or to modify thebehavior of existing tags (for example, ).

    ■ There are many built-in Tag Helpers for common tasks -■ such as creating forms, links, loading assets and more■ more available in public GitHub repositories and as NuGet packages.

    Environment TagHelper to use differentscripts in your views based on the runtimeenvironment

    Environment TagHelper to use differentscripts in your views based on the runtimeenvironment

  • 61 von 109School of Engineering © K. Rege, ZHAW

    Routing

  • 62 von 109School of Engineering © K. Rege, ZHAW

    Routing

    ■ Is responsible for mapping request URIs to endpoint selectors and dispatching

    incoming requests to endpoints i.e. Routers

    ■ Routes■ Are defined in the app and configured when the app starts.■ Can extract values from the URL contained in the request, and these values can then be used for

    request processing.

    ■ Enable Routing

    ■ For MVC■ specify the MVC additionally use

    void ConfigureServices() { services.AddControllersWithViews(); }

    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-3.1

    class Startup public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseRouting(); ...

  • 63 von 109School of Engineering © K. Rege, ZHAW

    Routing Basics

    ■ Choose a basic and descriptive routing scheme so that URLs are readable and

    meaningful. The default conventional route■ Supports a basic and descriptive routing scheme.■ Is a useful starting point for UI-based apps.

    ■ By default, an app has a single collection of routes.■ When a request arrives, the routes in the collection are processed in the order that they exist in the

    collection

    ■ App models, such as MVC/Razor Pages■ register all of their endpoints, which have a predictable implementation of routing scenarios.

    ■ The Framework attempts to match an incoming request URL to a route in thecollection by calling the RouteAsync method on each route in the collection.

    {controller=Home}/{action=Index}/{id?}

    Class name of the controllerClass name of the controller Method name of the controllerMethod name of the controller ParametersParameters

  • 64 von 109School of Engineering © K. Rege, ZHAW

    Create Routes

    ■ Most apps create routes by calling MapRoute or one of the similar extension

    methods defined on IRouteBuilder.

    ■ Any of the IRouteBuilder extension methods create an instance of Route andadd it to the route collection.

    ■ ASP.NET Core MVC is typically configured as a default handler that only

    handles requests that match an available controller and action.

    ■ e.g.If the URL /Products/Details/17 is entered the following route values are

    generated { controller = Products, action = Details, id = 17 }

    ■ If URL / is entered defaults are taken {controller=Home,action = Details,id=17}

    ■ Router Constraints …,{id:int} -> only /Products/Details/17 matches

    routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}");

  • 65 von 109School of Engineering © K. Rege, ZHAW

    … Create Routes

    ■ Use ** or * before the route parameter name: Catch-all

    ■ to capture the remainder of the URL path and can also match the empty string.

    ■ If the URL /Blog/All-About-Routing/Introduction is entered the following route

    values are generated{ controller = Blog, action = ReadArticle, article =

    All-About-Routing/Introduction }.

    ■ Add Constraint and dataToken (see below)

    routes.MapRoute( name: "blog", template: "Blog/{**article}", defaults: new { controller = "Blog", action = "ReadArticle" });

    routes.MapRoute( name: "us_english_products", template: "en-US/Products/{id}", defaults: new { controller = "Products", action = "Details" }, constraints: new { id = new IntRouteConstraint() }, dataTokens: new { locale = "en-US" });

    constant values passed to the route handler

  • 66 von 109School of Engineering © K. Rege, ZHAW

    Route Templates

    ■ Tokens within curly braces ({ ... }) define route parameters that are bound (i.e.passed to the controller) if the route is matched.

    ■ Literal text other than route parameters (for example, {id}) and the path separator

    / must exactly match the text in the URL.

    ■ e.g. URL patterns that attempt to capture a file name with an optional file

    extension have additional considerations.■ For example, consider the template files/{filename}.{ext?}.

    ■ When values for both filename and ext exist, both values are populated.■ If only a value for filename exists in the URL, the route matches because the trailing period (.)

    is optional.

  • 67 von 109School of Engineering © K. Rege, ZHAW

    … Route Templates

    ■ Route parameters may have default values designated by specifying the default

    value after the parameter name separated by an equals sign (=).■ For example, {controller=Home} defines Home as the default value for controller.

    ■ Route parameters may have constraints that must match the route value bound

    from the URL.

    ■ Adding a colon (:) and constraint name after the route parameter name specifies

    an inline constraint on a route parameter.■ e.g. blog/{article:minlength(10)} specifies a minlength constraint with the argument 10

    ■ Route parameters may also have parameter transformers, which transform a

    parameter's value when generating links and matching actions■ For example, the route template blog/{article:slugify} specifies a custom slugify transformer.

  • 68 von 109School of Engineering © K. Rege, ZHAW

    … Route Templates

    ■ Table demonstrates example of route templates

  • 69 von 109School of Engineering © K. Rege, ZHAW

    Reserved Routing Names

    ■ The following keywords are reserved names and can't be used as route names

    or parameters:■ action■ area■ controller■ handler■ page

    ■ Values explicitly provided but that don't match a segment of the route are added

    to the query string.■ The following table shows the result when using the route template {controller}/{action}/{id?}.

  • 70 von 109School of Engineering © K. Rege, ZHAW

    Route Constraint Reference

    ■ Route constraints should be used to disambiguate similar routes,

    ■ but not to validate the inputs for a particular route.■ constraint fails -> 404 is returned

    ■ Custom Constraints services.AddRouting(options => { options.ConstraintMap.Add("customName",typeof(MyCustomConstraint));});

  • 71 von 109School of Engineering © K. Rege, ZHAW

    Parameter Transformer

    ■ Execute when generating a link for a Route.■ Implement Microsoft.AspNetCore.Routing.IOutboundParameterTransformer.

    ■ Take the parameter's route value and transform it to a new string value.

    ■ Are configured using ConstraintMap in Startup.ConfigureServices.

    ■ Result in using the transformed value in the generated link.■ For example, a custom slugify parameter transformer in route pattern blog\{article:slugify} with

    Url.Action(new { article = "MyTestArticle" }) generates blog\my-test-article.

    services.AddRouting(options =>{ // Replace the type and the name used to refer to it with your own // IOutboundParameterTransformer implementation options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer);});

    routes.MapRoute( name: "default", template: "{controller:slugify=Home}/{action:slugify=Index}/{id?}");

  • 72 von 109School of Engineering © K. Rege, ZHAW

    Attribute Routing

    ■ Attribute routing enables you to specify routing information by decorating yourcontrollers and actions with attributes that define your application's routes.

    ■ route definitions are placed next to the controller and action with which they're associated.

    [Route("api/[controller]")]public class ProductsController : Controller{ [HttpGet("{id}")] public IActionResult GetProduct(int id) { ... }}

  • 73 von 109School of Engineering © K. Rege, ZHAW

    Controllers

  • 74 von 109School of Engineering © K. Rege, ZHAW

    Add a controller to an ASP.NET Core MVC App

    ■ In the MVC App a Default Controller is added

    ■ But also additional Controllers may be added■ In the Add Scaffold (code is generated) dialog box, select MVC Controller - Empty

    https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-controller?view=aspnetcore-3.1

  • 75 von 109School of Engineering © K. Rege, ZHAW

    Default MVC Home Controller and their Views

    ■ The Controller return the Content of the according (generated) Views

    ■ Routing is set that request is passed,

    to the Home Controller

    namespace WebMVCCore.Controllers { public class HomeController : Controller {

    public IActionResult Index() { return View(); }

    public IActionResult Welcome() { return View(); }

    public IActionResult Privacy() { return View(); }

    [ResponseCache(Duration = 0,Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel {

    RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } }}

  • 76 von 109School of Engineering © K. Rege, ZHAW

    … Default MVC Home Controller

    ■ The Routing is set (by default) as follows

    ■ Add the following Controller

    using Microsoft.AspNetCore.Mvc;using System.Text.Encodings.Web;

    namespace MvcMovie.Controllers{ public class HomeController : Controller {

    // GET: /Home/ public string Index() { return "This is my default action..."; }

    // GET: /Home/Welcome/ public string Welcome() { return "This is the Welcome action method..."; } }}

    app.UseMvc(routes =>{ routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}");});

    The Controller's Class Nameis determinedby naming convention

    The Controller's Class Nameis determinedby naming convention

    no action thusIndex Methodis called

    no action thusIndex Methodis called

    action = "Welcome"thus WelcomeMethod is called

    action = "Welcome"thus WelcomeMethod is called

  • 77 von 109School of Engineering © K. Rege, ZHAW

    URL-Information passed to the Controller

    ■ The Controller Welcome Method can also have parameters■ Routing Roules determine hot to set the values of these parameters

    ■ When calling this Method with … ?name=hugo&numtimes=2■ the result looks the following;■ if no numtimes is added the default (=1) is taken

    ■ The Controller Welcome Method matched the id of the Route ... /{id?}"

    // Requires using System.Text.Encodings.Web;public string Welcome(string name, int numTimes = 1){ return HtmlEncoder.Default.Encode($"Hello {name}, NumTimes is:{numTimes}");}

    public string Welcome(string name, int ID = 1){ return HtmlEncoder.Default.Encode($"Hello {name}, ID: {ID}");}

  • 78 von 109School of Engineering © K. Rege, ZHAW

    Views

  • 79 von 109School of Engineering © K. Rege, ZHAW

    Add a View as Controller Result

    ■ Steps to Add a Welcome View■ Right click on the Views folder, and then■ Right click on the Views/Home folder,

    and then Add > New Item.■ In the Add New Item

    ■ In the search box in the upper-right, enter view■ Select Razor View■ name it Welcome.cshtml.■ Select Add

    ■ Type the following Text into the View

    ■ Change Welcome Method in Controller to public IActionResult Welcome() { return View(); }

    @{ ViewData["Title"] = "Index";}

    Index

    Hello from our View Template!

  • 80 von 109School of Engineering © K. Rege, ZHAW

    Passing Data from the Controller to the View

    ■ Controllers are responsible for providing the data required in order for a view

    template to render a response.■ The ViewData dictionary object contains data that will be passed automatically to the view.■ e.g. parameters of the Controller are filled up into that dictionary

    ■ And pass them to the View

    public IActionResult Welcome(string name, int numTimes = 1) { ViewData["Message"] = "Hello " + name; ViewData["NumTimes"] = numTimes; return View(); }

    @{ViewData["Title"] = "Welcome";}

    Welcome

    @for (int i = 0; i < (int)ViewData["NumTimes"]; i++) { @ViewData["Message"] }

  • 81 von 109School of Engineering © K. Rege, ZHAW

    Passing Model from the Controller to the View

    ■ Add a new Model Class in the Models Folder

    ■ In the Controller: inject it and pass the model parameter

    ■ In the View the Model is referenced via @model

    namespace WebMVCCore.Models{ public class WelcomeViewModel { public DateTime CurrentTime => DateTime.UtcNow; }}

    public IActionResult Welcome(WelcomeViewModel model) { return View(model);}

    @model [email protected]{ViewData["Title"] = "Welcome";}

    WelcomeThe current time is @Model.CurrentTime.ToShortTimeString()

    PageModel class file has byconvention the same name as theView Page

    PageModel class file has byconvention the same name as theView Page

    The Model is Injected when callingthe method of the controller andpassed to the view

    The Model is Injected when callingthe method of the controller andpassed to the view

  • 82 von 109School of Engineering © K. Rege, ZHAW

    Razor Page Syntax

    ■ For a file to act as a Razor content page■ The file extension is .cshtml■ The first line in the file is @page

    ■ It's possible (but not recommended) to combine c# code with view tags

    https://www.learnrazorpages.com/razor-pages

    @[email protected]{ var name = string.Empty; if (Request.HasFormContentType) { name = Request.Form["name"]; }}

    Name:

    @if (!string.IsNullOrEmpty(name)) {

    Hello @name!

    }

    The Razor code block is denoted by and [email protected]{ and is terminated with a closing }.The content within the block is standard C#code.

    The Razor code block is denoted by and [email protected]{ and is terminated with a closing }.The content within the block is standard C#code.

    https://docs.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-2.2

  • 83 von 109School of Engineering © K. Rege, ZHAW

    Razor Syntax

    ■ All code blocks must appear within @{ ... }

    ■ The value of variables are rendered into HTML by prefixing them with the @

    sign:

    ■ To render the variable number within the loop use @

    ■ Additional item as text only, is to prefix the text with @:

    @{ var numbers = Enumerable.Range(1, 10); //Get numbers from 1 - 10 foreach(var number in numbers){ ... }}

    The time is @DateTime.Now

    @{ var numbers = Enumerable.Range(1, 10); //Get numbers from 1 - 10 foreach(var number in numbers){ @(number * 10)@: * 10 = @(number * 10) }}

  • 84 von 109School of Engineering © K. Rege, ZHAW

    … Razor Syntax

    ■ Razor also looks for html tags. If it sees one, it jumps out of code and will only

    jump back into code when it sees a matching closing tag:

    ■ If you do not want to render html tags, you can use the tag to tell Razor

    where code ends and begins again. The tag is not rendered to the

    browser:

    @{ var numbers = Enumerable.Range(1, 10); //Get numbers from 1 - 10 foreach(var number in numbers){ @(number * 10)  }}

    @{ var numbers = Enumerable.Range(1, 10); //Get numbers from 1 - 10 foreach(var number in numbers){ @(number * 10) * 10 = @(number * 10)  }}

  • 85 von 109School of Engineering © K. Rege, ZHAW

    … Razor Syntax

    ■ Comments■ within a code block can denoted by two forward slashes //, as can be seen in all the preceding

    examples.■ Alternatively, you can use /*...*/ or @*...*@. If you want to put a server side comment outside of a

    code block, precede the line @*

    @{ /*Get numbers from 1 - 10*/ //Get numbers between 1 - 10 @*Get numbers between 1 - 10*@ var numbers = Enumerable.Range(1, 10); foreach(var number in numbers){ @number }}

  • 86 von 109School of Engineering © K. Rege, ZHAW

    Tag Helpers&

    Layout Pages

  • 87 von 109School of Engineering © K. Rege, ZHAW

    Tag Helpers

    ■ Reusable components for automating the generation of HTML in Razor Pages.

    They target specific HTML tags.

    ■ The ASP.NET Core framework includes a number of predefined tag helperstargeting many commonly used HTML elements as well as some custom tags:

  • 88 von 109School of Engineering © K. Rege, ZHAW

    Enabling Standard Tag Helpers

    ■ They are enabled by adding an @addTagHelper directive to the page, or more

    usually to a _ViewImports.cshtml file:■ by default is inherited by all files in the Pages folder and subfolders; making Tag Helpers available.

    ■ The @addTagHelper directive is followed by a wildcard character (*) to specifythat all tag helpers found in the specified assembly should be used, a

    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

  • 89 von 109School of Engineering © K. Rege, ZHAW

    Custom TagHelper

    ■ Define new email Tag Helpernamespace AuthoringTagHelpers.TagHelpers { [HtmlTargetElement("email")] public class EmailTagHelper : TagHelper { private const string EmailDomain = "zhaw.ch";

    // Can be passed via . // Pascal case gets translated into lower-kebab-case. [HtmlAttributeName("mail-to")] public string MailTo { get; set; } public override void Process(TagHelperContext context,

    TagHelperOutput output) { output.TagName = "a"; // Replaces with tag var address = MailTo + "@" + EmailDomain; output.Attributes.SetAttribute("href", "mailto:" + address); output.Content.SetContent(address); } }}

    @using [email protected] *, [email protected] *, AuthoringTagHelpers

    Support:
    Marketing:

    _ViewImports.cshtml to enable it

    new Tag used in page

  • 90 von 109School of Engineering © K. Rege, ZHAW

    Layout Pages

    ■ Most sites feature the same content on every page, e.g.■ Headers, footers, and navigation systems are just some examples■ Site-wide scripts and style sheets

    ■ Layout page acts as a template for all pages that reference it

    @RenderBody()

    @{ Layout = "_Layout";}

    _ViewStart.cshtml is included into every page

    _Layout.cshtml

  • 91 von 109School of Engineering © K. Rege, ZHAW

    Razor Pages = Web Applications

  • 92 von 109School of Engineering © K. Rege, ZHAW

    The MVVM Architectural Pattern

    ■ Model■ Data Container■ Business logic and Data

    ■ View■ Data display and user interactivity■ Implemented in WPF as a Page, UserControl, DataTemplate or custom control

    ■ Has little or no code behind

    ■ ViewModel■ Implements change notifications■ Maintains state for the View (communicates via data binding)■ UI logic and data for the View i.e. Abstracts the Model for View usage

    https://stackoverflow.com/questions/667781/what-is-the-difference-between-mvc-and-mvvm

  • 93 von 109School of Engineering © K. Rege, ZHAW

    Hello Razor Pages

    ■ Build Razor Pages Project

    dnet new webapp

    uncheck for developmentuncheck for development

  • 94 von 109School of Engineering © K. Rege, ZHAW

    What Is Razor Pages?

    ■ A "page-based" approach for building server-side rendered apps in ASP.NET

    Core

    ■ Can coexist with "traditional" MVC or Web API controllers.

    ■ Razor Pages offers much the same functionality as traditional MVC,■ But using a slightly different model by taking advantage of strong MV pairing.■ Each route (each pair of actions) becomes a separate Razor Page,

    ■ instead of grouping many similar actions together under a single controller.■ That page can have multiple handlers that each respond to a different HTTP verb, but use the same

    view.

    https://www.twilio.com/blog/introduction-asp-net-core-razor-pages

    https://www.endpoint.com/blog/2018/11/20/whats-the-deal-with-asp-net-core-razor-pages

    https://www.youtube.com/watch?v=yyBijyCI5Sk

  • 95 von 109School of Engineering © K. Rege, ZHAW

    Simple Razor Pages Differences to MVC

    ■ No Controller

    ■ No MVC but MVVM

    ■ Every View has an associated VM class

    that contains the code

    ■ This class inherits from PageModel

    public class IndexModel2 : PageModel { public string Message { get; private set; } = "PageModel in C#"; public void OnGet() { Message += $" Server time is { DateTime.Now }"; } }

    @[email protected] IndexModel2

    Separate page model

    @Model.Message

  • 96 von 109School of Engineering © K. Rege, ZHAW

    PageModel Files

    ■ The purpose of the Razor Pages PageModel class is to provide■ Separation between the UI layer (the .cshtml view file) and processing logic for the page.

    ■ Reasons to use Page Models:■ To reduces the complexity of the UI layer .■ For automated unit testing (of the Model)■ Smaller, reusable units of code for specific purposes

  • 97 von 109School of Engineering © K. Rege, ZHAW

    When should you use Razor Pages?

    ■ Razor Pages uses the same infrastructure as traditional MVC■ Possible to mix Razor Pages with MVC and Web API controllers all in the same app.■ Razor Pages also uses the same ASP.NET Core primitives as traditional MVC, so you still get

    model binding, etc.

    ■ When your Controller have little or no logic■ just returning views (for example, as the (generated) HomeController.

    ■ When you have HTML Forms with pairs of GET and POST actions.■ Razor Pages makes each pair a cohesive page,

    ■ which requires less cognitive overhead when developing, rather than having to jump betweenmultiple files.

    ■ When you were previously using ASP.NET Web Pages (WebMatrix).

  • 98 von 109School of Engineering © K. Rege, ZHAW

    Web APIs

  • 99 von 109School of Engineering © K. Rege, ZHAW

    Building Web APIs with ASP.NET Core

    ■ A Controller Class that responds to HTTP requests

    ■ The API Project is chosen

    dnet new webapi

    uncheck for developmentuncheck for development

    https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-2.2

    https://www.youtube.com/watch?v=aIkpVzqLuhA

    https://www.youtube.com/watch?v=J_MEscBWJYI

    Video TutorialsVideo Tutorials

  • 100 von 109School of Engineering © K. Rege, ZHAW

    Controller Class Generated

    ■ The following Controller is generated

    namespace WebService.Controllers {

    [Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { // GET api/values [HttpGet] public ActionResultGet() { return new string[] { "value1", "value2" }; }

    // GET api/values/5 [HttpGet("{id}")] public ActionResult Get(int id) { return "value"; }

    // POST api/values [HttpPost] public void Post([FromBody] string value) {}

    // PUT api/values/5 [HttpPut("{id}")] public void Put(int id,[FromBody] string value){}

    // DELETE api/values/5 [HttpDelete("{id}")] public void Delete(int id){} }}

    ■ All the Methods for the 4 REST CRUD

    Calls are generated

    ■ For the Controller Attributed Routing is

    applied

    ■ For the Methods that return values, adummy Value is returned

    ■ Scaffolding if e.g. Entity Framework

    should be used

  • 101 von 109School of Engineering © K. Rege, ZHAW

    Test the Web API

    ■ Launch in Command Prompt■ simply: dotnet run

    ■ Browser or Test with Tool e.g. Postman■ call url: localhost:/api/values

    ■ Values are returned as

    JSON String

    namespace WebService.Controllers{ [Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { // GET api/values [HttpGet] public ActionResult Get() { return new string[] { "value1", "value2" }; }

    name of the controllere.g. values

    name of the controllere.g. values

    set "launchBrowser": false inlaunchsettings.json and startwith VS

    set "launchBrowser": false inlaunchsettings.json and startwith VS

  • 102 von 109School of Engineering © K. Rege, ZHAW

    Web API with custom Types

    ■ Return Custom Types

    ■ Objects are returnes as JSON String

    public class Test { public string Name { get; set; } public int Age { get; set; } }

    [Route("api/[controller]")] [ApiController] public ActionResult Get() { Test test = new Test(); test.Name = "Hugo"; test.Age = 10; return test; }

  • 103 von 109School of Engineering © K. Rege, ZHAW

    Access to DataBase in API

    ■ Add DB Context

    ■ Register the database context

    ■ Next Steps: use Scaffolding (i.e. Code Generation)

    using Microsoft.EntityFrameworkCore;

    namespace TodoApi.Models{ public class TodoContext : DbContext { public TodoContext(DbContextOptions options) : base(options) {}

    public DbSet TodoItems { get; set; } }}

    https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-3.1

  • 104 von 109School of Engineering © K. Rege, ZHAW

    Attributes

    ■ Attributes are used to configure the behavior of web API controllers and action

    methods.

    ■ The example above used attributes to specify the HTTP method accepted andthe status codes returned:

    Attribute Notes[Route] Specifies URL pattern for a controller or action.[Bind] Specifies prefix and properties to include for model binding.[HttpGet] Identifies an action that supports the HTTP GET method.[Consumes] Specifies data types that an action accepts.[Produces] Specifies data types that an action returns....

    Attribute Notes[Route] Specifies URL pattern for a controller or action.[Bind] Specifies prefix and properties to include for model binding.[HttpGet] Identifies an action that supports the HTTP GET method.[Consumes] Specifies data types that an action accepts.[Produces] Specifies data types that an action returns....

    [Route("api/[controller]")][ApiController]public class ValuesController : ControllerBase {

    [HttpGet]public async Task CreateAsync(Pet pet) {

  • 105 von 109School of Engineering © K. Rege, ZHAW

    Binding source parameter inference

    ■ Defines the location at which an action parameter's value is found.

    ■ The following binding source attributes exist:

    ■ e.g. [FromQuery] -> indicates that the discontinuedOnly parameter value is

    provided in the request URL's query string

    ■ e.g. [FromBody -> indicates Parameter comes from (Post) Body

    Attribute Binding source[FromBody] Request body[FromForm] Form data in the request body[FromHeader] Request header[FromQuery] Request query string parameter[FromRoute] Route data from the current request[FromServices] The request service injected as an action parameter

    Attribute Binding source[FromBody] Request body[FromForm] Form data in the request body[FromHeader] Request header[FromQuery] Request query string parameter[FromRoute] Route data from the current request[FromServices] The request service injected as an action parameter

    [HttpGet]public async Task GetAsync( [FromQuery] bool discontinuedOnly = false){ List products = null;

    [HttpPost]public IActionResult Action2(Product product, [FromBody] Order order)

  • 106 von 109School of Engineering © K. Rege, ZHAW

    The Web API Client

    ■ Use of e.g. NewtonSoft JSON Libraryusing System;using System.Net.Http;using Newtonsoft.Json;namespace WebApiClient { public class Test { public string Name { get; set; } public int Age { get; set; }

    } class Program {

    public static Test GetTest(string url) { var httpClientHandler = new HttpClientHandler(); httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }; using (var httpClient = new HttpClient(httpClientHandler)) { var response = httpClient.GetStringAsync(new Uri(url)).Result; Test test = JsonConvert.DeserializeObject(response); return test; } }

    static void Main(string[] args) { Test test = GetTest("https://localhost:5001/api/values"); Console.WriteLine("Result "+test.Name+" "+test.Age); Console.ReadKey(); } }}

    To ignore Certificate checksTo ignore Certificate checks

  • 107 von 109School of Engineering © K. Rege, ZHAW

    Questions?I'm a very badhardcore dog!

  • 108 von 109School of Engineering © K. Rege, ZHAW

    Appendix Command dotnet new

    Console application console [C#], F#, VBClass library classlib [C#], F#, VBUnit test project mstest [C#], F#, VBxUnit test project xunit [C#], F#, VBNUnit test project nunit [C#], F#, VBRazor page page [C#]MVC ViewImports viewimports [C#]MVC ViewStart viewstart [C#]ASP.NET Core empty web [C#], F#ASP.NET Core Web App (MVC) mvc [C#], F#ASP.NET Core Web App razor, webapp [C#]ASP.NET Core with Angular angular [C#]ASP.NET Core with React.js react [C#]ASP.NET Core with React.js and Redux reactredux [C#]ASP.NET Core Web API webapi [C#], F#Razor class library razorclasslib [C#]global.json file globaljson NuGet config nugetconfig Web config webconfig Solution file sln https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-new

  • 109 von 109School of Engineering © K. Rege, ZHAW

    Base Class ControllerBase

    ■ Controller usually derives from ControllerBase

    ■ ControllerBase provides properties and methods that are useful for handlingHTTP

    [Route("api/[controller]")][ApiController]public class ValuesController : ControllerBase {

    [HttpPost][ProducesResponseType(StatusCodes.Status201Created)][ProducesResponseType(StatusCodes.Status400BadRequest)]public async Task CreateAsync(Pet pet) {

    await _repository.AddPetAsync(pet); return CreatedAtAction(nameof(GetByIdAsync), new { id = pet.Id }, pet);

    }

    CreatedAtAction Returns 201 status codeBadRequest Returns 400 status code.NotFound Returns 404 status code.PhysicalFile Returns a file.TryUpdateModelAsync Invokes model binding.TryValidateModel Invokes model validation...

    CreatedAtAction Returns 201 status codeBadRequest Returns 400 status code.NotFound Returns 404 status code.PhysicalFile Returns a file.TryUpdateModelAsync Invokes model binding.TryValidateModel Invokes model validation...