Enterprise Application Development with C# 9 and .NET 5 - Rishabh Verma - E-Book

Enterprise Application Development with C# 9 and .NET 5 E-Book

Rishabh Verma

0,0
39,59 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.

Mehr erfahren.
Beschreibung

.NET Core is one of the most popular programming platforms in the world for an increasingly large community of developers thanks to its excellent cross-platform support. This book will show you how to confidently use the features of .NET 5 with C# 9 to build robust enterprise applications.
Throughout the book, you'll work on creating an enterprise app and adding a key component to the app with each chapter, before ?nally getting it ready for testing and deployment. You'll learn concepts relating to advanced data structures, the Entity Framework Core, parallel programming, and dependency injection. As you progress, you'll cover various authentication and authorization schemes provided by .NET Core to make your apps and APIs secure. Next, you'll build web apps using ASP.NET Core 5 and deploy them on the cloud while working with various cloud components using Azure. The book then shows you how to use the latest Microsoft Visual Studio 2019 and C# 9 to simplify developer tasks, and also explores tips and tricks in Visual Studio 2019 to improve your productivity. Later, you'll discover various testing techniques such as unit testing and performance testing as well as di?erent methods to deploy enterprise apps.
By the end of this book, you’ll be able to create enterprise apps using the powerful features of .NET 5 and deploy them on the cloud.

Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:

EPUB
MOBI

Seitenzahl: 555

Veröffentlichungsjahr: 2021

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Enterprise Application Development with C# 9 and .NET 5

Enhance your C# and .NET skills by mastering the process of developing professional-grade web applications

Ravindra Akella

Arun Kumar Tamirisa

Suneel Kumar Kunani

Bhupesh Guptha Muthiyalu

BIRMINGHAM—MUMBAI

Enterprise Application Development with C# 9 and .NET 5

Copyright © 2021 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 authors, 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.

Group Product Manager: Aaron Lazar

Publishing Product Manager: Kushal Dave

Senior Editor: Rohit Singh

Content Development Editor: Tiksha Lad

Technical Editor: Pradeep Sahu

Copy Editor: Safis Editing

Project Coordinator: Francy Puthiry

Proofreader: Safis Editing

Indexer: Manju Arasan

Production Designer: Alishon Mendonca

First published: February 2021

Production reference: 1230221

Published by Packt Publishing Ltd.

Livery Place

35 Livery Street

Birmingham

B3 2PB, UK.

ISBN 978-1-80020-944-2

www.packt.com

To my mother, Mallika, and my father, Sastry, for their love and support.

– Ravindra Akella

To my parents, Rajaiah and Mahalakshmi, for their love, endless support, and encouragement.

– Suneel Kumar Kunani

Contributors

About the authors

Ravindra Akella works as a senior consultant at Microsoft and has more than 14 years of software development experience. Specializing in .NET and web-related technologies, his current role involves the end-to-end ownership of products right from architecture to delivery. He has led the software architecture design, development, and delivery of large, complex solutions using the Azure cloud and related technologies. He is a tech-savvy developer who is passionate about embracing new technologies. He has delivered talks and sessions on Azure and other technologies at international conferences. He has also authored books on .NET Core 3.0 before.

Authoring a book is a complex task, so I want to thank a few unsung heroes who helped make this happen. Firstly, thanks to my friend Rishabh Verma for involving me in this book. My sincere gratitude to my managers and colleagues who made me feel good about authoring this book. I am incredibly grateful to my parents, my wife, Srividya, and my son, Vaarush, for their continued support to complete this book. I am grateful to the incredible co-authors and technical reviewers for their support throughout the journey. Finally, I would like to thank Packt for giving me this opportunity.

Arun Kumar Tamirisa is a senior consultant currently working at Microsoft and has more than 15 years of IT experience in the design, development, and deployment of enterprise applications using the Microsoft .NET and Azure technology stacks. He has extensive experience in using popular client-side libraries such as Angular and Knockout.js and server-side technologies such as ASP.NET Core, web APIs, C#, and SQL Server. He is passionate about learning about, working on, and contributing toward developing solutions that solve complex problems.

My special thanks to the co-authors, the reviewers, and the Packt team for their tremendous support right from the beginning. I also wish to acknowledge the support of the extended team who have been working tirelessly in the background across time zones through the entire journey. Finally, I want to thank my wonderful family for their support and love.

Suneel Kumar Kunani is a passionate developer who strives to learn something new every day. With over 16 years of experience in .NET and Microsoft technologies, he works on architecting and building mission-critical, highly scalable, and secure solutions at Microsoft. He loves to teach and evangelize about the best practices in building distributed cloud solutions.

I would like to first and foremost thank my family for their support, patience, and encouragement throughout the long process of writing this book. I would like to extend my thanks to the Packt team, the co-authors, and the technical reviewers who made the journey of writing this book so pleasant. I am thankful to my managers and colleagues who supported and encouraged me in writing this book.

Bhupesh Guptha Muthiyalu is a Microsoft certified professional and works at Microsoft as a software engineering manager. He has 16+ years of software development experience on the .NET technology stack. His current role involves designing systems that are resilient to the iterations and changes required by the needs of enterprise businesses, validating architectural innovations, delivering solutions with high quality, managing the end-to-end ownership of products, and building diverse teams with capabilities to fulfill customer objectives. He is passionate about creating reusable components and identifying opportunities to make a product better.

I want to thank my parents, Mrs. Geetha Rani and Mr. Muthiyalu, my wife, Aparna, and my children, Tarak and Yashvak, for their continued support, patience, and encouragement throughout the long process of writing this book.

About the reviewers

