Fully updated to ASP.NET 5.0, ASP.NET Core in Action, Second Edition is a hands-on primer to building cross-platform web applications with your C# and .NET skills. Even if you've never worked with ASP.NET you'll start creating productive cross-platform web apps fast. And don’t worry about late-breaking changes to ASP.NET Core.
About the technology
Build full-stack web applications that run anywhere. Developers love ASP.NET Core for its libraries and pre-built components that maximize productivity. Version 5.0 offers new features for server-side apps, as well as background services for cross-platform development.
About the book
ASP.NET Core in Action, Second Edition is a comprehensive guide to creating web applications with ASP.NET Core 5.0. Go from basic HTTP concepts to advanced framework customization. Illustrations and annotated code make learning visual and easy. Master logins, dependency injection, security, and more. This updated edition covers the latest features, including Razor Pages and the new hosting paradigm.
What's inside
* Developing apps for Windows and non-Windows servers
* Configuring applications
* Building custom components
* Logging, testing, and security
About the reader
For intermediate C# developers.
Author(s): Andrew Lock
Edition: 2
Publisher: Manning
Year: 2021
Language: English
Pages: 832
ASP.NET Core in Action
brief contents
contents
preface
acknowledgments
about this book
Who should read this book
How this book is organized: A roadmap
About the code
liveBook discussion forum
about the author
about the cover illustration
Part 1—Getting started with ASP.NET Core
1 Getting started with ASP.NET Core
1.1 An introduction to ASP.NET Core
1.1.1 Using a web framework
1.1.2 What is ASP.NET Core?
1.2 When to choose ASP.NET Core
1.2.1 What type of applications can you build?
1.2.2 If you’re new to .NET development
1.2.3 If you’re a .NET Framework developer creating a new application
1.2.4 Converting an existing ASP.NET application to ASP.NET Core
1.3 How does ASP.NET Core work?
1.3.1 How does an HTTP web request work?
1.3.2 How does ASP.NET Core process a request?
1.4 What you will learn in this book
Summary
2 Your first application
2.1 A brief overview of an ASP.NET Core application
2.2 Creating your first ASP.NET Core application
2.2.1 Using a template to get started
2.2.2 Building the application
2.3 Running the web application
2.4 Understanding the project layout
2.5 The .csproj project file: Defining your dependencies
2.6 The Program class: Building a web host
2.7 The Startup class: Configuring your application
2.7.1 Adding and configuring services
2.7.2 Defining how requests are handled with middleware
2.8 Generating responses with Razor Pages
2.8.1 Generating HTML with Razor Pages
2.8.2 Handling request logic with PageModels and handlers
Summary
3 Handling requests with the middleware pipeline
3.1 What is middleware?
3.2 Combining middleware in a pipeline
3.2.1 Simple pipeline scenario 1: A holding page
3.2.2 Simple pipeline scenario 2: Handling static files
3.2.3 Simple pipeline scenario 3: A Razor Pages application
3.3 Handling errors using middleware
3.3.1 Viewing exceptions in development: DeveloperExceptionPage
3.3.2 Handling exceptions in production: ExceptionHandlerMiddleware
3.3.3 Handling other errors: StatusCodePagesMiddleware
3.3.4 Error handling middleware and Web APIs
Summary
4 Creating a website with Razor Pages
4.1 An introduction to Razor Pages
4.1.1 Exploring a typical Razor Page
4.1.2 The MVC design pattern
4.1.3 Applying the MVC design pattern to Razor Pages
4.1.4 Adding Razor Pages to your application
4.2 Razor Pages vs. MVC in ASP.NET Core
4.2.1 MVC controllers in ASP.NET Core
4.2.2 The benefits of Razor Pages
4.2.3 When to choose MVC controllers over Razor Pages
4.3 Razor Pages and page handlers
4.3.1 Accepting parameters to page handlers
4.3.2 Returning responses with ActionResults
Summary
5 Mapping URLs to Razor Pages using routing
5.1 What is routing?
5.2 Routing in ASP.NET Core
5.2.1 Using endpoint routing in ASP.NET Core
5.2.2 Convention-based routing vs. attribute routing
5.2.3 Routing to Razor Pages
5.3 Customizing Razor Page route templates
5.3.1 Adding a segment to a Razor Page route template
5.3.2 Replacing a Razor Page route template completely
5.4 Exploring the route template syntax
5.4.1 Using optional and default values
5.4.2 Adding additional constraints to route parameters
5.4.3 Matching arbitrary URLs with the catch-all parameter
5.5 Generating URLs from route parameters
5.5.1 Generating URLs for a Razor Page
5.5.2 Generating URLs for an MVC controller
5.5.3 Generating URLs with ActionResults
5.5.4 Generating URLs from other parts of your application
5.6 Selecting a page handler to invoke
5.7 Customizing conventions with Razor Pages
Summary
6 The binding model: Retrieving and validating user input
6.1 Understanding the models in Razor Pages and MVC
6.2 From request to model: Making the request useful
6.2.1 Binding simple types
6.2.2 Binding complex types
6.2.3 Choosing a binding source
6.3 Handling user input with model validation
6.3.1 The need for validation
6.3.2 Using DataAnnotations attributes for validation
6.3.3 Validating on the server for safety
6.3.4 Validating on the client for user experience
6.4 Organizing your binding models in Razor Pages
Summary
7 Rendering HTML using Razor views
7.1 Views: Rendering the user interface
7.2 Creating Razor views
7.2.1 Razor views and code-behind
7.2.2 Introducing Razor templates
7.2.3 Passing data to views
7.3 Creating dynamic web pages with Razor
7.3.1 Using C# in Razor templates
7.3.2 Adding loops and conditionals to Razor templates
7.3.3 Rendering HTML with Raw
7.4 Layouts, partial views, and _ViewStart
7.4.1 Using layouts for shared markup
7.4.2 Overriding parent layouts using sections
7.4.3 Using partial views to encapsulate markup
7.4.4 Running code on every view with _ViewStart and _ViewImports
7.5 Selecting a view from an MVC controller
Summary
8 Building forms with Tag Helpers
8.1 Catering to editors with Tag Helpers
8.2 Creating forms using Tag Helpers
8.2.1 The Form Tag Helper
8.2.2 The Label Tag Helper
8.2.3 The Input and Textarea Tag Helpers
8.2.4 The Select Tag Helper
8.2.5 The Validation Message and Validation Summary Tag Helpers
8.3 Generating links with the Anchor Tag Helper
8.4 Cache-busting with the Append Version Tag Helper
8.5 Using conditional markup with the Environment Tag Helper
Summary
9 Creating a Web API for mobile and client applications using MVC
9.1 What is a Web API and when should you use one?
9.2 Creating your first Web API project
9.3 Applying the MVC design pattern to a Web API
9.4 Attribute routing: Linking action methods to URLs
9.4.1 Combining route attributes to keep your route templates DRY
9.4.2 Using token replacement to reduce duplication in attribute routing
9.4.3 Handling HTTP verbs with attribute routing
9.5 Using common conventions with the [ApiController] attribute
9.6 Generating a response from a model
9.6.1 Customizing the default formatters: Adding XML support
9.6.2 Choosing a response format with content negotiation
Summary
Part 2—Building complete applications
10 Service configuration with dependency injection
10.1 Introduction to dependency injection
10.1.1 Understanding the benefits of dependency injection
10.1.2 Creating loosely coupled code
10.1.3 Dependency injection in ASP.NET Core
10.2 Using the dependency injection container
10.2.1 Adding ASP.NET Core framework services to the container
10.2.2 Registering your own services with the container
10.2.3 Registering services using objects and lambdas
10.2.4 Registering a service in the container multiple times
10.2.5 Injecting services into action methods, page handlers, and views
10.3 Understanding lifetimes: When are services created?
10.3.1 Transient: Everyone is unique
10.3.2 Scoped: Let’s stick together
10.3.3 Singleton: There can be only one
10.3.4 Keeping an eye out for captured dependencies
Summary
11 Configuring an ASP.NET Core application
11.1 Introducing the ASP.NET Core configuration model
11.2 Configuring your application with CreateDefaultBuilder
11.3 Building a configuration object for your app
11.3.1 Adding a configuration provider in Program.cs
11.3.2 Using multiple providers to override configuration values
11.3.3 Storing configuration secrets safely
11.3.4 Reloading configuration values when they change
11.4 Using strongly typed settings with the options pattern
11.4.1 Introducing the IOptions interface
11.4.2 Reloading strongly typed options with IOptionsSnapshot
11.4.3 Designing your options classes for automatic binding
11.4.4 Binding strongly typed settings without the IOptions interface
11.5 Configuring an application for multiple environments
11.5.1 Identifying the hosting environment
11.5.2 Loading environment-specific configuration files
11.5.3 Setting the hosting environment
Summary
12 Saving data with Entity Framework Core
12.1 Introducing Entity Framework Core
12.1.1 What is EF Core?
12.1.2 Why use an object-relational mapper?
12.1.3 When should you choose EF Core?
12.1.4 Mapping a database to your application code
12.2 Adding EF Core to an application
12.2.1 Choosing a database provider and installing EF Core
12.2.2 Building a data model
12.2.3 Registering a data context
12.3 Managing changes with migrations
12.3.1 Creating your first migration
12.3.2 Adding a second migration
12.4 Querying data from and saving data to the database
12.4.1 Creating a record
12.4.2 Loading a list of records
12.4.3 Loading a single record
12.4.4 Updating a model with changes
12.5 Using EF Core in production applications
Summary
13 The MVC and Razor Pages filter pipeline
13.1 Understanding filters and when to use them
13.1.1 The MVC filter pipeline
13.1.2 The Razor Pages filter pipeline
13.1.3 Filters or middleware: Which should you choose?
13.1.4 Creating a simple filter
13.1.5 Adding filters to your actions, controllers, Razor Pages, and globally
13.1.6 Understanding the order of filter execution
13.2 Creating custom filters for your application
13.2.1 Authorization filters: Protecting your APIs
13.2.2 Resource filters: Short-circuiting your action methods
13.2.3 Action filters: Customizing model binding and action results
13.2.4 Exception filters: Custom exception handling for your action methods
13.2.5 Result filters: Customizing action results before they execute
13.2.6 Page filters: Customizing model binding for Razor Pages
13.3 Understanding pipeline short-circuiting
13.4 Using dependency injection with filter attributes
Summary
14 Authentication: Adding users to your application with Identity
14.1 Introducing authentication and authorization
14.1.1 Understanding users and claims in ASP.NET Core
14.1.2 Authentication in ASP.NET Core: Services and middleware
14.1.3 Authentication for APIs and distributed applications
14.2 What is ASP.NET Core Identity?
14.3 Creating a project that uses ASP.NET Core Identity
14.3.1 Creating the project from a template
14.3.2 Exploring the template in Solution Explorer
14.3.3 The ASP.NET Core Identity data model
14.3.4 Interacting with ASP.NET Core Identity
14.4 Adding ASP.NET Core Identity to an existing project
14.4.1 Configuring the ASP.NET Core Identity services and middleware
14.4.2 Updating the EF Core data model to support Identity
14.4.3 Updating the Razor views to link to the Identity UI
14.5 Customizing a page in ASP.NET Core Identity’s default UI
14.6 Managing users: Adding custom data to users
Summary
15 Authorization: Securing your application
15.1 Introduction to authorization
15.2 Authorization in ASP.NET Core
15.2.1 Preventing anonymous users from accessing your application
15.2.2 Handling unauthorized requests
15.3 Using policies for claims-based authorization
15.4 Creating custom policies for authorization
15.4.1 Requirements and handlers: The building blocks of a policy
15.4.2 Creating a policy with a custom requirement and handler
15.5 Controlling access with resource-based authorization
15.5.1 Manually authorizing requests with IAuthorizationService
15.5.2 Creating a resource-based AuthorizationHandler
15.6 Hiding elements in Razor templates from unauthorized users
Summary
16 Publishing and deploying your application
16.1 Understanding the ASP.NET Core hosting model
16.1.1 Running vs. publishing an ASP.NET Core app
16.1.2 Choosing a deployment method for your application
16.2 Publishing your app to IIS
16.2.1 Configuring IIS for ASP.NET Core
16.2.2 Preparing and publishing your application to IIS
16.3 Hosting an application on Linux
16.3.1 Running an ASP.NET Core app behind a reverse proxy on Linux
16.3.2 Preparing your app for deployment to Linux
16.4 Configuring the URLs for your application
16.5 Optimizing your client-side assets using BundlerMinifier
16.5.1 Speeding up an app using bundling and minification
16.5.2 Adding BundlerMinifier to your application
16.5.3 Using minified files in production with the Environment Tag Helper
16.5.4 Serving common files from a CDN
Summary
Part 3—Extending your applications
17 Monitoring and troubleshooting errors with logging
17.1 Using logging effectively in a production app
17.1.1 Highlighting problems using custom log messages
17.1.2 The ASP.NET Core logging abstractions
17.2 Adding log messages to your application
17.2.1 Log level: How important is the log message?
17.2.2 Log category: Which component created the log
17.2.3 Formatting messages and capturing parameter values
17.3 Controlling where logs are written using logging providers
17.3.1 Adding a new logging provider to your application
17.3.2 Replacing the default ILoggerFactory with Serilog
17.4 Changing log verbosity with filtering
17.5 Structured logging: Creating searchable, useful logs
17.5.1 Adding a structured logging provider to your app
17.5.2 Using scopes to add additional properties to your logs
Summary
18 Improving your application’s security
18.1 Adding HTTPS to an application
18.1.1 Using the ASP.NET Core HTTPS development certificates
18.1.2 Configuring Kestrel with a production HTTPS certificate
18.1.3 Enforcing HTTPS for your whole app
18.2 Defending against cross-site scripting (XSS) attacks
18.3 Protecting from cross-site request forgery (CSRF) attacks
18.4 Calling your web APIs from other domains using CORS
18.4.1 Understanding CORS and how it works
18.4.2 Adding a global CORS policy to your whole app
18.4.3 Adding CORS to specific Web API actions with EnableCorsAttribute
18.4.4 Configuring CORS policies
18.5 Exploring other attack vectors
18.5.1 Detecting and avoiding open redirect attacks
18.5.2 Avoiding SQL injection attacks with EF Core and parameterization
18.5.3 Preventing insecure direct object references
18.5.4 Protecting your users’ passwords and data
Summary
19 Building custom components
19.1 Customizing your middleware pipeline
19.1.1 Creating simple endpoints with the Run extension
19.1.2 Branching middleware pipelines with the Map extension
19.1.3 Adding to the pipeline with the Use extension
19.1.4 Building a custom middleware component
19.2 Creating custom endpoints with endpoint routing
19.2.1 Creating a custom endpoint routing component
19.2.2 Creating simple endpoints with MapGet and WriteJsonAsync
19.2.3 Applying authorization to endpoints
19.3 Handling complex configuration requirements
19.3.1 Partially building configuration to configure additional providers
19.3.2 Using services to configure IOptions with IConfigureOptions
19.4 Using a third-party dependency injection container
Summary
20 Building custom MVC and Razor Pages components
20.1 Creating a custom Razor Tag Helper
20.1.1 Printing environment information with a custom Tag Helper
20.1.2 Creating a custom Tag Helper to conditionally hide elements
20.1.3 Creating a Tag Helper to convert Markdown to HTML
20.2 View components: Adding logic to partial views
20.3 Building a custom validation attribute
20.4 Replacing the validation framework with FluentValidation
20.4.1 Comparing FluentValidation to DataAnnotations attributes
20.4.2 Adding FluentValidation to your application
Summary
21 Calling remote APIs with IHttpClientFactory
21.1 Calling HTTP APIs: The problem with HttpClient
21.2 Creating HttpClients with IHttpClientFactory
21.2.1 Using IHttpClientFactory to manage HttpClientHandler lifetime
21.2.2 Configuring named clients at registration time
21.2.3 Using typed clients to encapsulate HTTP calls
21.3 Handling transient HTTP errors with Polly
21.4 Creating a custom HttpMessageHandler
Summary
22 Building background tasks and services
22.1 Running background tasks with IHostedService
22.1.1 Running background tasks on a timer
22.1.2 Using scoped services in background tasks
22.2 Creating headless worker services using IHost
22.2.1 Creating a worker service from a template
22.2.2 Running worker services in production
22.3 Coordinating background tasks using Quartz.NET
22.3.1 Installing Quartz.NET in an ASP.NET Core application
22.3.2 Configuring a job to run on a schedule with Quartz.NET
22.3.3 Using clustering to add redundancy to your background tasks
Summary
23 Testing your application
23.1 An introduction to testing in ASP.NET Core
23.2 Unit testing with xUnit
23.2.1 Creating your first test project
23.2.2 Running tests with dotnet test
23.2.3 Referencing your app from your test project
23.2.4 Adding Fact and Theory unit tests
23.2.5 Testing failure conditions
23.3 Unit testing custom middleware
23.4 Unit testing API controllers
23.5 Integration testing: Testing your whole app in-memory
23.5.1 Creating a TestServer using the Test Host package
23.5.2 Testing your application with WebApplicationFactory
23.5.3 Replacing dependencies in WebApplicationFactory
23.5.4 Reducing duplication by creating a custom WebApplicationFactory
23.6 Isolating the database with an in-memory EF Core provider
Summary
Appendix A—Preparing your development environment
A.1 Installing the .NET SDK
A.2 Choosing an IDE or editor
A.2.1 Visual Studio (Windows)
A.2.2 JetBrains Rider (Windows, Linux, macOS)
A.2.3 Visual Studio for Mac (macOS)
A.2.4 Visual Studio Code (Windows, Linux, macOS)
Appendix B—Understanding the .NET ecosystem
B.1 The evolution of .NET into .NET 5.0
B.1.1 Exploring the .NET platforms that prompted .NET Core
B.1.2 Introducing .NET Core
B.1.3 .NET 5.0: The first step in the One .NET vision
B.1.4 The future: .NET 6.0 and beyond
B.2 Sharing code between projects
B.2.1 Finding a common intersection with Portable Class Libraries
B.2.2 .NET Standard: A common interface for .NET
B.2.3 Fudging .NET Standard 2.0 support with the compatibility shim
B.3 .NET 5.0 and the future of .NET Standard
Summary
Appendix C—Useful references
C.1 Relevant books
C.2 Announcement blog posts
C.3 Microsoft documentation
C.4 Security-related links
C.5 ASP.NET Core GitHub repositories
C.6 Tooling and services
C.7 ASP.NET Core blogs
C.8 Video links
index