36,59 €
Get up to speed with the latest features of C# 8, ASP.NET Core 3 and .NET Core 3.1 LTS to create robust and maintainable web services
Key Features
Book Description
In recent times, web services have evolved to play a prominent role in web development. Applications are now designed to be compatible with any device and platform, and web services help us keep their logic and UI separate. Given its simplicity and effectiveness in creating web services, the RESTful approach has gained popularity, and this book will help you build RESTful web services using ASP.NET Core.
This REST book begins by introducing you to the basics of the REST philosophy, where you'll study the different stages of designing and implementing enterprise-grade RESTful web services. You'll also gain a thorough understanding of ASP.NET Core's middleware approach and learn how to customize it. The book will later guide you through improving API resilience, securing your service, and applying different design patterns and techniques to achieve a scalable web service. In addition to this, you'll learn advanced techniques for caching, monitoring, and logging, along with implementing unit and integration testing strategies. In later chapters, you will deploy your REST web services on Azure and document APIs using Swagger and external tools such as Postman.
By the end of this book, you will have learned how to design RESTful web services confidently using ASP.NET Core with a focus on code testability and maintainability.
What you will learn
Who this book is for
This book is for anyone who wants to learn how to build RESTful web services with the ASP.NET Core framework to improve the scalability and performance of their applications. Basic knowledge of C# and .NET Core will help you make the best use of the code samples included in the book.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 527
Veröffentlichungsjahr: 2019
Copyright © 2019 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Commissioning Editor:Richa TripathiAcquisition Editor:Alok DhuriContent Development Editor:Ruvika RaoTechnical Editor:Pradeep SahuCopy Editor: Safis EditingSenior Editor: Rohit SinghProject Coordinator: Francy PuthiryProofreader: Safis EditingIndexer:Pratik ShirodkarProduction Coordinator:Alishon Mendonsa
First published: December 2019
Production reference: 1261219
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78953-761-1
www.packtpub.com
Packt.com
Subscribe to our online digital library for full access to over 7,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Fully searchable for easy access to vital information
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.packt.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.packt.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
Samuele Resca is a software engineer working at Just Eat and primarily focused on web technologies. He is a Microsoft Most Valuable Professional in Visual Studio and development technologies. Samuele writes software engineering blog posts on Samuele Resca – Blog and The DEV Community, and he contributes to open source projects. He is continuously learning and developing around the web ecosystem with a focus on the .NET Core ecosystem, cloud computing, serverless computing, and reactive programming. Samuele is from Italy, and he currently lives in London.
Ankit Sharma is a software engineer currently working as a senior technical member with ADP in Hyderabad, India. He has over 5 years of extensive experience in Microsoft technologies including C#, ASP.NET, SQL Server, and UI technologies such as jQuery and Angular. He is a technical author and speaker and loves to contribute to the open source community. He writes articles for multiple platforms, which include c-sharpcorner, Dzone, Medium, and TechNet Wiki. For his dedicated contribution to the developer community, he has been recognized as a c-sharpcorner MVP, Dzone MVB, and Top contributor in Technology at Medium. He is also the author of the first ever book on Blazor – Blazor Quick Start Guide. You can tweet him at @ankitsharma_007.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Title Page
Copyright and Credits
Hands-On RESTful Web Services with ASP.NET Core 3
Dedication
About Packt
Why subscribe?
Contributors
About the author
About the reviewer
Packt is searching for authors like you
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Download the color images
Conventions used
Get in touch
Reviews
Section 1: Getting Started
REST 101 and Getting Started with ASP.NET Core
REST
The importance of being REST compliant
REST requirements
Uniform interface
Manipulation of resources through representations
Self-descriptive messages
Hypermedia as the Engine of Application State
Stateless
Client-server separation
Layered system
Richardson maturity model
Introducing ASP.NET Core
The evolution of ASP.NET
The new .NET ecosystem
.NET STANDARD
Why use ASP.NET Core to build RESTful web services?
Preparing your development environment
.NET Core CLI
IDEs and development tools in ASP.NET Core
Summary
Section 2: Overview of ASP.NET Core
Overview of ASP.NET Core
Setting up our .NET Core project
Overview of .csproj
The Program.cs file in detail
Setting up an ASP.NET Core project
The project structure
The Program.cs and Startup.cs files
Overview of controllers 
Summary
Working with the Middleware Pipeline
Introducing middleware
The middleware pipeline in practice
HttpContext in ASP.NET Core
Class-based middleware
Conditional pipeline
Understanding built-in middleware
Summary
Dependency Injection System
Dependency inversion principle
Benefits of dependency injection
Dependency injection in ASP.NET Core
Registering services using the dependency injection container
Registering services conditionally
Constructor injection
Action method injection
Services life cycle
Transient life cycle
Scoped life cycle
Singleton life cycle
Life cycle madness
Injecting services into middleware
Summary
Web Service Stack in ASP.NET Core
What is a controller?
Identifying controllers
Extending controllers
The ApiController attribute
Handling requests using controllers and actions
Creating an in-memory repository
Handling client requests
Handling HTTP methods using actions
Responding to requests
CreateAt response
Updating resources
Partial updating
Deleting resources
Asynchronous processing and acceptance status
Data transfer objects
Implementing request models
Implementing response models
Implementing validation of requests
Custom validation attributes
Summary
Routing System
Overview of the routing system
Conventional routing
Attribute routing
Custom attribute routing
Routing constraints
Custom constraints
Summary
Filter Pipeline
Introduction to filters
Concrete filter implementations
Asynchronous filters
The scope of filters
The use of filters
Life cycle and dependency injection
Filter use cases
Existing entity constraints
Altering exceptions
Summary
Section 3: Building a Real-World RESTful API
Building the Data Access Layer
Setting up the project
Implementing the domain model
Designing entities
Implement entities
Data access using ORMs
Finding the right tool for the job
Implementing a data access layer using EF Core
Defining the repository pattern and unit of work
Connecting our repository to the database
DbContext definition
Implementing the repository 
Transforming entities into a SQL schema
Custom conversions using the Fluent API
Applying the schema definition on the current data context 
Generating a schema for the Artist and Genre entities
Executing migrations
Defining the configuration part
Testing the EF Core repository
Seeding data using DbContext
Initializing the testing class
Implementing a data access layer using Dapper
Creating stored CRUD procedures
Implementing the IItemRepository interface
Summary
Implementing the Domain Logic
Implementing service classes
The service class interface
Implementing the mapping layer
Mapping logic using Automapper
The service class implementation
Testing the service layer
Refactoring testing classes
Implementing the ItemService tests
Implementing request model validation
Testing request model validation
Dependencies registration
Summary
Implementing the RESTful HTTP Layer
Implementing the item controller
Implementing action methods
Testing controllers using the WebApplicationFactory<T> class
Extending the WebApplicationFactory
Testing a controller
Loading test data using xUnit data attributes
Improving the resilience of the API 
Existence check
JSON-customized errors
Implementing pagination
Exposing related entities 
Extending the data access layer
Extending the test coverage 
Extending the IItemRepository interface
Extending the capabilities of the service layer
Improving the validation mechanism
Updating the dependencies in the Startup class
Adding the related controllers
Extending tests for the ArtistController class
A final overview
Summary
Advanced Concepts of Building an API
Implementing the soft delete procedure
Updating the IItemRepository implementation
Implementing delete operations
Implementing HATEOAS 
Enriching our model with HATEOAS data
Implementing HATEOAS in a controller
The asynchronous code in ASP.NET Core
Task definitions
The need for asynchronous code in ASP.NET Core
What's new in ASP.NET Core?
Best practices in asynchronous programming
Don't use async void methods
Use Task.FromResult over Task.Run
Enable cancellation
Asynchronous code in I/O bound operations
Measure response time using middleware
Summary
The Containerization of Services
An introduction to containers
Docker terminology
Using Docker to run the catalog service
Defining environment variables
Defining the Dockerfile
Executing the docker-compose command
Optimizing Docker images
An overview of different Docker images
Multi-stage builds on the catalog service
Summary
Service Ecosystem Patterns
An introduction to the cart service
The theory behind the mediator pattern
The domain model and the data access layer
The ICartRepository Redis implementation
Handlers and routes implementation
Exposing functionalities using CartController
Implementing resilient communication using an HTTP client
Implementing the catalog HTTP client 
Integrating an HTTP client into the cart service
Implementing resilience using Polly.NET
Integrating Polly into ICatalogService
Sharing events using an event bus
Setting up a RabbitMQ instance and publishing an event
Running the cart service using Docker
Summary
Implementing Worker Services Using .NET Core
Introducing worker services
Understanding the worker services life cycle
Hosting models
Implementing a health-checking worker
Project structure overview
Running a worker service on Docker
Consuming the sold-out event
Creating a sold-out handler
Testing the sold-out process
Configuring the background service
Summary
Securing Your Service
Overview of secure communication
Securing data using HTTPS  
Enforcing HTTPS in ASP.NET Core
HTTP/2 on Kestrel
Enabling CORS in ASP.NET Core
Implementing CORS using the middleware approach
Implementing CORS using the attribute approach
Securing APIs with token-based authentication
Implementing token-based authentication
Defining the service layer
Applying authentication on the controller
Storing data using EF Core
Declaring the identity database context
Testing authentication
Summary
Section 4: Advanced Concepts for Building Services
Caching Web Service Responses
Introduction to the HTTP caching system
The HTTP caching specification
Implementing response caching in ASP.NET Core
Implementing a distributed cache
Implementing the IDistributedCache interface
Inject memory cache into the tests
Summary
Logging and Health Checking
Logging in ASP.NET Core
The key characteristics of logging
Implementing the logging part
Exception logging
Verifying logging using Moq
Implementing logging providers
Implementing a custom log provider in tests
Web service health check 
Implementing health checks on databases
Implementing custom health checks
Summary
Deploying Services on Azure
Getting started with Azure
Pushing containers into Azure Container Registry
Creating an Azure Container Registry
Configuring Azure Container Instances
Configuring app services
Creating an app service using a container image
Summary
Documenting Your API Using Swagger
Understanding OpenAPI
Implementing the Swagger project
Implementing OpenAPI in ASP.NET Core services
Understanding ASP.NET Core's conventions
Custom conventions
Summary
Testing Services Using Postman
Overview of Postman
Testing the API using Postman
Using the runner to test the APIs
Importing a collection using OpenAPI
Summary
Other Books You May Enjoy
Leave a review - let other readers know what you think
.NET Core is a breath of fresh air for all the consumers of the Microsoft ecosystem. The old ASP.NET and .NET framework both have a long history. Over the years, the growth of the .NET framework and the long-time support constraints have resulted in odd implementations and hard-to-maintain web applications and web services.
Furthermore, the strong dependency between .NET framework and the Windows OS has led to substantial limitations in the cloud technology world.
.NET Core and ASP.NET Core are designed to evolve. They use abstract software development practices including open source, community-oriented approaches, as well as continuous improvement concepts. Today, ASP.NET Core is more flexible, fast, and powerful than ever. All the constraints developers had faced with .NET framework have been expelled and rewritten from scratch. Consequently, it is now possible to run .NET Core on every platform with no limitations. The framework is directly shipped with the .NET Core application. Therefore, it is possible to run it using a containerization approach. The documentation, the issues, and the roadmap are all available on GitHub. Microsoft is now following, by default, an open source way of working.
I've been interested in .NET Core since the first release of the old DNX runtime. This book will introduce you to the power of ASP.NET Core and how to use its strength and flexibility to run web services. Furthermore, the book aims to fight the prejudices that people have regarding the .NET ecosystem and seeks to increase the adoption of .NET Core.
This book is intended for those who want to learn how to build RESTful web services with ASP.NET Core. To make the best use of the code samples included in the book, you should have basic knowledge of C#.
Chapter 1, REST 101 and Getting Started with ASP.NET Core, explains some fundamentals of RESTful APIs and how they can be useful when building an application.
Chapter 2, Overview of ASP.NET Core, shows the essential components of the .csproj file. It illustrates the main components of a project: the Startup class and theProgram.csfile.
Chapter 3, Working with the Middleware Pipeline, explores middlewares, which are a central part of ASP.NET Core. This chapter walks you through the middleware pipeline and explains how it can handle requests and initialize different services based on them. Furthermore, the chapter covers the different out-of-the-box middlewares provided by ASP.NET Core and how to build a custom middleware.
Chapter 4, Dependency Injection System, introduces you to dependency injection principles and to the concepts behind dependency injection. It shows you how to use dependency injection to initialize components and options inside your application and how to use them inside your controllers.
Chapter 5, Web Service Stack in ASP.NET Core, describes how to create a web service stack in ASP.NET Core. It goes into depth on concerns such as controllers, action methods, action results, model binding, and model validation.
Chapter 6, Routing System, delves into the routing system, which handles HTTP requests. The chapter shows you how to deal with the default routing system of ASP.NET Core.
Chapter 7, Filter Pipeline, covers another essential topic in ASP.NET Core: filters. Filters are a vital component for achieving cross-cutting implementations in our services. The chapter introduces them; it shows how to implement our filters and explores some concrete use cases.
Chapter 8, Building the Data Access Layer, introduces the domain model part. The main topics are related to how to build the domain model and how to access data using object-relational mapping (ORM).
Chapter 9, Implementing the DomainLogic, describes the mediator pattern approach to keeping logic isolated from other application components. The mediator pattern is one way to handle and manage our logic.
Chapter 10, Implementing the RESTful HTTP Layer, explains how to retrieve data from the mediator and use it inside our controllers.
Chapter 11, Advanced Concepts of Building the API, presents some advanced concepts around building APIs in ASP.NET Core. The chapter will cover topics around the soft deletion of resources, and it introduces some good practices for working with asynchronous code in ASP.NET Core.
Chapter 12, The Containerization of Services, gives you a quick introduction to containers and how they can be useful when running your application locally in a sandboxed environment.
Chapter 13, Service Ecosystem Patterns, focuses on the patterns involved when multiple services are part of the same ecosystem.
Chapter 14, Implementing Worker Services Using .NET Core, is dedicated to the new worker template of .NET Core. Workers provide a way to implement small services or daemons that can be used to perform background operations.
Chapter 15, Securing Your Service, talks about securing a service or an API. Besides that, it covers concepts including Secure Sockets Layer (SSL), Cross-Origin Resource Sharing (CORS), and authentication.
Chapter 16, Caching Web Service Responses, covers all the caching choices provided by ASP.NET Core.
Chapter 17, Logging, Monitoring, and Health Checking, shows some best practices for logging and monitoring your application.
Chapter 18, Deploying Services on Azure, shows some examples of how to host a web service in the cloud.
Chapter 19, Documenting Your API Using Swagger, introduces you to the OpenAPI standard and how to implement it in an ASP.NET Core application.
Chapter 20, Testing Services Using Postman, shows how to use Postman to test a web service.
This book assumes that you have some knowledge of C# (or a similar object-oriented programming language, such as Java) and that you have some experience in building web applications.
This book doesn't require any specific tools, but you will need .NET Core installed on your machine (https://dotnet.microsoft.com/download). I strongly suggest that you have at least one code editor, such as Visual Studio Code, possibly with OmniSharp, or an integrated development environment (IDE) such as Visual Studio (on Windows or Mac), or Rider IDE (on Windows, Mac, or Linux).
I've written all the examples on macOS X using Rider IDE and Bash.
You can download the example code files for this book from your account at www.packt.com. If you purchased this book elsewhere, you can visit www.packt.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packt.com
.
Select the
SUPPORT
tab.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Hands-On-RESTful-Web-Services-with-ASP.NET-Core-3. In case there's an update to the code, it will be updated on the existing GitHub repository.
We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://static.packt-cdn.com/downloads/9781789537611_ColorImages.pdf.
There are a number of text conventions used throughout this book.
CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "The headers part tells the client that the response should be processed using a specific content-type; in this case, application/json."
A block of code is set as follows:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp3.0;net461</TargetFrameworks>
</PropertyGroup></Project>
When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp3.0;net461</TargetFrameworks>
</PropertyGroup></Project>
Any command-line input or output is written as follows:
dotnet build
dotnet run
Bold: Indicates a new term, an important word, or words that you see onscreen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "As you can see, it is running Hello, World!"
Feedback from our readers is always welcome.
General feedback: If you have questions about any aspect of this book, mention the book title in the subject of your message and email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packt.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the Internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packt.com.
In this section, we will introduce you to all the macro concepts of REST APIs and ASP.NET Core. You will also learn about local development.
This section includes the following chapter:
Chapter 1
,
REST 101 and Getting Started with ASP.NET Core
Nowadays, almost all applications rely on web services. A lot of them operate using the RESTful method. The resource-centric approach and the simplicity of the REST style have become an industry standard. Therefore, it is essential to understand the theory behind the REST way of working and why it is important. This chapter will introduce you to the Representational State Transfer (REST) method. We will see what the definition of REST is and how to identify REST-compliant web services. We will also introduce .NET Core 3.1 and ASP.NET Core, the brand new version of the open-source, cross-platform framework provided by Microsoft.
In summary, this chapter covers the following topics:
Overview of REST architectural elements
A brief introduction to the .NET ecosystem
Why you should choose .NET to build a RESTful web service
By the end of this chapter, you will have an overview of some useful tools and IDEs that you can use to start developing on .NET Core.
This chapter will cover some of the base concepts of .NET Core 3.1 and ASP.NET Core. You need to have either Windows, Linux, or macOS installed. The setup process will depend on which OS you are using. We'll look at the different tools that can be used to develop apps and web services in .NET Core.
What is REST? Representational State Transfer (REST) is usually defined as a software architecture style that applies some constraints to a web service. It identifies a set of resource-centric rules that describe the roles and the interaction between the constraints of a distributed hypermedia system, instead of focusing on the implementation of the components. Although it is quite rare to find a REST service that does not use HTTP, the definition does not mention any of these topics and instead describes REST as media- and protocol-agnostic.
The preceding definition can be further explained with an example. Consider an e-commerce website. When you browse a list of products and click on one them, the browser interprets your click as a request to a specific resource; in this case, the details of the product you clicked on. The browser makes an HTTP call to the URI, which corresponds to the details of the product and asks for a specific resource using the URI. This process is shown in the following diagram:
The concept of REST is pretty similar: the client asks the server for a specific resource, and this allows them to navigate and obtain other information about resources stored on the server.
Before we discuss REST, we should understand the importance of web services in the modern application development world.
A typical modern application uses web services to obtain and query data. Any company that develop any product or solution uses web services to deliver and track information. This is because it can be difficult to replicate all the data and every behavior you need for every client who uses your application. Web services are also useful for providing access to third-party clients and services. Consider, for example, the Application Programming Interfaces (APIs) of Google Maps or Instagram: these platforms expose information through HTTP to share it with other companies and services.
The REST approach to web service architecture became increasingly popular because it is straightforward and clear. Unlike some old methods, such as the Simple Object Access Protocol (SOAP) or the Windows Communication Foundation (WCF), REST services provide a clean way of querying data. Different information can be obtained using different URIs without the need for adding any overhead to requests.
Today, more than ever, our services need to be prepared to scale so that they can be adapted to consumers. In a world of different technologies and distributed teams around the globe, we should be able to transform our architecture to solve complex business challenges. HTTP and REST help us address these challenges.
Roy Thomas Fielding is the main person behind the formalization of the HTTP protocol and the REST style: he described them in his dissertation, Architectural Styles and the Design of Network-based Software Architectures (https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm). Moreover, Fielding's dissertation clearly defines the constraints of a REST system, as follows:
Uniform interface
Stateless
Cacheable
Client-server
Layered system
Code on demand
All of these, apart from code on demand, are essential when we wish to define a web service as REST-compliant. To explain these concepts, we will use the APIs provided by The New York Times: https://developer.nytimes.com/. To use these APIs, you need to go through a pre-authentication process. You can get an API key for this from the following link: https://developer.nytimes.com/signup.
Uniform interface refers to the separation between the client and the server. This is advantageous because it means that the two systems are independent. The first principle of a uniform interface is that it should be resource-based, which means that we should start to think in a resource-oriented way. Therefore, every object or entity inside our system is a resource and a URI uniquely identifies each of them. Furthermore, if we think about the HTTP protocol, each resource is presented to the client in the form of XML or JSON to decouple the client from the server.
Let's use The New York Times APIs to understand this topic. Consider the following URI:
http://api.nytimes.com/svc/archive/v1/2018/6.json?api-key={your_api_key}
It contains some precise information about the resources we are asking for, including the following:
The fact that we are getting information from the
archive
section of the newspaper data
The specific month we are asking for; in this case, June 2018
The fact that the resource will be serialized using
JSON format
Let's take another API request provided by The New York Times:
https://api.nytimes.com/svc/books/v3/lists.json?api-key={your_api_key}&list=hardcover-fiction
This provides a list of books based on a category; in this case, this category is Hardcover Fiction. Let's analyze the response:
{ "status": "OK", "copyright": "Copyright (c) 2018 The New York Times Company. All Rights Reserved.", "num_results": 15, "last_modified": "2018-06-28T02:38:01-04:00", "results": [ { "list_name": "Hardcover Fiction", "display_name": "Hardcover Fiction", "published_date": "2018-07-08", "isbns": [ { "isbn10": "1780898401", "isbn13": "9780316412698" } ], "book_details": [ { "title": "THE PRESIDENT IS MISSING", "contributor": "by Bill Clinton and James Patterson", "author": "Bill Clinton and James Patterson", "contributor_note": "", "price": 0, "age_group": "", "publisher": "Little, Brown and Knopf" } ], "reviews": [ { "book_review_link": "", "first_chapter_link": "" } ] } .... ]}
As you can see, this is a clear representation of the resource. The client has all the required information to process and modify data using APIs (if the APIs allow that).
Let's look at the response of the following call:
https://api.nytimes.com/svc/books/v3/lists.json?api-key={your_api_key}&list=hardcover-fiction
As we mentioned previously, the response is a representation of the data, either stored in a data source or obtained from another system. In any case, some information is missing: how does the client know the format of the response? This kind of information is usually written in the response header. For example, here are all the headers of the previous request:
accept-ranges: bytesaccess-control-allow-headers:
Accept, Content-Type, X-Forwarded-For, X-Prototype-Version, X-Requested-With
access-control-allow-methods: GET, OPTIONSaccess-control-allow-origin: *access-control-expose-headers: Content-Length, X-JSONage: 0connection: keep-alivecontent-length: 14384content-type: application/json; charset=UTF-8date: Tue, 03 Jul 2018 12:47:08 GMTserver: Apache/2.2.15 (CentOS)vary: Originvia: kong/0.9.5x-cache: MISSx-kong-proxy-latency: 4x-kong-upstream-latency: 29x-ratelimit-limit-day: 1000x-ratelimit-limit-second: 5x-ratelimit-remaining-day: 988x-ratelimit-remaining-second: 4x-varnish: 63737329
The headers part tells the client that the response should be processed using a specific content-type; in this case, application/json. It also provides information about encoding, caching, and related meta information, such as the age header, which contains the time in seconds that the object has been in the proxy cache.
Services usually deliver a state to clients via body content, response codes, and response headers. Above all, hypermedia-driven services (HATEOAS) include the URI of other resources within their responses. The following example describes the concept of HATEOAS:
{ "links": { "self": { "href": "http://example.com/people" }, "item": [ { "href": "http://example.com/people/1", "title": "Kendrick West" }, { "href": "http://example.com/people/2", "title": "Anderson Rocky" } ] },}
The previous response provides a list of people, together with the URIs that specify detailed information of each person. Therefore, the client knows the right URI of the request to use in order to get the information regarding each resource.
Being stateless is a crucial characteristic of a REST service. Indeed, HTTP, as a stateless protocol, doesn't keep track of all the information about the connection between the client and the server once the communication ends.
A stateless protocol forces the client to fulfill the request with all the required information each time it needs some information from the server. Let's take one of the previous URIs:
https://api.nytimes.com/svc/books/v3/lists.json?api-key={your_api_key}&list=hardcover-fiction
The client has to send the API key with each request to be authenticated by the server. Furthermore, it must store the API key information.
Statelessness is very important if we wish to take advantage of REST services. Nowadays, with the rise of highly distributed systems, it is difficult to deal with stateful services because this requires the states to be managed and replicated on different servers. A stateless approach helps delegate state management to the client.
The main aim of REST services is to decouple the server and the client. This is very important because it helps keep unique business logic and data storage for each client application. Applications are usually distributed across a multitude of different clients, including the web, smartphones, smart TVs, and the IoT. A REST approach helps us prevent logic replication across clients. This means that the client does not have any business logic or storage, and the server does not deal with user interfaces or the presentation layer.
The concept of a layered system is strictly related to the structure of the infrastructure of our application. RESTful services allow a loosely coupled approach because the information is transferred over a protocol – in most cases, HTTP – and each server has a single high-level purpose. Proxy servers, web servers, and database servers are usually isolated and they cover a purpose in our feature, if you have one server that provides all the required features, it is often hard to maintain and scale.
The Richardson maturity model is a model that was developed by Leonard Richardson, and its purpose is to measure the maturity of APIs by providing some general criteria. The model has four classification steps, from Level 0 to Level 3. The highest level corresponds to a more compliant service. This model isn't just for theoretical purposes; it also helps us understand some of the recommended methods for web service development. Let's take a look at an overview of these different levels. The following diagram shows the structure of the levels in the Richardson maturity model:
A generic service is at Level 0: The Swamp of Plain Old XML when it uses a generic protocol superficially (in the case of web services, this is HTTP). An example of this is a heavy SOAP web service. SOAP implementations use only one URI and only one HTTP verb, and they wrap each request message within a massive envelope.
As we mentioned previously, thinking in terms of resources is the best way to understand and design an API. Therefore, a generic service that's at Level 1 uses multiple URIs associated with different resources. For example, if we think about an API of a general store, we could obtain the complete list of product categories by calling this sample URI:
GET https://api.mystore.com/v1/categories
At the same time, we can get the details of a single category by calling the following URI:
GET https://api.mystore.com/v1/categories/{category_id}
On the other hand, we can get a list of products related to a single category by calling the following URI:
GET https://api.mystore.com/v1/categories/{category_id}/products
As you can see, we can obtain different information by calling different URIs. There is no envelop, and all the requested information is contained in the URI.
Level 2, which is related to HTTP verbs, introduces the use of HTTP verbs to enhance the information that's transferred on request. Let's take the previous request URI as an example:
https://api.mystore.com/v1/categories/{category_id}/products
This can produce different results, depending on the HTTP verb. The following table shows the meanings of various HTTP verbs:
GET /v1/categories/ HTTP/1.1Host: api.mystore.comContent-Type: application/json
POST /v1/categories/ HTTP/1.1Host: api.mystore.comContent-Type: application/json{ "categoryId": 1, "categoryDescription": "Vegetables"}
PUT /v1/categories/1 HTTP/1.1Host: api.mystore.comContent-Type: application/json{ "categoryId": 1, "categoryDescription": "Fruits and Vegetables"}
PUT /v1/categories/1 HTTP/1.1Host: api.mystore.comContent-Type: application/json{ "categoryDescription": "Fruits and Vegetables"}
DELETE /v1/categories/1 HTTP/1.1Host: api.mystore.comContent-Type: application/json
Different HTTP verbs correspond to various data operations. As opposed to a Level 0 service, which doesn't use any specifications of HTTP to deliver information, a Level 2 service takes advantage of HTTP specifications to deliver as much information as possible. Finally, a system with a Level 3 service implements the concept of HATEOAS. As we discussed in the previous section, a HATEOAS provides the resource's URI inside its response. A clear advantage of this approach is that the client doesn't need any information on its side to navigate through the web service's resources. Most importantly, if our web service adds the resource's URI, the client immediately has all the information they need.
At the time of writing this book, .NET Core 3.1 is the LTS (short for Long Term Support) version of the framework powered by Microsoft and the community. ASP.NET Core is the highly modular web framework that runs over the .NET Core platform: it can be used to develop a wide range of web solutions, such as web applications, web assembly client applications and web API projects.
To learn about some of the basic concepts of ASP.NET Core, we need to understand the Model View Controller (MVC) pattern that is implemented in ASP.NET Core.
MVC separates our web application by grouping implementations into three different areas. In a web environment, the starting point is usually a web request that's made by a client or a generic user. The request passes through a middleware pipeline, and the controller then handles it. The controllers also perform some logic operations and populate our model.
The model is the representation of the state of the application. When it is associated with a view, it is called a view model. Once the model is populated, the controller returns a specific view, depending on the request. The purpose of the views is to present data through HTML pages.
In the case of a web API stack, which is the typical way of building web services in ASP.NET Core, the process is the same except for the view part. Instead of this, the controller serializes the model in the response.
To understand how ASP.NET Core helps developers build web services, let's go through the history of the ASP.NET framework.
The first version of ASP.NET was released in 2002 when Microsoft decided to invest in web development. They released ASP.NET Web Forms, which is a set of UI components that we can use to build web interfaces. The core idea of this approach was to provide a very high-level abstraction tool that can produce a GUI for the web. Providing this level of abstraction was a good idea because developers were not familiar with the web. However, ASP.NET Web Forms came with a lot of downsides. First of all, developers had limited control over HTML, and components had to store information in a view state, which was transferred and updated between the client and the server. Furthermore, the components were not correctly separated, and developers tended to mix the presentation code with the business logic code.
In order to improve the experience of developing web applications, Microsoft announced the arrival of ASP.NET MVC in 2007. This new development platform ran on the ASP.NET framework and used concepts from other development platforms that implemented MVC patterns, such as Ruby on Rails. The ASP.NET MVC framework still had some points of weakness. It was built on ASP.NET, which means it had to maintain its retro compatibility with old web forms and web services frameworks such as WCF. Furthermore, it only ran on Windows servers combined with Internet Information Services (IIS).
The latest web framework to be developed by Microsoft is ASP.NET Core. It runs on .NET Core, which is cross-platform and open source. With ASP.NET Core, Microsoft made the choice to release a new lightweight framework that does not have any back-compatibility components derived from previous versions of ASP.NET.
Let's look at an overview of the .NET ecosystem to understand the different frameworks that act as the foundations of ASP.NET Core. Some of the information provided here may sound obvious, but it is essential to clarify the differences between different runtimes and frameworks:
The first block is related to Desktop Packs, which provides the tools for the development of desktop applications starting from .NET Core 3.0. We will not use these tools in this book since they are strictly related to desktop development.
The second block is related to the cross-platform part of .NET Core. This set of tools allows developers to build applications on the WEB, DATA, and AI/ML domain. The WEB section refers to ASP.NET Core, which is a collection of libraries that comes with .NET Core. Usually, ASP.NET Core is combined with the DATA access part. Later in this book, we will see how we can use EF Core to access the database layer. Finally, the AI/ML section, which will not be discussed in this book, provides useful tools in the machine learning domain. At the bottom of the preceding diagram, we have a common layer, that is, .NET STANDARD. It allows developers to build third-party libraries that can be used by the Desktop Packs and by the WEB, DATA, and AI/ML parts.
In conclusion, the new .NET ecosystem can be used by any developer, including cloud developers, web developers, and desktop developers. As we mentioned previously, it also runs anywhere and on any platform. In this book, all of our examples will be based on .NET Core.
.NET STANDARD was introduced along with .NET Core. The aim of the .NET STANDARD is to provide a common API surface for .NET Core and .NET Framework. It works as a unique Base Class Library (BCL) for our applications in both .NET Framework and .NET Core. The release of .NET Standard 2.0 has introduced 32,000 compatible APIs and supports the following framework versions:
.
NET Framework 4.6.1 +
.NET Core 2.0 +
Mono 5.4 +
Recently, Microsoft introduced .NET Standard 2.1. This new version provides new APIs that were introduced as part of the open-source development of .NET Core 3.0. .NET Standard 2.1 will be the common point between the new versions of .NET Core, starting from the 3.0 version, and the other versions of the upcoming frameworks, such as Mono.
You may wish to choose the .NET Standard for different reasons:
To build third-party libraries that are compatible with both .NET Core and .NET Framework. In that case, your package will target .NET Standard 2.0. Eventually, if you want to use the newly optimized APIs that we described previously, it is possible to use multi-targeting to target both .NET Standard 2.0 and .NET Standard 2.1.
To migrate your .NET Framework codebase gradually by isolating logic on .NET Standard projects.
For example, consider a class library project which is used by different versions of .NET. The library may run on either .NET Core or .NET Framework. To avoid maintainability pitfalls, the library package can be compiled for multiple versions of .NET Standard and it can be used by both a .NET Core and a .NET Framework solution.
There is a massive choice of web frameworks that allow developers to build REST web services. One such framework is ASP.NET Core on .NET Core 3.1. .NET Core 3.1 provides a new, lightweight, cross-platform and opensource way to build web applications. Most importantly, it is designed to be cloud-ready: the framework is no longer part of the server, unlike in .NET Framework; instead, it is shipped with the application.
Another key point is that .NET Core maintains a high level of modularity, which adheres to the Unix philosophy and allows you to use only what you need in tailored applications. ASP.NET Core also introduces two new hosting solutions for web applications and web services:
Kestrel
: T
he default HTTP server for ASP.NET Core. It supports HTTPS and web sockets, and it runs on Windows, Linux, and macOS.
Kestrel
is usually combined with a
reverse-proxy,
such as NGINX, IIS, or Apache.
HTTP.sys
: A
Windows-only HTTP server that can be used as an alternative to Kestrel on Windows.
ASP.NET Core and .NET Core are developed by Microsoft and the community, and they are open source projects. In the case of ASP.NET Core, open source isn't just a buzzword; all the features are community-driven, and the ASP.NET team streams a community standup video on YouTube every week, in which they discuss roadmaps, deadlines, and issues. All the .NET Core code is available on GitHub at the following links:
.NET Core
: The repository of .NET Core (
https://github.com/dotnet/core
)
ASP.NET Core
: Contains all the references to ASP.NET Core projects (
https://github.com/aspnet/AspNetCore
)
All the repositories usually come with a roadmap and some contributing guidelines. It is possible to open issues and contribute to the code base. Microsoft has also founded the .NET foundation, an independent organization that fosters open development and collaboration around the .NET ecosystem.
The ASP.NET Core team is also focused on the performance of the framework. All the benchmark results are available on GitHub: https://github.com/aspnet/benchmarks.
In this section, we will show you how to set up your development environment so that you can develop web services using ASP.NET Core. As we mentioned previously, .NET Core is cross-platform, so it can run on the most common OSes. We will also look at how to interact with the .NET Core CLI, which is the starting point for building, running, developing, and testing our services.
First of all, let's start by downloading .NET Core 3.1 from https://www.microsoft.com/net/download/. In our case, we'll install the SDK version, which contains all the components that are required for our development environment, including ASP.NET Core.
Unlike the .NET framework, .NET Core provides an easy to use CLI that exposes all the necessary functionalities we can use to build applications and services. Once .NET Core is installed on your machine, run the dotnet --help command. You will see the following result:
.NET Core SDK (3.1.100)Usage: dotnet [runtime-options] [path-to-application] [arguments]Execute a .NET Core application.runtime-options: --additionalprobingpath <path> Path containing probing policy and assemblies to probe for. --additional-deps <path> Path to additional deps.json file. --fx-version <version> Version of the installed Shared Framework to use to run the application. --roll-forward <setting> Roll forward to framework version (LatestPatch, Minor, LatestMinor, Major, LatestMajor, Disable).path-to-application: The path to an application .dll file to execute.Usage: dotnet [sdk-options] [command] [command-options] [arguments]Execute a .NET Core SDK command.sdk-options: -d|--diagnostics Enable diagnostic output. -h|--help Show command line help. --info Display .NET Core information. --list-runtimes Display the installed runtimes. --list-sdks Display the installed SDKs. --version Display .NET Core SDK version in use.SDK commands: add Add a package or reference to a .NET project. build Build a .NET project. build-server Interact with servers started by a build. clean Clean build outputs of a .NET project. help Show command line help. list List project references of a .NET project. migrate Migrate a project.json project to an MSBuild project. msbuild Run Microsoft Build Engine (MSBuild) commands. new Create a new .NET project or file. nuget Provides additional NuGet commands. pack Create a NuGet package. publish Publish a .NET project for deployment. remove Remove a package or reference from a .NET project. restore Restore dependencies specified in a .NET project. run Build and run a .NET project output. sln Modify Visual Studio solution files. store Store the specified assemblies in the runtime package store. test Run unit tests using the test runner specified in a .NET project. tool Install or manage tools that extend the .NET experience. vstest Run Microsoft Test Engine (VSTest) commands.Additional commands from bundled tools: dev-certs Create and manage development certificates. fsi Start F# Interactive / execute F# scripts. sql-cache SQL Server cache command-line tools. user-secrets Manage development user secrets. watch Start a file watcher that runs a command when files change.Run 'dotnet [command] --help' for more information on a command.
The first thing to notice is the version of .NET Core, which is the version of .NET Core, that is, .NET Core SDK (3.1.100), followed by a list of Software Development Kit (SDK) commands. This contains the commands that are commonly executed during the development stage, such as dotnet build, dotnet restore, and dotnet run. These are used to build our projects, restore the NuGet dependencies, and run our project, respectively. Another relevant section is additional tools, which contain all the third-party CLI packages we will require, such as EF Core. In fact, the .NET Core CLI allows you to extend its functionality by adding specific tools in the form of NuGet packages.
.NET Core CLI is a base upon which higher-level tools such as IDEs, code editors, and continuous integration (CI) tools can be placed. Even though .NET Core is a cross-platform framework, there are various tools that can be used to build web applications and services on different platforms. The following table provides a recap of the different IDEs and editors that can be used to build ASP.NET Core:
Softwares
As you can see, it is possible to use different IDEs and code editors for different platforms. The choice you make usually depends on different factors. Let's look at an overview of the different editors:
Visual Studio 2019 (Community, Pro, and Enterprise)
: An editor that is well-known to anyone who has already developed on the .NET ecosystem. The community version of this product is totally free, and you can find it at
https://visualstudio.microsoft.com/it/downloads/
.
Visual Studio 2019 is the most comfortable choice if you wish to start building on Windows.
Visual Studio Code and OmniSharp
: A popular and open source editor powered by Microsoft and the community. It is cross-platform and built on Electron. OmniSharp is a useful third-party package for Visual Studio Code and other code editors that provides some integration with .NET Core projects. It also provides an IntelliSense feature.
Rider
: A brand new IDE powered by JetBrains and based on the IntelliJ platform and ReSharper. It is compatible with every platform, but it is not free. I've tried it in large projects, and it works well, primarily to provide the ReSharper integration out of the box.
Visual Studio for Mac
: A new IDE powered by Microsoft. It is only compatible with macOS and provides a few functionalities we can use to write C# or F# code in the .NET Core ecosystem. This IDE is still at an early stage, but it has a lot of advanced features.
In conclusion, tools such as Visual Studio 2019, Rider, and Visual Studio for Mac provide a great experience when combined with .NET Core. On the other hand, Visual Studio Code is the lightest and fastest editor. In the upcoming chapters and code demonstrations, I will use the .NET Core CLI to reproduce the same steps in different operating systems.
In this chapter, we have taken an overview of the REST style by considering some concrete some concrete examples. We also learned about some of the basic concepts of the .NET ecosystem, including how it is structured and why ASP.NET Core is an excellent choice if we wish to build web services. We also looked at an overview of the .NET Core CLI and the IDEs and code editors related to the .NET ecosystem.
The topics we covered in this chapter provide a good understanding of what REST means and why is important to follow this kind of principle when we develop a web service. Furthermore, we also looked at the fundamentals for setting up .NET Core in our local environment.
The next chapter will focus on ASP.NET Core and ASP.NET Core MVC. You'll learn how to set up a project using the .NET CLI and explore some of the fundamentals concepts of ASP.NET Core.
In this section, you will learn about the ins and outs of ASP.NET Core and be provided with an overview of the key components of the ASP.NET Core application.
This section includes the following chapters:
Chapter 2
,
Overview of ASP.NET Core
Chapter 3
,
Working with the Middleware Pipeline
Chapter 4
,
Dependency Injection System
Chapter 5
,
Web Service Stack in ASP.NET Core
Chapter 6
,
Routing System
Chapter 7
,
Filter Pipeline
In this chapter, we will explore some of the fundamental concepts of ASP.NET Core. .NET Core is cross-platform, but the IDEs and code editors that are used with it might vary depending on which OS they run on. To avoid repetition and cover all OS variants, I always use the CLI in the examples presented in this book. Furthermore, the dotnet instruction is the unique entry point and is also used, under the hood, by code editors and IDEs.
This chapter will cover the following topics:
Setting up a .NET Core 3.1 and ASP.NET Core project
The file structure of a .NET Core project template
This chapter assumes that you have already installed .NET Core version 3.1 or higher on your machine. First of all, let's start by launching the following command in our console:
dotnet new
The output will appear as follows:
The preceding output shows all the .NET Core project templates available on the local machine. Each of these has a user-friendly name, a short name, and tags. They are available in C#, F# and VB; the default is C#.
To create a new template, we'll use the short name. For example, in order to create a console application, we should run the following instruction:
dotnet new console -n HelloWorld
The preceding instruction will create a new project in the current folder, with the following tree structure:
.├── HelloWorld.csproj├── Program.cs└── obj ├── ...
The HelloWorld.csproj file contains all the meta-information about the project. The .NET Core version of the .csproj file is more lightweight compared to the .csproj file in previous versions of the .NET Framework. We'll discuss the new structure of this project file next in this chapter. The Program.cs file is the entry point of the application.
To build and execute our project, we can run the following commands inside the project folder:
dotnet build
dotnet run
As expected, we obtain the following result:
Hello World!
Unlike old .NET Framework projects, the build and run steps are lightweight processes, and they don't require any additional tools or configurations. In fact, .NET Core is not strictly chained to the development machine like the .NET Framework. Eventually, developers can write code without any other IDEs or code editors. However, for obvious reasons, it is always recommended that you use them to simplify the development process.
It is also essential to note that, once we execute the dotnet build command, the project files will change in the following way:
.├── HelloWorld.csproj├── Program.cs├── bin│ └── Debug│ └── netcoreapp3.1│ ├── ...└── obj├── Debug│ └── netcoreapp3.1│ ├── ...
The bin/Debug/ folder contains all the app's DLLs. Below that, we can see the netcoreapp3.1 folder, which refers to the current target framework. Therefore, if you build your project using a multi-target approach, you will find a folder for each target framework you specified. Now that we are able to run a simple console app, let's have a closer look at the csproj present in the project.
