asp.net core - radar.zhaw.chradar.zhaw.ch/~rege/dnet_fs19/dnet2_10.pdf · benefits of asp.net core...

Post on 27-May-2020

36 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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 111School 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 111School of Engineering © K. Rege, ZHAW

… ASP.NET Core

■ Is part - as its name suggest - Core Library

5 von 111School 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 111School 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

■ Actual Version is Core 3.0 (preview)

■ 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 111School 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 ModularModular

8 von 111School 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

9 von 111School of Engineering © K. Rege, ZHAW

Benefits of ASP.NET Core - Cross Platform

Asp.NET Core Applications can be developed and run across differentplatforms

■ Windows

■ macOS

■ Linux

APS.NET Core applications can be hosted on

■ IIS

■ Apache

■ Docker

■ Self-host in a process

10 von 111School 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/

ViewResultViewResultActionResult<T>ActionResult<T>

IActionResultIActionResult

11 von 111School 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

12 von 111School 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.

13 von 111School of Engineering © K. Rege, ZHAW

Installation

■ VS 17 with .NET Core 2.1 Development Tools

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

14 von 111School of Engineering © K. Rege, ZHAW

ASP.NET Core

15 von 111School of Engineering © K. Rege, ZHAW

uncheck fordevelopment

uncheck fordevelopment

ASP.NET Core Project Types

■ Create an New Empty Project

Generates minimum ofadditional files

Generates minimum ofadditional files

Generates MVC CodeSamples, CSS, HTML

Generates MVC CodeSamples, CSS, HTML

Generates REST HTTPServer, i.e. ControllersFolder

Generates REST HTTPServer, i.e. ControllersFolder

Generates Razor Pages APPMVC without "C"

Generates Razor Pages APPMVC without "C"

Razor Class Library Project,Reusable Razor Component

Razor Class Library Project,Reusable Razor Component

Legacy ;-) WebApplication support

Legacy ;-) WebApplication support

16 von 111School 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

17 von 111School of Engineering © K. Rege, ZHAW

Hello World

18 von 111School of Engineering © K. Rege, ZHAW

uncheck for developmentuncheck for development

New Project

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

■ Choose Empty as Web Application Type

Generates minimum ofadditional files

Generates minimum ofadditional files

19 von 111School 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

20 von 111School 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

■ <projectname>.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.

21 von 111School 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<TStartup> method ouf 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) => WebHost.CreateDefaultBuilder(args).UseStartup<Startup>(); }}

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

22 von 111School 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 (DI

■ 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-2.2

Use this method to configure theHTTP request pipeline.

Use this method to configure theHTTP request pipeline.

Middleware that is calledMiddleware that is called

23 von 111School of Engineering © K. Rege, ZHAW

Configuration Files

24 von 111School 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" }}}}

//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

25 von 111School of Engineering © K. Rege, ZHAW

<project name>.csproj File

■ TargetFramework■ which framework should be used■ HostingModel

■ Internal: Web Server thathosts .NET Core App

■ Use External Web Server thatdispatches calls - as forewardProxy

<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>netcoreapp2.2</TargetFramework> <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.App" /> <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" /> </ItemGroup></Project>

"full blown" .net coreWebServer

"full blown" .net coreWebServer

Development WebServerDevelopment WebServer

WebMVCCore.csproj

26 von 111School 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

dependent of environmentoverrides general settings

dependent of environmentoverrides general settings

Pre

ced

ence

added new environmentvariable

added new environmentvariable

appsettings.json

Azure Key VaultAzure Key Vault https://www.humankode.com/asp-net-core/how-to-store-secrets-in-azure-key-vault-using-net-core

Injected Injected

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

27 von 111School of Engineering © K. Rege, ZHAW

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

■ The Value can now be accessed in a Module via the _config variable

■ also used in the generated Start method e.g. to configure Middleware■ e.g. IsDevelopment() returns true if "ASPNETCORE_ENVIRONMENT": "Development"

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

28 von 111School of Engineering © K. Rege, ZHAW

Middleware

29 von 111School 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

30 von 111School of Engineering © K. Rege, ZHAW

Handles a Requests (terminating)

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

Startup 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) { app.Run(async context => { await context.Response.WriteAsync("Hello, World!"); }); }}