Abhijit Jana is a technology leader, strategist, solution architect, development consultant, and trusted technology advisor with 14 years of experience in the IT industry, with expertise in development, architecting, engineering, consulting, services delivery, leadership, and mentoring. He is currently associated with West Pharmaceutical Services as the director of software engineering and is responsible for building, managing, and leading the overall application development and software engineering team. Before West, he was associated with Microsoft and is a former MVP. There, he managed several complex projects and delivered solutions to enterprise customers worldwide.

He has been a speaker at various technology conferences and several IITs across India.

Priyanka Shah has more than 12 years of experience in designing and implementing complex applications across a diverse technology stack (C#, .NET, .NET Core, Java, Azure, AWS, Python, NLP conversational AI, Docker, microservices, SQL/NoSQL databases, ELK, and Azure AI). She also has full-stack development experience. She currently works as a solution architect for low-latency/high-availability applications at an investment house in Singapore. She is also the innovation lead for AI/ML and data science streams. She has been awarded Microsoft MVP for AI and is a regular public speaker and blogger on ML/AI topics. She is active in the tech community space, where she regularly organizes global conferences and features in many international conferences on the Microsoft cloud and Azure AI/ML.

I am grateful to the members of Packt for presenting me with this opportunity to review a book authored on modern/trending tech stacks. I also want to thank Packt members for their patience and help during the process. Reviewing the book also gave me a chance to gain fresh insights into ASP.NET Core 5.0. It was an enriching experience. Lastly, thanks to my family for helping me with those extra hours that I put in for this endeavor!

Table of Contents

Preface

Section 1: Architecting an Enterprise Application and its Fundamentals

Chapter 1: Designing and Architecting the Enterprise Application

Technical requirements

A primer on common design principles and patterns

Design principles

Design patterns

Understanding common enterprise architectures

Common issues with monolithic apps

Separation of concerns/single responsibility architecture

Domain-driven architecture

Stateless services architecture

Event-driven architecture

Data storage and access architecture

Resiliency architecture

Evolution and operations architecture

Identifying enterprise application requirements (business and technical)

The application's business requirements

The application's technical requirements

Architecting an enterprise application

Solution structuring for an enterprise application

Summary

Questions

Chapter 2: Introducing .NET 5 Core and Standard

Technical requirements

Introducing .NET 5

Understanding the core features

Understanding application frameworks

Understanding the core components of .NET

Setting up the development environment

Understanding the CLI

Overview of global.json

What is .NET Standard?

Understanding the use of .NET 5 and .NET Standard

Understanding .NET 5 cross-platform and cloud application support

Cloud support

Summary

Questions

Further reading

Chapter 3: Introducing C# 9

Technical requirements

Understanding Init-only setters

Working with record types

The with expression

Understanding top-level statements

Examining objects with pattern matching

The constant pattern

Type patterns

Property patterns

Conjunctive and disjunctive patterns

Pattern matching with the switch expression

Tuple patterns

Understanding type inference with target-typed expressions

Understanding static anonymous functions

Eager initialization with module initializers

Summary

Questions

Section 2: Cross-Cutting Concerns

Chapter 4: Threading and Asynchronous Operations

Technical requirements

Understanding the jargon

Demystifying threads, lazy initialization, and ThreadPool

Working with System.Threading.Thread

ThreadPool

Lazy initialization

Understanding locks, semaphores, and SemaphoreSlim

The critical section and thread safety

Introducing locks

Mutex (Windows only)

Introducing semaphores and SemaphoreSlim

Choosing the right synchronization constructs

Introducing tasks and parallels

Introduction to Task and the TPL

Handling task exceptions

Implementing task cancellation

Implementing continuations

SynchronizationContext

TaskScheduler

Implementing data parallelism

Using Parallel LINQ (PLINQ)

Introducing async-await

The task-based asynchronous pattern

Principles of using async-await

Async streams with IAsyncEnumerable

Wrappers for legacy patterns

ThreadPool starvation

Using concurrent collections for parallelism

ConcurrentDictionary

Producer-consumer concurrent collections

The BlockingCollection<T> class

Summary

Questions

Further reading

Chapter 5: Dependency Injection in .NET

Technical requirements

What is DI?

Types of DI

DI in ASP.NET Core 5

Understanding service lifetimes

Managing application services

DI in Razor Pages

Using third-party containers

Summary

Questions

Chapter 6: Configuration in .NET Core

Technical requirements

Understanding configuration

Default configuration

Adding configurations

Reading configurations

Leveraging built-in configuration providers

Azure Key Vault configuration provider

File configuration provider

Building a custom configuration provider

Configuration source

Configuration provider

Configuration extension

Summary

Questions

Further reading

Chapter 7: Logging in .NET 5

Technical requirements

Characteristics of good logging

Understanding the available logging providers

Built-in logging providers

Third-party logging providers

Working with Azure App Service

Enabling application logging in Azure App Service

Monitoring using metrics

Alerting using metrics

Real-time telemetry in Azure Application Insights

Enabling application logging in Application Insights

Creating a .NET 5 logging class library

Summary

Questions

Chapter 8: Understanding Caching

Technical requirements

Introduction to caching

Client caching

Content Delivery Network (CDN)

Web server caching

Database caching

Application caching

Understanding the components of caching

Response caching

Distributed caching

Cache access patterns

Caching platforms

In-memory cache

Distributed cache

Designing a cache abstraction layer using distributed caching

Caching considerations

Summary

Questions

Further reading

Section 3: Developing Your Enterprise Application

Chapter 9: Working with Data in .NET 5

Technical requirements

Introduction to data

Relational Database Management System (RDBMS)

NoSQL

Disks, files, and directories

Handling directories

Reading/writing data with streams, binary, and strings

Streams

Reader/writer

TextReader/TextWriter versus BinaryReader/BinaryWriter

JSON.NET

SQL, Azure Cosmos DB, and Azure Storage

SQL Server

Azure Cosmos DB

Azure Storage

Working with EF Core

Configuration and querying

Code first versus database first

Designing a Data access service using Azure Cosmos DB

Summary

Questions

Further reading

Chapter 10: Creating an ASP.NET Core 5 Web API

Technical requirements

Introduction to Representational State Transfer (REST)

The REST maturity model

Understanding the internals of an ASP.NET Core 5 web API

Program and Startup classes

Understanding middleware

Building a custom middleware

Handling requests using controllers and actions

Understanding ASP.NET Core routing

Attribute-based routing

The ControllerBase class, the ApiController attribute, and the ActionResult class

Integration with the data layer

Creating DTOs

Service class contracts

The mapper class using AutoMapper

HttpClient factory for service-to-service calls

Implementing service classes

Implementing action methods in the controller

Understanding gRPC

Building a gRPC server in .NET

Building a gRPC client in .NET

Testing gRPC services

Summary

Questions

Further reading

Chapter 11: Creating an ASP.NET Core 5 Web Application

Technical requirements

Introduction to frontend web development

Razor syntax

Exploring Razor Pages

Exploring the ASP.NET Core MVC website

Understanding single-page applications

Integrating APIs with the service layer

Creating the controller and actions

Creating a UI using ASP.NET Core MVC

Setting up AdminLTE, the Layout page, and views

Understanding Blazor

Summary

Questions

Further reading

Section 4: Security

Chapter 12: Understanding Authentication

Technical requirements

Understanding the elements of authentication in .NET 5

Introduction to ASP.NET Core Identity

Sample implementation

Scaffolding

Integration with external login providers

Understanding OAuth 2.0

Tokens

Authorization grant types

Introduction to Azure AD

Azure AD B2C setup

Integration of our e-commerce application to Azure AD B2C

Introduction to Windows Authentication

Understanding best practices to secure client and server applications

Summary

Questions

Further reading

Chapter 13: Understanding Authorization

Technical requirements

Back to a few basics

Understanding authorization

Simple authorization

Enabling authorization globally

Role-based authorization

Policy-based role authorization

Implementing role-based authorization

Claim-based authorization

Policy-based authorization

Requirements

Requirement handlers

Registering a policy

Custom authorization

Custom authorization attributes

Authorization in client and server applications

Assigning roles to users

User identity in views

Summary

Questions

Further reading

Section 5: Health Checks, Unit Testing, Deployment, and Diagnostics

Chapter 14: Health and Diagnostics

Technical requirements

Introducing health checks

The health check API in ASP.NET Core 5

Adding a health check endpoint

Monitoring dependent URIs

Building a custom health check

Monitoring the application with Application Insights

Live Metrics

Usage analysis with Application Insights

Smart Detection

Application availability

Search

Logs

Snapshot Debugger

Performing remote debugging

Summary

Questions

Further reading

Chapter 15: Testing

Technical requirements

Introducing testing

Understanding unit testing

Unit testing in Visual Studio

Code coverage

Understanding functional testing

Automating functional test cases

Understanding load testing

Load testing with JMeter

Summary

Questions

Chapter 16: Deploying the Applications in Azure

Technical requirements

Introducing Azure DevOps

Boards

Repos

Pipelines

Test plans

Artifacts

Understanding the CI pipeline

Understanding the flow and components of a pipeline

Understanding the CD pipeline

Continuous deployment versus continuous delivery

Deploying an ASP.NET 5 application

Creating a pipeline for CI and CD

Summary

Questions

Further reading

Assessments

Chapter 1

Chapter 2

Chapter 3

Chapter 4

Chapter 5

Chapter 6

Chapter 7

Chapter 8

Chapter 9

Chapter 10

Chapter 11

Chapter 12

Chapter 13

Chapter 14

Chapter 15

Chapter 16

Why subscribe?

Other Books You May Enjoy

Packt is searching for authors like you

Leave a review - let other readers know what you think

Section 1: Architecting an Enterprise Application and its Fundamentals

In this part, we will envision an enterprise application with a high level of technical and functional requirements. We will then discuss the approach to architecting and designing the application. We will lay out the structure of the layers and solution using .NET 5. We will also learn about the new language features of C# 9 along with the .NET runtimes, which we will leverage to build the application.

This section contains the following chapters:

Chapter 1, Designing and Architecting the Enterprise ApplicationChapter 2, Introducing .NET 5 Core and StandardChapter 3, Introducing C# 9

Chapter 1: Designing and Architecting the Enterprise Application

Enterprise applications are software solutions designed to solve large and complex problems for enterprise organizations. They enable Order-to-Fulfillment capabilities for enterprise customers in the IT, government, education, and public sectors and empower them to digitally transform their businesses with capabilities such as product purchase, payment processing, automated billing, and customer management. The number of integrations when it comes to enterprise applications is quite high, and the volume of users is also very high as such applications are typically targeted at a global audience. To ensure that enterprise systems remain highly reliable, highly available, and highly performant, getting the design and architecture right is very important. Design and architecture form the foundation of any good software. They form the basis for the rest of the software development life cycle and therefore are very important to get right and avoid any rework later, which could prove very costly depending on the changes needed. So, you need a flexible, scalable, extensible, and maintainable design and architecture.

In this chapter, we will cover the following topics:

A primer on common design principles and patternsUnderstanding common enterprise architecturesIdentifying enterprise application requirements (business and technical)Architecting an enterprise applicationSolution structuring for an enterprise application

By the end of the chapter, you will be able to design and architect applications by following the right design principles.

Technical requirements

You will need a basic understanding of .NET Core, C#, and Azure.

A primer on common design principles and patterns

Every piece of software in the world solves one real-world problem or another. As time goes by, things change, including what we expect from any specific software. To manage this change and deal with various aspects of software, engineers have developed a number of programming paradigms, frameworks, tools, techniques, processes, and principles. These principles and patterns, proven over time, have become guiding stars for engineers to use to collaborate and build quality software.

We will be discussing object-oriented programming (OOP) in this chapter, a paradigm based on the concepts of "objects" and their states, behaviors, and interactions with each other. We will also cover some common design principles and patterns.

Principles are high-level abstract guidelines to be followed while designing; they are applicable regardless of the programming language being used. They do not provide implementation guidelines.

Patterns are low-level specific implementation guidelines that are proven, reusable solutions for recurring problems. Let's first start with design principles.

Design principles

Techniques become principles if they are widely accepted, practiced, and proven to be useful in any industry. Those principles become solutions to make software designs more understandable, flexible, and maintainable. We will cover the SOLID, KISS, and DRY design principles in this section.

SOLID

The SOLID principles are a subset of many principles promoted by American software engineer and instructor Robert C. Martin. These principles have become de facto standard principles in the OOP world and have become part of the core philosophy for other methodologies and paradigms.

SOLID is an acronym for the following five principles:

Single responsibility principle (SRP): An entity or software module should only have a single responsibility. You should avoid granting one entity multiple responsibilities:

Figure 1.1 – SRP

Open-closed principle (OCP): Entities should be designed in such a way that they are open for extension but closed for modification. This means regression testing of existing behaviors can be avoided; only extensions need to be tested:

Figure 1.2 – OCP

Liskov substitution principle (LSP): Parent or base class instances should be replaceable with instances of their derived classes or subtypes without altering the sanity of the program:

Figure 1.3 – LSP

Interface segregation principle (ISP): Instead of one common large interface, you should plan multiple, scenario-specific interfaces for better decoupling and change management:

Figure 1.4 – ISP

Dependency inversion principle (DIP): You should avoid having any direct dependency on concrete implementations. High-level modules and low-level modules should not depend on each other directly, and instead, both should depend on abstractions as much as possible. Abstraction should not depend on details and details should depend on abstractions.

Figure 1.5 – DIP

Don't repeat yourself (DRY)

With DRY, a system should be designed in such a way that the implementation of a feature or a pattern should not be repeated in multiple places. This would result in maintenance overhead as a change in requirements would result in modification being needed at multiple places. If you fail to make a necessary update in one place by mistake, the behavior of the system will become inconsistent. Rather, the feature should be wrapped into a package and should be reused in all places. In the case of a database, you should look at using data normalization to reduce redundancy:

Figure 1.6 – DRY

This strategy helps in reducing redundancy and promoting reuse. This principle helps an organization's culture as well, encouraging more collaboration.

Keep it simple, stupid (KISS)

With KISS, a system should be designed as simply as possible, avoiding complicated designs, algorithms, new untried technologies, and so on. You should focus on leveraging the right OOP concepts and reusing proven patterns and principles. Include new or non-simple things only if it is necessary and adds value to the implementation.

When you keep it simple, you will be able to do the following better:

Avoid mistakes while designing/developingKeep the train running (there is always a team whose job is to maintain the system, although they are not the team that developed the system in the first place)Read and understand your system and code (your system and code need to be understandable to people new to it or people using it far in the future)Do better and less error-prone change management

With this, we are done with our primer on common design principles; we have learned about SOLID, DRY, and KISS. In the next section, we'll look at some common design patterns in the context of real-world examples to help you understand the difference between principles and patterns and when to leverage which pattern, a skill that's essential for good design and architecture.

Design patterns

While following design principles in the OOP paradigm, you may see the same structures and patterns repeating over and again. These repeating structures and techniques are proven solutions to common problems and are known as design patterns. Proven design patterns are easy to reuse, implement, change, and test. The well-known book Design Patterns: Elements of Reusable Object-Oriented Software, comprising what are known as the Gang of Four (GOF) design patterns, is considered as the bible of patterns.

We can categorize the GOF patterns as follows:

Creative: Helpful in creating objectsStructural: Helpful in dealing with the composition of objectsBehavioral: Helpful in defining the interactions between objects and distributing responsibility

Let's look at the patterns with some real-life examples.

Creational design patterns

Let's have a look at some creational design patterns along with relevant examples in the following table:

Table 1.1

Structural design patterns

The following table includes some examples of structural design patterns:

Table 1.2

Behavior design patterns

The following table includes some examples of behavioral design patterns:

Table 1.3

Sometimes, you can become overwhelmed by all these patterns being on the table, but really, any design is a good design until it violates the basic principles. One rule of thumb that we can use is to go back to basics, and in design, principles are the basics.

Figure 1.7 – Pattern versus principles

With this, we are done with our primer on common design principles and patterns. By now, you should have a good understanding of the different principles and patterns, where to use them, and what it takes to build a great solution. Let's now spend some time looking at common enterprise architectures.

Understanding common enterprise architectures

There are a few principles and architectures that are commonly practiced when designing enterprise applications. First and foremost, the goal of any architecture is to support business needs at the lowest cost possible (costs being time and resources). A business wants software to enable it rather than acting as a bottleneck. In today's world, availability, reliability, and performance are the three KPIs of any system.

In this section, we will first look at the issues with monolithic architecture and then we will see how to avoid them using widely adopted and proven architectures for developing enterprise applications.

Consider a classical monolithic e-commerce website application, such as the one shown in the following diagram, with all the business providers and functionality in a single app and data being stored in a classical SQL database:

Figure 1.8 – Monolithic application

The monolithic architecture was widely adopted 15-20 years ago, but plenty of problems arose for software engineering teams when systems grew and business needs expanded over time. Let's look at some of the common issues with this approach.

Common issues with monolithic apps

Let's have a look at the scaling issues:

In a monolithic app, the only way to horizontally scale is by adding more compute to the system. This leads to higher operational costs and unoptimized resource utilization. Sometimes, scaling becomes impossible due to conflicting needs in terms of resources.As all the features mostly use single storage, there is the possibility of locks leading to high latency, and there will also be physical limits as to how far a single storage instance can scale.

Here are some issues associated with availability, reliability, and performance:

Any changes in the system will require the redeployment of all components, leading to downtime and low availability.Any non-persistent state, such as sessions stored in a web app, will be lost after every deployment. This will lead to the abandonment of all workflows that were triggered by users.Any bugs in a module, such as memory leaks or security bugs, make all the modules vulnerable and have the potential to impact the whole system.Due to the highly coupled nature and sharing of resources within modules, there will always be unoptimized use of resources, leading to high latency in the system.

Lastly, let's see what the impact on the business and engineering teams is:

The impact of a change is difficult to quantify and needs extensive testing. Hence, it slows down the rate of delivery to production. Even a small change will require the entire system to be deployed again.In a single highly coupled system, there will always be physical limits on collaboration across teams to deliver any feature.New scenarios such as mobile apps, chatbots, and analysis engines will take more effort as there are no independent reusable components or services.Continuous deployment is almost impossible.

Let's try to solve these common problems by adopting some proven principles/architectures.

Separation of concerns/single responsibility architecture

Software should be divided into components or modules based on the kind of work it performs. Every module or component should have a single responsibility. Interaction between components should be via interfaces or messaging systems. Let's look at the n-tier and microservices architecture and how the separation of concerns is taken care of.

N-tier architecture

N-tier architecture divides the application of a system into three (or n) tiers:

Presentation (known as the UX layer, the UI layer, or the work surface)Business (known as the business rules layer or the services layer)Data (known as the data storage and access layer)

Figure 1.9 – N-tier architecture

These tiers can be owned/managed/deployed separately. For example, multiple presentation layers, such as web, mobile, and bot layers, can leverage the same business and data tier.

Microservices architecture

Microservices architecture consists of small, loosely coupled, independent, and autonomous services. Let's look at their benefits:

Services can be deployed and scaled independently. An issue in one service will have a local impact and can be fixed by just deploying the impacted service. There is no need to share a technology or framework.Services communicate with each other via well-defined APIs or a messaging system such as Azure Service Bus:

Figure 1.10 – Microservices architecture

As seen in the preceding figure, a service can be owned by independent teams and can have its own cycle. Services are responsible for managing their own data stores. Scenarios demanding lower latency can be optimized by bringing in a cache or high-performance NoSQL stores.

Domain-driven architecture

Each logical module should not have a direct dependency on another module. Each module or component should serve a single domain.

Modeling services around a domain prevents service explosion. Modules should be loosely coupled and modules that are likely to change together can be clubbed together.

Stateless services architecture

Services should not have any state. State and data should be managed independently from services, that is, externally. By delegating state externally, services will have the resources to serve more requests with high reliability.

Session affinity should not be enabled as it leads to sticky session issues and will stop you from getting the benefits of load balancing, scalability, and the distribution of traffic.

Event-driven architecture

The main features of event-driven architecture are as follows:

In event-driven architecture, communication, which is generally known as (publisher-subscriber communication) between modules, is primarily asynchronous and achieved via events. Producers and consumers are totally decoupled from each other. The structure of the event is the only contract that is exchanged between them.There can be multiple consumers of the same event taking care of their specific operations; ideally, they won't even be aware of each other. Producers can continuously push events without worrying about the availability of the consumers.Publishers publish events via a messaging infrastructure such as queues or a service bus. Once an event is published, the messaging infrastructure is responsible for sending the event to eligible subscribers:

Figure 1.11 – Event-driven architecture

This architecture is best suited for scenarios that are asynchronous in nature. For example, long-running operations can be queued for processing. A client might poll for a status or even act as a subscriber for an event.

Data storage and access architecture

Data storage and access architecture play a vital role in the scaling, availability, and reliability of an overall system:

A service should decide the type of data storage depending on the needs of the operation.Data should be partitioned and modeled according to the needs of the given operation. Hot partitions should be avoided at any cost. Replication should be opted for if you need more than one type of structure from the same data.The correct consistency model should be chosen for lower latency. For example, an operation that can afford to have stale data for some time should use weak/eventual consistency. Operations that have the potential to change the state and need real-time data should opt for stronger consistency.Caching data that is appropriate to services helps the performance of services. Areas should be identified where data can be cached. Depending on the given need, an in-memory or out-of-memory cache can be chosen.

Resiliency architecture

As the communication between components increases, so does the possibility of failures. A system should be designed to recover from any kind of failure. We will cover a few strategies for building a fault-tolerant system that can heal itself in the case of failures.

If you are familiar with Azure, you'll know that applications, services, and data should be replicated globally in at least two Azure regions for planned downtime and unplanned transient or permanent failures. Choosing Azure App Service to host web applications, using REST APIs, and choosing a globally distributed database service such as Azure Cosmos DB, is wise in these scenarios. Choosing Azure paired regions will help in business continuity and disaster recovery (BCDR), as at least one region in each pair will be prioritized for recovery if an outage affects multiple regions. Now, let's see how to tackle different types of faults.

Transient faults can occur in any type of communication or service. You need to have a strategy to recover from transient faults, such as the following:

Identify the operation and type of a transient fault, then determine the appropriate retry count and interval.Avoid anti-patterns such as endless retry mechanisms with a finite number of retries or circuit breakers.

If a failure is not transient, you should respond to the failure gracefully by choosing some of the following options:

Failing overCompensating for any failed operationsThrottling/blocking the bad client/actorUsing a leader election to select a leader in the case of a failure

Telemetry plays a big role here; you should have custom metrics to keep a tab on the health of any component. Alerts can be raised when a custom event occurs or a specific metric reaches a certain threshold.

Evolution and operations architecture

Evolution and operations play a vital role in continuous integration, deployment, staged feature rollout, and reducing downtime and costs:

Services should be deployed independently.Designing an ecosystem that can scale enables a business to grow and change over time.A loosely coupled system is best for a business, as any change or feature can be delivered with good velocity and quality. Changes can be managed and scoped to individual components.Elasticity in scale leads to the better management of resources, which in turn reduces operation costs.A continuous build and release pipeline alongside a blue-green deployment strategy can help in identifying issues early in a system. This also enables the testing of certain hypotheses with a reduced amount of production traffic.

With this, we are done with our coverage of common enterprise architectures. Next, we will look at enterprise application requirements and different architectures through the lens of the design principles and common architectures we have learned about.

Identifying enterprise application requirements (business and technical)

In the next few chapters, we will build a working e-commerce application. It will be a three-tier application consisting of a UI layer, a service layer, and a database. Let's look at the requirements for this e-commerce application.

The solution requirements are the capabilities to be implemented and made available in the product to solve a problem or achieve an objective.

The business requirements are simply the end customer's needs. In the IT world, "business" generally refers to "customers." These requirements are collected from various stakeholders and documented as a single source of truth for everyone's reference. This eventually becomes the backlog and scope of work to be completed.

The technical requirements are the technology aspects that a system should implement, such as reliability, availability, performance, and BCDR. These are also known as quality of service (QOS) requirements.

Let's break the typical business requirements for an e-commerce application site down into the following categories: Epic, Feature, and User Story.

The application's business requirements

The following screenshot from Azure DevOps shows a summary of the backlog for our business requirements. You can see the different features expected in our application along with the user stories:

Figure 1.12 – Requirements backlog from Azure DevOps

The application's technical requirements

Having seen the business requirements, let's now go through the technical requirements:

The e-commerce application should be highly available, that is, available for 99.99% of the time for any 24-hour period.The e-commerce application should be highly reliable, that is, reliable 99.99% of the time for any 24-hour period.The e-commerce application should be highly performant: 95% of the operations should take less than or equal to 3 seconds.The e-commerce application should be highly scalable: it should automatically scale up/down based on the varying load.The e-commerce application should have monitoring and alerts: an alert should be sent to a support engineer in the case of any system failure.

Here are the technical aspects identified for the e-commerce application and its requirements:

Frontend

A web application (e-commerce) using ASP.NET 5.0

Core components

Logging/caching/configuration in C# 9.0 and .NET 5.0

Middle tier

An Azure API gateway to implement authenticationA user management service through an ASP.NET 5.0 web API to add/remove usersProduct and pricing services through an ASP.NET 5.0 web API to get products from the data storeA domain data service through an ASP.NET 5.0 web API to get the domain data, such as country data.A payment service through an ASP.NET 5.0 web API to complete paymentsAn order processing service through an ASP.NET 5.0 web API to submit and search ordersAn invoice processing service through an ASP.NET 5.0 web API to generate invoicesA notification service through an ASP.NET 5.0 web API to send notifications such as emails

Data tier

A data access service through an ASP.NET 5.0 web API to talk to Azure Cosmos DB to read/write dataEntity Framework Core to access data

Azure Stack

Azure Cosmos DB as a backend data store Azure Service Bus for asynchronous message processingAzure App Service to host the web application and web APIsAzure Traffic Manager for high availability and responsivenessAzure Application Insights for diagnostics and telemetryAzure paired regions for better resiliencyAzure resource groups to create Azure Resource Manager (ARM) templates and deploy to the Azure subscriptionAzure Pipelines for continuous integration and continuous deployment (CI/CD)

We are now done with the enterprise application requirements. Next, we will look at architecting an enterprise application.

Architecting an enterprise application

The following architecture diagram depicts what we are building. We need to keep in mind all of the design principles, patterns, and requirements we saw in this chapter when we are architecting and developing the application. The next figure shows the proposed architecture diagram for our e-commerce enterprise application:

Figure 1.13 – Our e-commerce application's three-tier architecture diagram

Separation of concerns/SRP has been taken care of at each tier. The presentation tier containing the UI is separated from the services tier containing the business logic, which is again separated from the data access tier containing the data store.

The high-level components are unaware of the low-level components consuming them. The data access tier is unaware of the services consuming it, and services are unaware of the UX tier consuming them.

Each service is separated based on the business logic and functionality it is supposed to perform.

Encapsulation has been taken care of at the architecture level and should be taken care of during development as well. Each component in the architecture will be interacting with other components through well-defined interfaces and contracts. We should be able to replace any component in the diagram without worrying about its internal implementation if it adheres to the contracts.

The loosely coupled architecture here also helps in faster development and faster deployment to market for customers. Multiple teams can work in parallel on each of their components independently. They share the contracts and timelines for integration testing at the start, and once the internal implementation and unit tests are done, they can start with integration testing.

Refer to the following figure:

Figure 1.14 – Our e-commerce application components, broken down by chapter

From the figure, we identify the chapters in which different parts of the e-commerce application that we will build will be covered, which are explained as follows:

Creating an ASP.NET web application (our e-commerce portal) will be covered as part of Chapter 11, Creating an ASP.NET Core 5 Web Application.Authentication will be covered as part of Chapter 12, Understanding Authentication.The order processing service and the invoice processing service are the two core services for generating orders and invoicing. They will be the heart of the e-commerce application as they are the ones that are responsible for the revenue. Creating an ASP.NET Core web API will be covered as part of Chapter 10, Creating an ASP.NET Core 5 Web API, and cross-cutting concerns will be covered as part of Chapter 5, Dependency Injection in .NET, Chapter 6, Configuration in .NET Core, and Chapter 7, Logging in .NET 5, respectively. The DRY principle will be taken care of by reusing core components and cross-cutting concerns instead of repeating implementations.Caching will be covered as part of the product pricing service in Chapter 8, Understanding Caching. Caching will help to improve the performance and scalability of our system, with temporary copies of frequently accessed data being available in memory.Data storage, access, and providers will be covered as part of the data access layer in Chapter 9, Working with Data in .NET 5. The kind of architecture that we have adopted, where data and access to it is separate from the rest of the application, gives us better maintenance. Azure Cosmos DB is our choice to scale throughput and storage elastically and independently across any number of Azure regions worldwide. It is also secure by default and enterprise-ready.

This concludes our discussion on architecting our enterprise application. Next, we will look at the solution structure for our enterprise application.

Solution structuring for an enterprise application

We will go with a single solution for all our projects to keep things simple, as shown in the following figure. The other approach of having separate solutions for the UI, shared components, web APIs, and so on can also be considered when the number of projects in the solution explodes and causes maintenance issues. The following screenshot shows our application's solution structure:

Figure 1.15 – Solution structure for the e-commerce application

Summary

In this chapter, we learned about common design principles such as SOLID, DRY, and KISS. We also looked at various design patterns with real-world examples. Then, we looked at different enterprise architectures, identified requirements for the e-commerce application that we are going to build, and applied what we learned in order to architect our e-commerce application. You can now apply what you have learned here when you design any application. In the next chapter, we will learn about .NET 5 Core and Standard.

Questions

What is the LSP?

a. Base class instances should be replaceable with instances of their derived type.

b. Derived class instances should be replaceable with instances of their base type.

c. Designing for generics that can work with any data type.

What is the SRP?

a. Instead of having one common large interface, plan for multiple scenario-specific interfaces for better decoupling and change management.

b. You should avoid having direct dependencies on a concrete implementation; instead, you should depend on abstractions as much as possible.

c. An entity should only have a single responsibility. You should avoid giving one entity multiple responsibilities.

d. Entities should be designed in such a way that they should be open for extension but closed for modification.

What is the OCP?

a. Entities should be open to modification but closed for extension.

b. Entities should be open to extension but closed for modification.

c. Entities should be open to composition but closed for extension.

d. Entities should be open to abstraction but closed for inheritance.

Which pattern is used to make two incompatible interfaces work together?

a. Proxy

b. Bridge

c. Iterator

d. Adapter

Which principle ensures that services can be deployed and scaled independently and that an issue in one service will have a local impact and can be fixed by just redeploying the impacted service?

a. The domain-driven design principle

b. The Single Responsibility Principle

c. The stateless service principle

d. The resiliency principle

Chapter 2: Introducing .NET 5 Core and Standard

.NET is a developer platform that offers libraries and tools for building many different types of applications, such as web, desktop, mobile, games, Internet of Things (IoT), and cloud applications. Using .NET, we can develop applications targeting many operating systems, including Windows, macOS, Linux, Android, iOS, and so on, and it supports processor architectures such as x86, x64, ARM32, and ARM64.

.NET also supports application development using multiple programming languages, such as C#, Visual Basic, and F#, using popular integrated development environments (IDEs) such as Visual Studio, Visual Studio Code, and Visual Studio for Mac.

After .NET Core 3.1, .NET 5 is now a major release that includes C# 9 and F# 5 with many new features and performance improvements.

The following topics are covered in this chapter:

Introducing .NET 5Understanding the core components of .NET 5Understanding the CLIWhat is .NET Standard?Understanding .NET 5 cross-platform and cloud application support

This chapter will help us understand a few core components, libraries, and tools that are included in .NET for developing the applications.

Technical requirements

A Windows, Linux, or Mac machine is required.

Introducing .NET 5

In 2002, Microsoft released the first version of .NET Framework, a development platform to develop web and desktop applications. .NET Framework offers many services, including managed code execution, a vast set of APIs via a base class library, memory management, a common type system, language interoperability, and development frameworks such as ADO.NET, ASP.NET, WCF, WinForms, Windows Presentation Framework (WPF), and so on. Initially, it was released as a separate installer, but it was later integrated and shipped with the Windows operating system. .NET Framework 4.8 is the latest version of .NET Framework.

In 2014, Microsoft announced an open source, cross-platform implementation of .NET called .NET Core. .NET Core was built from scratch to make it cross-platform and it is currently available on Linux, macOS, and Windows. .NET Core is fast and modular, and offers support side by side so that we can run different versions of .NET Core on the same machine without affecting other applications.

.NET 5 is an open source, cross-platform implementation of .NET with which you can build console, web, desktop, and cloud applications that can run on Windows, macOS, and Linux operating systems. .NET 5 is the first release in the .NET unification journey, with many libraries, tools/SDKs, and runtime and performance improvements.

Next, let's understand the core features of .NET.

Understanding the core features

The following are a couple of the core features of .NET that we will understand about more in depth:

Open source: .NET is a free (with no licensing costs, including for commercial use), open source developer platform that offers many development tools for Linux, macOS, and Windows. Its source code is maintained by Microsoft and the .NET community on GitHub. You can access the .NET repositories at https://github.com/dotnet/core/blob/master/Documentation/core-repos.md.Cross-platform: .NET applications run on many operating systems, including Linux, macOS, Android, iOS, tvOS, watchOS, and Windows. They also run consistently across processor architectures such as x86, x64, ARM32, and ARM64.

With .NET, we can build the following types of applications:

Table 2.1

Programming languages: .NET supports multiple programming languages. Code written in one language is accessible to other languages. The following table shows the supported languages:

Table 2.2

IDEs: .NET supports multiple IDEs. Let's understand each one:

a. Visual Studio is a feature-rich IDE available on the Windows platform to build, debug, and publish .NET applications. It is available in three editions: Community, Professional, and Enterprise. Visual Studio 2019 Community Edition is free for students, individual developers, and organizations contributing to open source projects.

b. Visual Studio for Mac is free and available for macOS. It can be used to develop cross-platform applications and games for iOS, Android, and the web using .NET.

c. Visual Studio Code is a free, open source, lightweight yet powerful code editor available on Windows, macOS, and Linux. It has built-in support for JavaScript, TypeScript, and Node.js and with extensions, you can add support for many popular programming languages.

d. Codespaces, currently in preview, is a cloud development environment powered by Visual Studio Code and hosted by GitHub to develop .NET applications.

Deployment models: .NET supports two modes of deployment:

a. Self-contained: When a .NET application is published in self-contained mode, the published artifact contains the .NET runtime, libraries, and the application and its dependencies. Self-contained applications are platform-specific, and the target machine need not have the .NET runtime installed. The machine uses the .NET runtime shipped along with the application to run the application.

b. Framework-dependent: When a .NET application is published in framework-dependent mode, the published artifact contains only the application and its dependencies. The .NET runtime must be installed on the target machine to run the application.

Next, let's understand the application frameworks offered by .NET.

Understanding application frameworks

.NET simplifies application development by offering many application frameworks. Each application framework contains a set of libraries to develop targeted applications. Let's understand each in detail:

ASP.NET Core: This is an open source and cross-platform application development framework that lets you build modern, cloud-based, internet-connected applications, such as web, IoT, and API applications. ASP.NET Core is built on top of .NET Core, hence you can build and run across platforms such as Linux, macOS, and Windows.WPF: This is a UI framework that lets you create desktop applications for Windows. WPF uses Extensible Application Markup Language (XAML), a declarative model for application development.Entity Framework (EF) Core: This is an open source, cross-platform, lightweight, object-relational mapping (ORM) framework to work with databases using .NET objects. It supports LINQ queries, change tracking, and schema migrations. It works with popular databases such as SQL Server, SQL Azure, SQLite, Azure Cosmos DB, MySQL, and many more.Language-Integrated Query (LINQ): This adds query capabilities to .NET programming languages. LINQ allows you to query data from a database, XML, in-memory arrays, and collections with the same API.

In the next section, let's understand the core components of .NET.

Understanding the core components of .NET

.NET has two major components: a runtime and base class libraries. The runtime includes a garbage collector (GC) and the just-in-time (JIT) compiler, which manages the execution of .NET applications and base class libraries (BCLs), also known as runtime libraries or framework libraries, which contain the fundamental building blocks for .NET applications.

The .NET SDK is available for download at https://dotnet.microsoft.com/download/dotnet/5.0. It contains a set of libraries and tools to develop and run .NET applications. You can choose to install either the SDK or the .NET runtime. To develop .NET applications, you should install the SDK on the development machine and the .NET runtime to run .NET applications. The .NET runtime is included in the .NET SDK, hence you don't have to install the .NET runtime separately if you have already installed the .NET SDK:

Figure 2.1 – Visualization of the .NET SDK

The .NET SDK contains the following components:

Common Language Runtime (CLR): CLR executes the code and manages memory allocation. .NET applications, when compiled, produce an intermediate language (IL). CLR uses a JIT compiler to convert compiled code to machine code. It is a cross-platform runtime that is available for Windows, Linux, and macOS.Memory management: The GC manages the allocation and release of memory for .NET applications. For every new object created, memory is allocated in the managed heap and when there is not enough free space available, GC checks for objects in the managed heap and removes them if they are no longer used in the application. For more information, you can refer to https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection. JIT: When .NET code is compiled, it is converted to IL. IL is platform- and language-independent, so when the runtime runs the application, JIT converts IL into machine code that the processor understands.Common type system: This defines how types are defined, used, and managed in CLR. It enables cross-language integrations and ensures type safety.Base class library: This contains implementations for primitive types such as System.String and System.Boolean, collections such as List<T> and Dictionary<TKey, TValue>, and utility functions to perform I/O operations, HTTP, serialization, and many more. It simplifies .NET application development. Roslyn compilers: Roslyn is an open source C# and Visual Basic compiler with rich code analysis APIs. It enables building code analysis tools with the same API used by Visual Studio.MSBuild: This is a tool to build .NET applications. Visual Studio uses MSBuild to build .NET applications.NuGet: This is an open source package manager tool with which you can create, publish, and reuse code. A NuGet package contains compiled code, its dependent files, and a manifest that includes package version number information.

In the next section, let's understand how to set up the development environment to create and run .NET applications.

Setting up the development environment

Setting up a development environment is very easy. You will need the .NET SDK to build and run .NET applications; optionally, you can choose to install IDEs that support .NET application development. You need to perform the following steps to set up the .NET SDK on your machine:

Note

Visual Studio Community Edition is free for individual developers, classroom learning, and for unlimited users in organizations contributing to research or open source projects. It offers the same features as Professional Edition, but for advanced features such as advanced debugging and diagnostics tools, testing tools, and more, you need to have Enterprise Edition. To compare features, you can visit