Preface |
|
xvii | |
Acknowledgments |
|
xix | |
About This Book |
|
xxi | |
About The Author |
|
xxv | |
About The Cover Illustration |
|
xxvi | |
Part 1 Getting Started With MVC |
|
1 | (264) |
|
1 Getting started with ASP.NET Core |
|
|
3 | (25) |
|
1.1 An introduction to ASP.NET Core |
|
|
4 | (4) |
|
|
4 | (1) |
|
The benefits and limitations of ASP.NET |
|
|
5 | (1) |
|
|
6 | (2) |
|
1.2 When to choose ASP.NET Core |
|
|
8 | (9) |
|
What type of applications can you build? |
|
|
8 | (2) |
|
If you're new to .NET development |
|
|
10 | (2) |
|
If you're a .NET Framework developer creating a new application |
|
|
12 | (4) |
|
Converting an existing ASP.NET application to ASP.NET Core |
|
|
16 | (1) |
|
1.3 How does ASP.NET Core work? |
|
|
17 | (4) |
|
How does an HTTP web request work? |
|
|
17 | (2) |
|
How does ASP.NET Core process a request? |
|
|
19 | (2) |
|
1.4 Choosing a platform for ASP.NET Core |
|
|
21 | (2) |
|
Advantages of using .NET Framework |
|
|
21 | (1) |
|
Advantages of using .NET Core |
|
|
22 | (1) |
|
1.5 Preparing your development environment |
|
|
23 | (5) |
|
|
24 | (1) |
|
If you're a Linux or macOS user |
|
|
25 | (3) |
|
|
28 | (33) |
|
2.1 A brief overview of an ASP.NET Core application |
|
|
29 | (3) |
|
2.2 Creating your first ASP.NET Core application |
|
|
32 | (4) |
|
Using a template to get started |
|
|
32 | (3) |
|
|
35 | (1) |
|
2.3 Running the web application |
|
|
36 | (2) |
|
2.4 Understanding the project layout |
|
|
38 | (2) |
|
2.5 The csproj project file: defining your dependencies |
|
|
40 | (1) |
|
2.6 The Program class: building a web host |
|
|
41 | (3) |
|
2.7 The Startup class: configuring your application |
|
|
44 | (8) |
|
Adding and configuring services |
|
|
45 | (2) |
|
Defining how requests are handled with middleware |
|
|
47 | (5) |
|
2.8 MVC middleware and the home controller |
|
|
52 | (2) |
|
2.9 Generating HTML with Razor template views |
|
|
54 | (7) |
|
3 Handling requests with the middleware pipeline |
|
|
61 | (32) |
|
|
63 | (3) |
|
3.2 Combining middleware in a pipeline |
|
|
66 | (12) |
|
Simple pipeline scenario 1: a holding page |
|
|
67 | (3) |
|
Simple pipeline scenario 2: Handling static files |
|
|
70 | (3) |
|
Simple pipeline scenario 3: An MVC web application |
|
|
73 | (5) |
|
3.3 Handling errors using middleware |
|
|
78 | (15) |
|
Viewing exceptions in development: DeveloperExceptionPage |
|
|
80 | (2) |
|
Handling exceptions in production: ExceptionHandlerMiddleware |
|
|
82 | (4) |
|
Handling other errors: StatusCodePagesMiddleware |
|
|
86 | (4) |
|
Disabling error handling middleware for Web APIs |
|
|
90 | (3) |
|
4 Creating web pages with MVC controllers |
|
|
93 | (27) |
|
4.1 An introduction to MVC |
|
|
95 | (18) |
|
|
95 | (3) |
|
|
98 | (6) |
|
Adding the MvcMiddleware to your application |
|
|
104 | (7) |
|
What makes a controller a controller? |
|
|
111 | (2) |
|
4.2 MVC controllers and action methods |
|
|
113 | (7) |
|
Accepting parameters to action methods |
|
|
114 | (2) |
|
|
116 | (4) |
|
5 Mapping URLs to methods using conventional routing |
|
|
120 | (28) |
|
|
122 | (3) |
|
5.2 Routing to MVC controllers and actions |
|
|
125 | (4) |
|
5.3 Routing using conventions |
|
|
129 | (11) |
|
Understanding route templates |
|
|
131 | (2) |
|
Using optional and default values |
|
|
133 | (2) |
|
Adding additional constraints to route parameters |
|
|
135 | (3) |
|
Defining default values and constraints using anonymous objects |
|
|
138 | (1) |
|
Matching arbitrary URLs with the catch-all parameter |
|
|
139 | (1) |
|
5.4 Handling multiple matching actions for a route |
|
|
140 | (2) |
|
5.5 Generating URLs from route parameters |
|
|
142 | (6) |
|
Generating URLs based on an action name |
|
|
143 | (1) |
|
Generating URLs based on a route name |
|
|
144 | (1) |
|
Generating URLs with ActionResults |
|
|
145 | (3) |
|
6 The binding model: retrieving and validating user input |
|
|
148 | (26) |
|
6.1 Understanding the M in MVC |
|
|
149 | (3) |
|
6.2 From request to model: making the request useful |
|
|
152 | (12) |
|
|
155 | (3) |
|
|
158 | (4) |
|
Choosing a binding source |
|
|
162 | (2) |
|
6.3 Handling user input with model validation |
|
|
164 | (10) |
|
|
164 | (1) |
|
Using DataAnnotations attributes for validation |
|
|
165 | (3) |
|
Validating on the server for safety |
|
|
168 | (3) |
|
Validating on the client for user experience |
|
|
171 | (3) |
|
7 Rendering HTML using Razor views |
|
|
174 | (30) |
|
7.1 Views: rendering the user interface in MVC |
|
|
175 | (4) |
|
|
179 | (8) |
|
Selecting a view from a controller |
|
|
181 | (1) |
|
Introducing Razor templates |
|
|
182 | (3) |
|
|
185 | (2) |
|
7.3 Creating dynamic web pages with Razor |
|
|
187 | (6) |
|
Using C# in Razor templates |
|
|
188 | (1) |
|
Adding loops and conditionals to Razor templates |
|
|
189 | (2) |
|
|
191 | (2) |
|
7.4 Layouts, partial views, and _ViewStart |
|
|
193 | (11) |
|
Using layouts for shared markup |
|
|
194 | (2) |
|
Overriding parent layouts using sections |
|
|
196 | (2) |
|
Using partial views to encapsulate markup |
|
|
198 | (2) |
|
Running code on every view with _ViewStart and _ViewImports |
|
|
200 | (4) |
|
8 Building forms with Tag Helpers |
|
|
204 | (30) |
|
8.1 Catering to editors with Tag Helpers |
|
|
206 | (3) |
|
8.2 Creating forms using Tag Helpers |
|
|
209 | (19) |
|
|
214 | (1) |
|
|
215 | (2) |
|
The Input and Textarea Tag Helpers |
|
|
217 | (3) |
|
|
220 | (5) |
|
The Validation Message and Validation Summary Tag Helpers |
|
|
225 | (3) |
|
8.3 Generating links with the Anchor Tag Helper |
|
|
228 | (1) |
|
8.4 Cache-busting with the Append Version Tag Helper |
|
|
229 | (1) |
|
8.5 Using conditional markup with the Environment Tag Helper |
|
|
230 | (4) |
|
9 Creating a Web API for mobile and client applications using MVC |
|
|
234 | (31) |
|
9.1 What is a Web API and when should you use one? |
|
|
235 | (3) |
|
9.2 Creating your first Web API Controller |
|
|
238 | (4) |
|
9.3 Applying the MVC design pattern to a Web API |
|
|
242 | (4) |
|
9.4 Attribute routing: taking fine-grained control of your URLs |
|
|
246 | (9) |
|
Ordering of conventional and attribute routes |
|
|
249 | (2) |
|
Combining route attributes to keep your route templates DRY |
|
|
251 | (2) |
|
Using token replacement to reduce duplication in attribute routing |
|
|
253 | (1) |
|
Handling multiple matching actions with attribute routing |
|
|
254 | (1) |
|
9.5 Enabling additional input formatters: binding to XML data |
|
|
255 | (3) |
|
9.6 Generating a response from a model |
|
|
258 | (9) |
|
Customizing the default formatters: adding XML support |
|
|
260 | (2) |
|
Choosing a response format with content negotiation |
|
|
262 | (3) |
Part 2 Building Complete Applications |
|
265 | (234) |
|
10 Service configuration with dependency injection |
|
|
267 | (36) |
|
10.1 Introduction to dependency injection |
|
|
268 | (10) |
|
Understanding the benefits of dependency injection |
|
|
269 | (5) |
|
Creating loosely coupled code |
|
|
274 | (2) |
|
Dependency injection in ASP.NET Core |
|
|
276 | (2) |
|
10.2 Using the dependency injection container |
|
|
278 | (14) |
|
Adding ASP.NET Core framework services to the container |
|
|
278 | (1) |
|
Registering your own services with the container |
|
|
279 | (3) |
|
Registering services using objects and lambdas |
|
|
282 | (4) |
|
Registering a service in the container multiple times |
|
|
286 | (3) |
|
Injecting services into action methods and view templates |
|
|
289 | (3) |
|
10.3 Understanding lifetimes: when are services created? |
|
|
292 | (11) |
|
Transient: everyone is unique |
|
|
295 | (1) |
|
Scoped: let's stick together, guys |
|
|
296 | (1) |
|
Singleton: there can be only one |
|
|
297 | (1) |
|
Keeping an eye out for captured dependencies |
|
|
298 | (5) |
|
11 Configuring an ASP.NET Core application |
|
|
303 | (31) |
|
11.1 Introducing the ASP.NET Core configuration model |
|
|
304 | (2) |
|
11.2 Configuring your application with CreateDefaultBuilder |
|
|
306 | (2) |
|
11.3 Building a configuration object for your app |
|
|
308 | (12) |
|
Adding a configuration provider in Program.cs |
|
|
310 | (3) |
|
Using multiple providers to override configuration values |
|
|
313 | (2) |
|
Storing configuration secrets safely |
|
|
315 | (3) |
|
Reloading configuration values when they change |
|
|
318 | (2) |
|
11.4 Using strongly typed settings with the options pattern |
|
|
320 | (6) |
|
Introducing the Options interface |
|
|
321 | (2) |
|
Reloading strongly typed options with IOptionsSnapshot |
|
|
323 | (1) |
|
Designing your options classes for automatic binding |
|
|
324 | (2) |
|
11.5 Configuring an application for multiple environments |
|
|
326 | (8) |
|
Identifying the hosting environment |
|
|
326 | (1) |
|
Loading environment-specific configuration files |
|
|
327 | (2) |
|
Setting the hosting environment |
|
|
329 | (5) |
|
12 Saving data with Entity Framework Core |
|
|
334 | (35) |
|
12.1 Introducing Entity Framework Core |
|
|
336 | (6) |
|
|
336 | (1) |
|
Why use an object-relational mapper? |
|
|
337 | (2) |
|
When should you choose EF Core? |
|
|
339 | (1) |
|
Mapping a database to your application code |
|
|
340 | (2) |
|
12.2 Adding EF Core to an application |
|
|
342 | (7) |
|
Choosing a database provider and installing EF Core |
|
|
344 | (1) |
|
|
345 | (3) |
|
Registering a data context |
|
|
348 | (1) |
|
12.3 Managing changes with migrations |
|
|
349 | (6) |
|
Creating your first migration |
|
|
350 | (3) |
|
Adding a second migration |
|
|
353 | (2) |
|
12.4 Querying data from and saving data to the database |
|
|
355 | (11) |
|
|
356 | (2) |
|
Loading a list of records |
|
|
358 | (2) |
|
|
360 | (1) |
|
Updating a model with changes |
|
|
361 | (5) |
|
12.5 Using EF Core in production applications |
|
|
366 | (3) |
|
13 The MVC filter pipeline |
|
|
369 | (31) |
|
13.1 Understanding filters and when to use them |
|
|
370 | (11) |
|
|
372 | (1) |
|
Filters or middleware: which should you choose? |
|
|
373 | (2) |
|
|
375 | (2) |
|
Adding filters to your actions, your controllers, and globally |
|
|
377 | (2) |
|
Understanding the order of filter execution |
|
|
379 | (2) |
|
13.2 Creating custom filters for your application |
|
|
381 | (13) |
|
Authorization filters: protecting your APIs |
|
|
383 | (1) |
|
Resource filters: short-circuiting your action methods |
|
|
384 | (2) |
|
Action filters: customizing model binding and action results |
|
|
386 | (5) |
|
Exception filters: custom exception handling for your action methods |
|
|
391 | (1) |
|
Result filters: customizing action results before they execute |
|
|
392 | (2) |
|
13.3 Understanding pipeline short-circuiting |
|
|
394 | (2) |
|
13.4 Using dependency injection with filter attributes |
|
|
396 | (4) |
|
14 Authentication: adding users to your application with Identity |
|
|
400 | (32) |
|
14.1 Introducing authentication and authorization |
|
|
402 | (8) |
|
Understanding users and claims in ASP.NET Core |
|
|
402 | (1) |
|
Authentication in ASP.NET Core: services and middleware |
|
|
403 | (3) |
|
Authentication for APIs and distributed applications |
|
|
406 | (4) |
|
14.2 What is ASP.NET Core Identity? |
|
|
410 | (2) |
|
14.3 Creating a project that uses ASP.NET Core Identity |
|
|
412 | (11) |
|
Creating the project from a template |
|
|
412 | (2) |
|
Exploring the template in Solution Explorer |
|
|
414 | (2) |
|
The ASP.NET Core Identity data model |
|
|
416 | (2) |
|
Interacting with ASP.NET Core Identity: the MVC controllers |
|
|
418 | (5) |
|
14.4 Adding ASP.NET Core Identity to an existing project |
|
|
423 | (5) |
|
Configuring the ASP.NET Core Identity services and middleware |
|
|
424 | (2) |
|
Updating the EF Core data model to support Identity |
|
|
426 | (1) |
|
Adding the controllers, view models, and views |
|
|
427 | (1) |
|
14.5 Managing users: adding new claims to users |
|
|
428 | (4) |
|
15 Authorization: securing your application |
|
|
432 | (29) |
|
15.1 Introduction to authorization |
|
|
433 | (3) |
|
15.2 Authorization in ASP.NET Core |
|
|
436 | (4) |
|
Preventing anonymous users from accessing your application |
|
|
436 | (3) |
|
Handling unauthorized requests |
|
|
439 | (1) |
|
15.3 Using policies for claims-based authorization |
|
|
440 | (3) |
|
15.4 Creating custom policies for authorization |
|
|
443 | (8) |
|
Requirements and handlers: the building blocks of a policy |
|
|
444 | (1) |
|
Creating a policy with a custom requirement and handler |
|
|
445 | (6) |
|
15.5 Controlling access with resource-based authorization |
|
|
451 | (5) |
|
Manually authorizing requests with IAuthorizationService |
|
|
452 | (2) |
|
Creating a resource-based AuthorizationHandler |
|
|
454 | (2) |
|
15.6 Hiding elements in Razor templates from unauthorized users |
|
|
456 | (5) |
|
16 Publishing and deploying your application |
|
|
461 | (38) |
|
16.1 Understanding the ASP.NET Core hosting model |
|
|
463 | (7) |
|
Running vs. publishing an ASP.NET Core app |
|
|
465 | (3) |
|
Choosing a deployment method for your application |
|
|
468 | (2) |
|
16.2 Publishing your app to IIS |
|
|
470 | (5) |
|
Configuring HS for ASP.NET Core |
|
|
470 | (3) |
|
Preparing and publishing your application to IIS |
|
|
473 | (2) |
|
16.3 Hosting an application on Linux |
|
|
475 | (5) |
|
Running an ASP.NET Core app behind a reverse proxy on Linux |
|
|
476 | (2) |
|
Preparing your app for deployment to Linux |
|
|
478 | (2) |
|
16.4 Configuring the URLs for your application |
|
|
480 | (5) |
|
Using an environment variable |
|
|
480 | (1) |
|
Using configuration values |
|
|
481 | (4) |
|
16.5 Optimizing your client-side assets using BundlerMinifier |
|
|
485 | (16) |
|
Speeding up an app using bundling and minification |
|
|
488 | (2) |
|
Adding BundlerMinifier to your application |
|
|
490 | (4) |
|
Using minified files in production with the environment tag helper |
|
|
494 | (1) |
|
Serving common files from a CDN |
|
|
495 | (4) |
Part 3 Extending Your Applications |
|
499 | (145) |
|
17 Monitoring and troubleshooting errors with logging |
|
|
501 | (33) |
|
17.1 Using logging effectively in a production app |
|
|
503 | (4) |
|
Highlighting problems using custom log messages |
|
|
504 | (1) |
|
The ASP.NET Core logging abstractions |
|
|
505 | (2) |
|
17.2 Adding log messages to your application |
|
|
507 | (7) |
|
Log level: how important is the log message? |
|
|
509 | (2) |
|
Log category: which component created the log |
|
|
511 | (1) |
|
Formatting messages and capturing parameter values |
|
|
512 | (2) |
|
17.3 Controlling where logs are written using logging providers |
|
|
514 | (7) |
|
Adding a new logging provider to your application |
|
|
515 | (2) |
|
Replacing the default ILoggerFactory with Serilog |
|
|
517 | (4) |
|
17.4 Changing log verbosity with filtering |
|
|
521 | (5) |
|
17.5 Structured logging: creating searchable, useful logs |
|
|
526 | (8) |
|
Adding a structured logging provider to your app |
|
|
527 | (3) |
|
Using scopes to add additional properties to your logs |
|
|
530 | (4) |
|
18 Improving your application's security |
|
|
534 | (38) |
|
18.1 Adding HTTPS to an application |
|
|
535 | (13) |
|
Setting up IIS and IIS Express to use encryption |
|
|
538 | (3) |
|
Creating a self-signed certificate for local development |
|
|
541 | (3) |
|
Using HTTPS directly in Kestrel |
|
|
544 | (1) |
|
Enforcing HTTPS for your whole app |
|
|
545 | (3) |
|
18.2 Defending against cross-site scripting (XSS) attacks |
|
|
548 | (3) |
|
18.3 Protecting from cross-site request forgery (CSRF) attacks |
|
|
551 | (5) |
|
18.4 Calling your web APIs from other domains using CORS |
|
|
556 | (8) |
|
Understanding CORS and how it works |
|
|
557 | (2) |
|
Adding COPS to your whole app with middleware |
|
|
559 | (2) |
|
Adding COPS to specific MVC actions with EnableCorsAttribute |
|
|
561 | (1) |
|
Configuring CORS policies |
|
|
562 | (2) |
|
18.5 Exploring other attack vectors |
|
|
564 | (8) |
|
Detecting and avoiding open redirect attacks |
|
|
564 | (2) |
|
Avoiding SQL injection attacks with EF Core and parameterization |
|
|
566 | (2) |
|
Preventing insecure direct object references |
|
|
568 | (1) |
|
Protecting your users' passwords and data |
|
|
568 | (4) |
|
19 Building custom components |
|
|
572 | (35) |
|
19.1 Customizing your middleware pipeline |
|
|
574 | (9) |
|
Creating simple endpoints with the Run extension |
|
|
575 | (1) |
|
Branching middleware pipelines with the Map extension |
|
|
576 | (2) |
|
Adding to the pipeline with the Use extension |
|
|
578 | (3) |
|
Building a custom middleware component |
|
|
581 | (2) |
|
19.2 Handling complex configuration requirements |
|
|
583 | (6) |
|
Partially building configuration to configure additional providers |
|
|
584 | (2) |
|
Using services to configure IOptions with IConfigureOptions |
|
|
586 | (3) |
|
19.3 Using a third-party dependency injection container |
|
|
589 | (2) |
|
19.4 Creating a custom Razor Tag Helper |
|
|
591 | (6) |
|
Printing environment information with a custom Tag Helper |
|
|
592 | (3) |
|
Creating a custom Tag Helper to conditionally hide elements |
|
|
595 | (2) |
|
19.5 View components: adding logic to partial views |
|
|
597 | (4) |
|
19.6 Building a custom validation attribute |
|
|
601 | (6) |
|
20 Testing your application |
|
|
607 | (37) |
|
20.1 An introduction to testing in ASP.NET Core |
|
|
608 | (2) |
|
20.2 Unit testing with xUnit |
|
|
610 | (11) |
|
Creating your first test project |
|
|
611 | (2) |
|
Running tests with dotnet test |
|
|
613 | (1) |
|
Referencing your app from your test project |
|
|
614 | (3) |
|
Adding Fact and Theory unit tests |
|
|
617 | (3) |
|
Testing failure conditions |
|
|
620 | (1) |
|
20.3 Unit testing custom middleware |
|
|
621 | (3) |
|
20.4 Unit testing MVC controllers |
|
|
624 | (3) |
|
20.5 Integration testing: testing your whole app with a Test Host |
|
|
627 | (10) |
|
Creating a TestSeroer using the Test Host package |
|
|
628 | (2) |
|
Using your application's Startup file for integration tests |
|
|
630 | (2) |
|
Rendering Razor views in TestServer integration tests |
|
|
632 | (3) |
|
Extracting common setup into an xUnit test fixture |
|
|
635 | (2) |
|
20.6 Isolating the database with an in-memory EF Core provider |
|
|
637 | (7) |
Appendix A Getting to grips with .NET Core and .NET Standard |
|
644 | (19) |
Appendix B Useful references |
|
663 | (6) |
Index |
|
669 | |