31 von 111School 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) { app.Use(async (context, next) => { // Do work that doesn't write to the Response. await next.Invoke(); // Do logging or other work that doesn't write to the Response. });

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

32 von 111School 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" });}

33 von 111School of Engineering © K. Rege, ZHAW

Add a Middleware via NuGet Package

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

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

and diagnostics information

■ Simply add the new Middleware to

processing pipeline

public void Configure(IApplicationBuilder app) { app.UseIISPlatformHandler(); app.UseRuntimeInfoPage();

app.Run(async (context) => { var msg = Configuration["message"]; await context.Response.WriteAsync(msg); });}

34 von 111School of Engineering © K. Rege, ZHAW

Add a Logger 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<Startup> logger) {

will be injectedwill be injected

35 von 111School of Engineering © K. Rege, ZHAW

Custom Middleware Stopwatch

■ Write Middleware that measures Request timepublic 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(); 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<StopwatchMiddleware>(); 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

36 von 111School of Engineering © K. Rege, ZHAW

Custom Middleware Logger

■ Write a Middleware class e.g. for logging request and responses■ The class will need a constructor that takes two arguments

■ both will be provided by ASP.NET Core’s dependency injection system.■ The first is a RequestDelegate for the next piece of middleware to be called.■ The second is an ILoggerFactory which will be used to create a logger.

public class RequestResponseLoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger;

public RequestResponseLoggingMiddleware(RequestDelegate next, ILoggerFactory loggerFactory) { _next = next; loggerFactory.AddConsole().AddDebug(); _logger = loggerFactory.CreateLogger<RequestResponseLoggingMiddleware>(); }}

public static class RequestResponseLoggingMiddlewareExtensions { public static IApplicationBuilder UseRequestResponseLogging(this IApplicationBuilder builder) { return builder.UseMiddleware<RequestResponseLoggingMiddleware>(); }}

as new extensionmethod for theapplication builder

as new extensionmethod for theapplication builder

https://www.tutorialspoint.com/asp.net_core/asp.net_core_middleware.htmhttps://elanderson.net/2017/02/log-requests-and-responses-in-asp-net-core/

37 von 111School of Engineering © K. Rege, ZHAW

… Custom Logger Middleware Helper Methods

■ create the string that will be logged from the request data

■ dito for the response

private async Task<string> FormatRequest(HttpRequest request){ var body = request.Body; request.EnableRewind(); var buffer = new byte[Convert.ToInt32(request.ContentLength)]; await request.Body.ReadAsync(buffer, 0, buffer.Length); var bodyAsText = Encoding.UTF8.GetString(buffer); request.Body = body; return $"{request.Scheme} {request.Host}{request.Path} {request.QueryString} {bodyAsText}";}

private async Task<string> FormatResponse(HttpResponse response){ response.Body.Seek(0, SeekOrigin.Begin); var text = await new StreamReader(response.Body).ReadToEndAsync(); response.Body.Seek(0, SeekOrigin.Begin);

return $"Response {text}";}

copy request datastream intomemory stream

copy request datastream intomemory stream

38 von 111School of Engineering © K. Rege, ZHAW

… Custom Logger Middleware

■ This is the actual execution Invoke method of the Middleware■ it logs the the data before and after the next Middleware in the pipeline

■ To enable the new Middleware simply call extension method

public async Task Invoke(HttpContext context){ _logger.LogInformation(await FormatRequest(context.Request)); var originalBodyStream = context.Response.Body; using (var responseBody = new MemoryStream()) { context.Response.Body = responseBody;

await _next(context);

_logger.LogInformation(await FormatResponse(context.Response)); await responseBody.CopyToAsync(originalBodyStream); }}

app.UseRequestResponseLogging();

39 von 111School of Engineering © K. Rege, ZHAW

Dependency Injection

40 von 111School 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

41 von 111School 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<T>■ ILoggerFactory loggerFactory■ ….

42 von 111School 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<MyDependency> _logger;

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

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

return Task.FromResult(0); }}

43 von 111School 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<MyDependency>), typeof(Logger<MyDependency>)); services.AddScoped<IMyDependency, MyDependency>(); }

// 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 arecreated the first time they'rerequested

Singleton lifetime services arecreated the first time they'rerequested

44 von 111School of Engineering © K. Rege, ZHAW

General Principles

■ Dependency 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<XXX>■ 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 }

...}

45 von 111School of Engineering © K. Rege, ZHAW

MVCOverview

46 von 111School 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 111School 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 111School 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■ 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-2.2

49 von 111School 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■ Exposes commands (ICommand) to be used by the View

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

50 von 111School of Engineering © K. Rege, ZHAW

MVC Overview

51 von 111School 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

52 von 111School 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.■ Razor markup provides a productive syntax for Razor Pages and MVC Razor views.

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

■ 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.

53 von 111School 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..."; } }

54 von 111School 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 without breakingexisting stored URLs

Also: Application can beredesigned without breakingexisting stored URLs

55 von 111School 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 cleanly 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"

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

@model IEnumerable<Product><ul> @foreach (Product p in Model) { <li>@p.Name</li> }</ul>

56 von 111School of Engineering © K. Rege, ZHAW

View: Razor (View) Components

■ 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

■ Same as (former) partial views, but with associated logic.

57 von 111School of Engineering © K. Rege, ZHAW

Models

■ Perform user actions and/or retrieve results of queries

■ Check for Data validation■ Decorating your model object with data annotation 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; }}

58 von 111School of Engineering © K. Rege, ZHAW

Model Binding

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

HTTP headers) into objects that the controller can handle

■ Your controller logic doesn't have to do the work of figuring out the incomingrequest data

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

public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null) {... }

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

59 von 111School of Engineering © K. Rege, ZHAW

Dependency Injection of Model and View

■ Controllers can request needed services through their constructors

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

@inject SomeService ServiceName<!DOCTYPE html><html lang="en"><head> <title>@ServiceName.GetTitle</title></head><body> <h1>@ServiceName.GetTitle</h1></body></html>

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

60 von 111School 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

61 von 111School 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, <environment>) or to modify thebehavior of existing tags (for example, <label>).

■ 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.

<p> Thank you for confirming your email. Please <a asp-controller="Account" asp-action="Login">Click here to Log in</a>.</p>

<environment names="Development"> <script src="~/lib/jquery/dist/jquery.js"></script></environment><environment names="Staging,Production"> <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js" asp-fallback-src="~/lib/jquery/dist/jquery.min.js" asp-fallback-test="window.jQuery"> </script></environment>

LinkTagHelper to create alink to the Login actionof the AccountsController:

LinkTagHelper to create alink to the Login actionof the AccountsController:

EnvironmentTagHelper use different scripts inyour views based on the runtime environment

EnvironmentTagHelper use different scripts inyour views based on the runtime environment

62 von 111School of Engineering © K. Rege, ZHAW

Service: Web APIs

■ For building Web APIs i.e. Services that can be called via the Internet■ web services that reach different clients including browsers and mobile devices.

■ Support for HTTP content-negotiation■ with built-in support to format data automatically as JSON or XML■ Write custom formatters to add support for your own formats

■ Easily enable support for cross-origin resource sharing (CORS) so that your

Web APIs can be shared across multiple Web applications.

63 von 111School of Engineering © K. Rege, ZHAW

Routing

64 von 111School of Engineering © K. Rege, ZHAW

Routing

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

incoming requests to endpoints.

■ Routes are defined in the app and configured when the app starts.

■ Route can optionally extract values from the URL contained in the request, andthese values can then be used for request processing.

■ Versions■ specify the compatibility version to the MVC services registration in

class Startup void ConfigureServices() { ... services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

https://stackoverflow.com/questions/53758940/asp-net-core-2-2-upgrade-routing-from-2-1-to-2-2

breaking changes in 2.2breaking changes in 2.2

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

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

comparable JSF - Page Navigation Mechanismcomparable JSF - Page Navigation Mechanism

65 von 111School 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

66 von 111School 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?}");

67 von 111School 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" });

68 von 111School 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.

■ 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.

69 von 111School 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 slugify transformer.

70 von 111School of Engineering © K. Rege, ZHAW

… Route Templates

■ Table demonstrates example of route templates

71 von 111School 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?}.

72 von 111School 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 Constraintservices.AddRouting(options =>{ options.ConstraintMap.Add("customName", typeof(MyCustomConstraint));});

73 von 111School 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.

■ ASP.NET Core provides API conventions for using a parameter transformerswith generated routes:

■ Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention

■ Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteTransformerConvention (for Razor)

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?}");

74 von 111School 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) { ... }}

75 von 111School of Engineering © K. Rege, ZHAW

Controllers

76 von 111School 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-2.2

77 von 111School 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 }); } }}

78 von 111School 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

79 von 111School 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}");}

80 von 111School of Engineering © K. Rege, ZHAW

Views

81 von 111School 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";}

<h2>Index</h2><p>Hello from our View Template!</p>

82 von 111School 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";}

<h2>Welcome</h2><ul> @for (int i = 0; i < (int)ViewData["NumTimes"]; i++) { <li>@ViewData["Message"]</li> }</ul>

83 von 111School 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 WelcomeViewModel@{ViewData["Title"] = "Welcome";}

<h2>Welcome</h2><div>The current time is @Model.CurrentTime.ToShortTimeString() </div>

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

84 von 111School of Engineering © K. Rege, ZHAW

PageModel Files

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

■ There are a number of reasons why this separation is beneficial:■ It reduces the complexity of the UI layer making it easier to maintain.■ It facilitates automated unit testing.■ It enables greater flexibility for teams in that one member can work on the view while another can

work on the processing logic.■ It encourages smaller, reusable units of code for specific purposes, which aids maintenance and

scalability

85 von 111School 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

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

<div style="margin-top:30px;"> <form method="post"> <div>Name: <input name="name" /></div> <div><input type="submit" /></div> </form></div><div> @if (!string.IsNullOrEmpty(name)) { <p>Hello @name!</p> }</div>

The Razor code block is denoted by and opening@{ and is terminated with a closing }.The content within the block is standard C#code.

The Razor code block is denoted by and opening@{ 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

86 von 111School 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) }}

87 von 111School 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 <text> tag to tell Razor

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

browser:

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

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

88 von 111School 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 }}

89 von 111School of Engineering © K. Rege, ZHAW

Tag Helpers&

Layout Pages

90 von 111School 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:

91 von 111School of Engineering © K. Rege, ZHAW

Enabling 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

92 von 111School of Engineering © K. Rege, ZHAW

Custom TagHelper

■ Define new email Tag Helper

namespace AuthoringTagHelpers.TagHelpers { [HtmlTargetElement("email")] public class EmailTagHelper : TagHelper { private const string EmailDomain = "contoso.com";

// Can be passed via <email mail-to="..." />. // 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 <email> with <a> tag var address = MailTo + "@" + EmailDomain; output.Attributes.SetAttribute("href", "mailto:" + address); output.Content.SetContent(address); } }}

@using AuthoringTagHelpers@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers@addTagHelper *, AuthoringTagHelpers

<address> <strong>Support:</strong><email mail-to="Support"></email><br /> <strong>Marketing:</strong><email mail-to="Marketing"></email></address>

_ViewImports.cshtml to enable it

new Tag used in page

93 von 111School 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

<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <title></title> <link href="/css/site.css" rel="stylesheet" type="text/css" /> </head> <body> @RenderBody() </body></html>

@{ Layout = "_Layout";}

_ViewStart.cshtml is included into every page

a _Layout.cshtml is already generated

94 von 111School of Engineering © K. Rege, ZHAW

Razor Pages = Web Applications

95 von 111School of Engineering © K. Rege, ZHAW

Hello Razor Pages

■ Build Razor Pages Project

uncheck for developmentuncheck for development

dnet new webapp

96 von 111School 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

97 von 111School 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 }"; } }

@page@model IndexModel2

<h2>Separate page model</h2><p> @Model.Message</p>

98 von 111School of Engineering © K. Rege, ZHAW

When should you use Razor Pages?

■ Razor Pages uses the same infrastructure as traditional MVC■ can 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).

99 von 111School of Engineering © K. Rege, ZHAW

Web APIs

100 von 111School 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

101 von 111School 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 ActionResult<IEnumerable<string>>Get() { return new string[] { "value1", "value2" }; }

// GET api/values/5 [HttpGet("{id}")] public ActionResult<string> 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

102 von 111School 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:<port>/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<IEnumerable<string>> 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

103 von 111School of Engineering © K. Rege, ZHAW

Web API with custom Types

■ To Return Custom Type

■ The Class is return as JSON String

public class Test { public string Name { get; set; } public int Age { get; set; } } [Route("api/[controller]")] [ApiController] public ActionResult<Test> Get() { Test test = new Test(); test.Name = "Hugo"; test.Age = 10; return test; }

104 von 111School of Engineering © K. Rege, ZHAW

Access to DataBase in API

■ Add DB Context

■ Register the database context

■ Next Steps: see following Tutorial

■ Also Scaffolding is supported

using Microsoft.EntityFrameworkCore;

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

public DbSet<TodoItem> TodoItems { get; set; } }}

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

105 von 111School 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<ActionResult<Pet>> 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...

106 von 111School 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<ActionResult<Pet>> CreateAsync(Pet pet) {

107 von 111School 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<ActionResult<List<Product>>> GetAsync( [FromQuery] bool discontinuedOnly = false){ List<Product> products = null;

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

108 von 111School of Engineering © K. Rege, ZHAW

The Web API Client

■ Use of 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<Test>(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

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

Hosting Model

https://docs.microsoft.com/de-de/aspnet/core/fundamentals/servers/?view=aspnetcore-2.2

110 von 111School of Engineering © K. Rege, ZHAW

Questions?I'm a very badhardcore dog!

111 von 111School 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

top related