Core
Core
James Chambers
David Paquette
Simon Timms
PUBLISHED BY
Microsoft Press
A division of Microsoft Corporation
One Microsoft Way
Redmond, Washington 98052-6399
Copyright © 2017 by James Chambers, David Paquette & Simon Timms
All rights reserved. No part of the contents of this book may be reproduced or transmitted in any form or by any
means without the written permission of the publisher.
Library of Congress Control Number: 2016958907
ISBN: 978-1-5093-0406-6
First Printing
Microsoft Press books are available through booksellers and distributors worldwide. If you need support related
to this book, email Microsoft Press Support at mspinput@microsoft.com. Please tell us what you think of this
book at http://aka.ms/tellpress.
This book is provided “as-is” and expresses the author’s views and opinions. The views, opinions and information
expressed in this book, including URL and other Internet website references, may change without notice.
Some examples depicted herein are provided for illustration only and are fictitious. No real association or
connection is intended or should be inferred.
Microsoft and the trademarks listed at http://www.microsoft.com on the “Trademarks” webpage are trademarks
of the Microsoft group of companies. All other marks are property of their respective owners.
Introduction xvii
Index 387
vi
Table of Contents
Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii
ASP.NET. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
ASP.NET MVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Web API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
ASP.NET Core . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Chapter 2 Influencers 17
Backward compatibility. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Rails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Open source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
OWIN. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
http://aka.ms/tellpress
vii
Chapter 3 Models, Views, and Controllers 27
The M, the V, and the C of it. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Diving into Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Views. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Partial Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Controllers (...and Actions!). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
The API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Chapter 5 Builds 45
Command Line Builds. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Build Servers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Chapter 6 Deployment 57
Picking a web server. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Kestrel. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Reverse Proxy. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
IIS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
viii Contents
Nginx. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Publishing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Build Types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Building A Package. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
The Case for Azure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Azure Deployments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
Container Deployments. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
Chapter 8 Cross-Platform 93
Up and Running on Ubuntu. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Installing .NET Core. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
The dotnet CLI. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Choosing a Code Editor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
ix
Contents
Chapter 9 Containers 105
Repeatable Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
Docker. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
x Contents
Switching to Code. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Explicitly Using Markup. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
Razor Parser Control Cheat Sheet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
Bringing in More C# Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
Using C# Types in Your Views. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
Defining a Model. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
Using View Data. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
Working with Layouts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Foundations of Layouts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Including Sections from Views. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
Defining and Consuming Partial Views . . . . . . . . . . . . . . . . . . . . . . . . . . 161
Enhancing Views with Advanced Razor Functionality . . . . . . . . . . . . . . . . . . 162
Injecting Services into a View. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Working with Tag Helpers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
Avoiding Duplication in Your Views. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Using Alternate View Engines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
xi
Contents
PART 3 SPRINT RETRO: THE BELLY OF THE BEAST 189
Organization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
xii Contents
Bundler & Minifier. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
Grunt. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
gulp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
WebPack. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
Which Tool is Right for me? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
TypeScript. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
ES2015 to ES5 Compiler. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
Typing System. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
Module Loading. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
Bower. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
Adding Dependencies. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
Referencing Assets from Bower Packages. . . . . . . . . . . . . . . . . . . . . . . 262
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
xiii
Contents
Establishing a Development Workflow. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
Using Command Line Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
Working in Visual Studio Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
Modifying the Project Build Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
Using Third Party Frameworks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
Extending a CSS Framework. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
Customizing a CSS Framework Footprint. . . . . . . . . . . . . . . . . . . . . . . . 278
Leveraging CSS Frameworks for Custom Style Sheets. . . . . . . . . . . . 279
Alternatives to CSS Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
xiv Contents
Chapter 20 Testing 307
Unit Testing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
XUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
JavaScript Testing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320
Other Types of Testing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
xv
Contents
Setting the Current Culture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
MediatR. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
A Brief Introduction to the Messaging Pattern. . . . . . . . . . . . . . . . . . . 377
Implementing a Mediator. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
Areas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
Postfix 383
Index 387
http://aka.ms/tellpress
xvi Contents
Introduction
A SP.NET Core MVC is Microsoft’s latest web framework for .NET developers. It is the
next version of the now-familiar MVC Framework and aspires to cross boundaries by
enabling cross-platform development and deployment. It leverages a wide assortment
of open source libraries and is, itself built as open source software. ASP.NET Core MVC
helps developers to separate concerns like business logic, routing, services, and views
and provides new systems for configuration and extensibility. It uses the C# program-
ming language and the Razor view engine. If you are an experienced .NET developer or
a newcomer to the .NET platform, ASP.NET Core MVC is likely what your projects will be
built from.
This book follows the first few sprints of an application being redeveloped by a team
at a fictional company named Alpine Ski House. Each chapter contains a little bit of infor-
mation about the challenges the team is facing and how they work to overcome them.
Despite having a short story element to each chapter, the book dives deep to cover not
only the features of ASP.NET Core MVC, but also the tooling around it that developers
will use to build, maintain and deploy their applications.
In addition to its story elements and technical information around ASP.NET Core
MVC, the book discusses the new version of Entity Framework, package management
systems, and peripheral technologies that are used by modern web developers. Beyond
the explanatory content, the book also comes with an accompanying project—the very
same project that the developers at Alpine Ski House have built.
xvii
Assumptions
Readers should know how to program at an intermediate to senior level. Readers should
be proficient in C#, have a background in web development, and understand funda-
mentals of working in Visual Studio. Experience with previous versions of MVC will be
beneficial, but not required. Familiarity in working with a command line interface will be
an asset. After completing this book you will be able to build a meaningful and relevant
database-driven application and deploy it to a cloud-based infrastructure.
■■ Part 1, “Alpine Ski House,” Covers background information that sets up the ex-
ample app and fictional characters in the story used throughout the book
■■ Part 2, “Sprint Retro: A Journey of 1000 Steps,” focuses on the features required
to get our application out the door, configuring the pipeline so that deployment
happens on-the-fly in a way that the whole team understands.
■■ Part 3, “Sprint Retro: The Belly of the Beast,” focuses on the core features needed
to get the business running with our sample application. Here we introduce data
access using the Entity Framework Core, creating views using Razor, Configu-
ration and Logging, Security and User Management, and finally Dependency
Injection.
■■ Part 4, “Sprint Retro 3: Home Stretch” covers JavaScript and dependency man-
agement, along with building on top of the previous foundations.
Postfix covers some important topics such as testing, refactoring and extensibility.
xviii Introduction
Finding your best starting point in this book
The different sections of ASP.NET Core Application Development: Building an applica-
tion in four sprints cover a wide range of technologies associated with the ASP.NET Core
framework. Depending on your needs, and your existing understanding of Microsoft’s
web stack, you may wish to focus on specific areas of the book. Use the following table to
determine how best to proceed through the book.
Most of the book’s chapters include hands-on samples that let you try out the concepts
just learned. No matter which sections you choose to focus on, be sure to download and
install the sample applications on your system.
■■ The book includes samples for C# programmers and syntaxes such as HTML, CSS,
SCSS and Razor.
■■ A plus sign (+) between two key names means that you must press those keys at
the same time. For example, “Press Alt+Tab” means that you hold down the Alt
key while you press the Tab key.
■■ A vertical bar between two or more menu items (e.g. File | Close), means that
you should select the first menu or menu item, then the next, and so on.
xix
Introduction
System requirements
You will need the following hardware and software to run the sample application accom-
panying this book:
■■ Your code editor of choice. We use Visual Studio 2015 (any edition) or newer on
Windows and Visual Studio Code on Windows, Mac and Ubuntu Linux.
■■ SQL Server LocalDB (included with Visual Studio 2015 or newer on Windows).
Linux or Mac users will need access to a SQL Server database hosted either on a
Windows machine or in Microsoft Azure.
■■ At least 1 GB of RAM
https://github.com/AspNetMonsters/AlpineSkiHouse
Follow the instructions on the GitHub repository to download and run the sample project.
Note In addition to the sample project, your system should have .NET Core 1.0
or newer installed.
xx Introduction
Errata, updates, & book support
We’ve made every effort to ensure the accuracy of this book and its companion content.
You can access updates to this book—in the form of a list of submitted errata and their
related corrections—at:
https://aka.ms/ASPCoreAppDev/errata
If you discover an error that is not already listed, please submit it to us at the same page.
If you need additional support, email Microsoft Press Book Support at mspinput@
microsoft.com.
Please note that product support for Microsoft software and hardware is not offered
through the previous addresses. For help with Microsoft software or hardware, go to
http://support.microsoft.com.
http://aka.ms/mspressfree
http://aka.ms/tellpress
We know you’re busy, so we’ve kept it short with just a few questions. Your answers
go directly to the editors at Microsoft Press. (No personal information will be requested.)
Thanks in advance for your input!
xxi
Introduction
Stay in touch
Let’s keep the conversation going! We’re on Twitter: http://twitter.com/MicrosoftPress
xxii Introduction
PAR T I
CHAPTER 2 Influencers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
CHAPTER 5 Builds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
CHAPTER 6 Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Even the most fervent riders had to admit it: the season was at an
end. It hadn’t been the best season in memory but nor had it been
the worst. It had been, in every way, unremarkable. There had been
moments, a power outage in late February had forced the dust-
ing off of an emergency plan which had long been practiced but
never used. There had been reports on the local news station about
children trapped on gondolas for hours but with the balmy weather
nobody had ever truly been in danger. A smattering of free passes
was all that was required to keep the skiers and riders coming.
The spring was a time for the permanent staff to regroup and
the seasonal staff to return to wherever it is that lefties go in the
summer. A rumor among the permanent staff was that at least
half of the seasonal staff were rounded up by immigration as
soon as they stepped off the hill and sent back to Australia. Dani-
1
elle couldn’t imagine why the young seasonal staff would resist
being sent back to Australia. One thing was for sure, it was much
more exciting in Australia than in the sleepy mountain town that
reemerged from hibernation each winter.
It was still too early to plan the next year and Danielle was look-
ing forward to a month or two of down time before the cycle began
anew. She had been the lone developer for Alpine Ski House for
close to a decade and every year was about the same. Most of her
time involved keeping legacy systems running and adjusting what-
ever small things were needed for the next year’s activities. It wasn’t
the most exciting job in the world but over the winter months it was
expected that everybody would sneak off for a couple of hours ski-
ing on nice days and that was a perk she thoroughly enjoyed.
Opening the door to the low-rise that Alpine Ski House called
home she was surprised to see that things were buzzing. People
she wouldn’t have expected to see in the office for a couple of
hours were scattered about in huddles throughout the open
plan office. Confused, Danielle dumped her bag and grabbed a
coffee before looking for a huddle to join. The rest of the IT staff
seemed to be orbiting Tim, the portly IT manager and her boss.
Danielle headed over to join.
“Where have you been?” asked Arjun, “We just bought out
Thunder Valley and Mount Ballyhoo. They’re merging operations
and we’re all going to lose our jobs!”
The two other ski areas were a few miles down the road.
Thunder Valley was a small operation with only three lifts but a
loyal following of ski bums. It was a favorite for the locals who
wanted a break from the crowds of tourists in the winter months.
It couldn’t be more different from Mount Ballyhoo if it had been
the output of Babbage’s difference machine. Mount Ballyhoo
was a huge ski hill spanning three mountains with countless lifts
and enough on hill accommodation to house everybody in town
twice over. Every weekend they had bands playing on the hill,
2
and it was not uncommon to see famous people like Scott Gu
and John Skeet there rubbing shoulders with the commoners.
Danielle had to sit down. She was years still from retirement
and didn’t want to find another job. How many jobs would there
be for programmers in a seasonal town like this? “This is silly,” she
told herself, “there is no use planning a move back to the big city
based on this sort of uncertainty. Things will shake out in the next
couple of weeks.”
3
looked like they had just stepped of a golf course. Somehow they
were already tanned and relaxed looking.
4
CHAPTER 3
It was a surprise when Adrian popped over to Danielle’s cubicle. Maybe more surprising was the
furrowed brow he was sporting. “Got a minute?” he asked in a hushed tone, and then walked
away without waiting for an answer. She nodded a confused yes, mostly to herself, and slowly got
up to follow him to a side room. She scanned around the development pit, but didn’t see anyone
watching, much less interested, and couldn’t really get a read on why he was assuming the role of
secret agent in this software docu-drama.
He closed the door behind her as she stepped into the room. “Look, I’m a CSS guy. I’m not
going to sugar coat it. I know my way around jQuery well enough to troubleshoot, but I’m no
programmer.” He looked tense and Danielle wondered what he’d been thinking. “Everyone else
seems to be buying into this shift over to Core or whatever it’s called...but I’m...I mean, come on, I
run Linux on my laptop and I don’t even use Office.” The room quickly drew silent.
“Are you still nervous, Adrian? Marc had mentioned that you were worried about the cuts.”
Danielle was nervous too, truth be told. She had lost some good friends herself when the merge
went through, but she wasn’t sure that was what he needed to hear at the moment.
“Well yeah, I guess,” he replied. “But my knowledge of MVC is that it stands for Model-View-
Controller, and I haven’t taken a look any deeper than that. And you guys keep referring to it as
a framework. If it’s a framework, but you have to make your own models, views, and controllers,
then the MVC part seems more than a little misleading, don’t you think?”
He had a point. “Well, yeah, that’s actually pretty true,” said Danielle.
“I’m coming from a different view here; I just want to wrap my head around it. I want to learn,
but I’m not sure I know where to start, either.” Adrian pounded back the rest of his coffee like it
was about to expire. “I know they said we’re safe if we’re still here, but I don’t want to get caught
with my feet standing still if they think there’s still room to shrink the team.”
“Okay, look,” said Danielle, “I’ve got a bit of time right now, let’s run through the basics and
we’ll learn together. We’re all going to be fine.”
27
The M, the V, and the C of it
Let’s face it, the MVC Framework is a pretty boring name. The acronym used in the title is from the
well-known Model-View-Controller pattern, and it helps to organize a project. If you’re familiar
with it, the name literally spells out some of the original intent to separate concerns, and moves
away from the other common pattern at the time known as Page-Controller. The name can also
be misleading. The framework is much more than just models, views and controllers. ASP.NET
Core MVC has a growing set of tooling and libraries available to that help developers create great
applications, worthy of the modern web world.
Let’s do a quick recap on the aspects you should already understand, and then move into some
more interesting aspects of the framework, officially known as ASP.NET Core MVC.
Let’s consider this example from Alpine Ski House’s possible database design that deals with
user account summaries, as shown in Figure 3-1. When you want to indicate to the user that she
has a current season pass, you don’t want to return the list of season passes to the view and iterate
over the collection to see if one exists that has not yet expired.
FIGURE 3-1 A screen shot showing a sampling of tables that might be used to model purchasing season passes
The differentiation between what you craft for models on the front end, versus what you store in
the database, is important not just for separating the concerns of the view and the business logic that
supports it, but also for helping to prevent certain types of security issues. On the “write” side of things,
when a view uses a database entity, the application becomes more likely to fall victim to overbinding
bugs or attacks. Overbinding occurs when fields that weren’t anticipated from an incoming request are
present in form or querystring parameters. The model binder sees the properties, doesn’t know that
you hadn’t intended for them to be there, and kindly fills in your data for you. As an example, consider
the class representing some kind of a digital asset in Listing 3-2.
This type of model can be used to display a list of resources made available to a user, and doing so is
quite harmless. But, if you use the same object to receive edits for the record, a malicious user can ex-
ploit the fact that AssetOwnerId is a property and use that to take ownership of the asset. In fact, this
is how Egor Homakov gained administrative privileges for the Ruby on Rails (RoR) repository on GitHub
in 20121 (The technique in RoR is exploited through improperly checked models that make use of the
1 GitHub reinstates Russian who hacked site to expose flaw, John Leyden, March 5, 2012, http://www.theregister.co.uk.
Most of the examples you find for view models will likely use an entity directly as the model type for the
view; however, the approach does not facilitate other aspects of software development, such as testing,
nor does it help with separating concerns in your controllers. Using the entity directly in a view means that
you’ve achieved an undesirable level of coupling from the database all the way up to the view.
A model should be everything you need to render your page after you’ve taken care of business
logic and often has a flattened view of a denormalized record from several tables in the database.
For these reasons, and considering the intent of the object you’re building up when you create a
“model,” you should likely think of it as the “view model” due to its close relationship and responsi-
bility to the view.
Views
Here, the view in question happens to start with V and is indeed the view we’re talking about in our
new favorite acronym. Views in ASP.NET Core MVC are the files used to interleave parts of the model
with the HTML needed in order to present the user with the intended user interface. If you create a new
project from the default application template you will find all the views in the Views folder, or you can
search Solution Explorer with the term “.cshtml,” which is the extension used for Razor views.
Using the Razor view engine and syntax you’ve seen through the last few iterations of the MVC
Framework, you can switch effortlessly between the syntax used to control flow or access our model or
services, and the markup required to generate HTML.
In Listing 3-3 we have created an unordered list with values from the model’s IncludedFamily-
Members collection. Razor lets you use C# inline with the HTML and is pretty smart about how it inter-
prets what you throw at it. A simple @ character is enough for the parser to know you’re flipping into
C#, and since angle brackets can’t be used at the start of a valid C# statement, it can tell when you’ve
switched back to HTML. We’ll be covering Razor in greater detail in Chapter 11, “Razor Views.”
<ul>
@foreach (var familyMember in Model.IncludedFamilyMembers)
{
<li>@familyMember</li>
}
</ul>
Partials are not typically rendered on their own, but are used in composition of other views in your
project. The first place you see this in any MVC application is likely to be in the _Layout.cshtml, where
the view relies on partials to render the login status. Other common uses include using a partial view to
render items in toolbars, shopping cart summaries like those you see at the top of an ecommerce site,
or side bars with relevant data for the current page.
Child actions had to be rendered synchronously in previous versions of the MVC Framework, but the
same ideas that made partials possible can now be used to construct view components and invoked
asynchronously. We’ll talk about View Components more in Chapter 18, “Reusable Components,” which
is important in certain scenarios to keep performance in check on the site. Complex generated views
and partials that interact with services are examples of this, which we’ll talk about later in this chapter.
Before users can get the output of a view, and in order for you to load any kind of model into the
view engine, we must talk a little bit about Controllers in your project.
The default convention assumes that you are putting your controllers in a folder called “Controllers”
in the root of the project. This is no longer required because Core MVC actually does an assembly scan
using the naming and inheritance conventions, but it’s still a recommended practice to organize your
controllers in a recognized way. This helps other developers, including the future version of yourself, to
easily manage and maintain the code base down the road.
As software developers, we use controllers as a container for related sets of handlers for incoming
requests. These handlers are called actions and are implemented as methods in our controller class.
Each method, or action, can accept zero or more parameters that are automatically filled in by the
model binding step in the execution pipeline if they are presented by the incoming request.
As the authors of these “traffic cops,” our goal is to code our controllers using some well-accepted
practices. The primary responsibility of an action is to process a request, validating the incoming pa-
rameters and creating an appropriate response.
From time to time, this also requires creating or requesting an instance of a model class, or produc-
ing an appropriate HTTP status code based response. You should try to avoid having any business logic
FIGURE 3-2 An illustration showing how controllers are responsible for invoking business logic that helps to gener-
ate an appropriate HTTP response
Keeping these services external might seem to make things more complex, or raise questions like,
“Who will create these services for me?” This is a great question and one that we’ll answer in the “De-
pendency Injection” section later in this chapter.
Middleware
Here is the secret about middleware in ASP.NET Core MVC: it’s pretty much all middleware. All of it!
During application start-up you have the opportunity to load your configuration, configure your ser-
vices, and then configure the request pipeline, which is where the concept of middleware is called into
play. You can see this in the Configure method of the Startup class in the default project template.
Often, the description of middleware and the interpretation by the reader overcomplicates a fairly
simple premise. The purpose of middleware is to allow an application to say, “Have each request
processed by the following components in the order that I specify.” Middleware is a simplification over
There are several pieces of middleware that ship publically to handle most scenarios that you need
to cover during the execution of your application, both in lower level environments such as staging and
QA, as well as in production:
■■ Diagnostics: Provides exception handling and runtime helpers like database error pages and
technical details to developers.
■■ Static files: Allows a short-circuit of the request pipeline to return a file from disk.
■■ Identity and Authentication: Allows applications to protect end points and assets of an
application.
■■ Routing: Resolves which controller and action should be executed based on the incoming path
and parameters.
■■ CORS: Handles injecting the correct headers for cross-origin resource sharing.
■■ MVC itself: Usually at the end of the configured middleware pipeline as it consumes requests.
Each middleware component has the option to execute code before and after the next component
in the chain, or to short-circuit the execution and return a response. The name middleware likely comes
from the idea that you can execute a piece of software in the middle of something else, as shown in
Figure 3.3. In this instance, you see a series of different requests that are handled by the various mid-
dleware components in the default project template. In some cases, the request is handled by the static
files middleware, returning an asset in wwwroot. At other times, the request is allowed to pass all the
way through to the MVC execution pipeline where your controller is created and you can return a view.
FIGURE 3-3 An illustration showing examples of different request types as handled by middleware
Dependency Injection
There are many written volumes covering dependency injection, but we’ll recap the basics here for
completeness.
Generally speaking, it’s likely going to be a good idea for your code to be obvious about the depen-
dencies that it takes on. In C# you tend to do this by putting the components and services you need in
your constructor, such that any creator of the class has to provide your dependencies for you.
Let’s consider the constructor of the HomeController class in Listing 3-3. The class requires that
any time it is being created an instance of an ILogger implementation would be provided for it.
HomeController doesn’t need to know how to configure or create an ILogger, it doesn’t need to
know where to log to, or how it is to be done. But from any point after instantiation, HomeController
is now able to add valuable information to your log files as required. This one simple parameter on
the constructor explicitly defines your requirements and is referred to as the Explicit Dependencies
Principle.
For this controller to be created by the pipeline, you need to have something in the runtime aware
of how to resolve the ILogger requirement. You configure these services and components in a con-
tainer, and then these types of dependencies are injected for you into the constructors at runtime. And
voila, dependency injection! Being a broader topic, and also by virtue of ASP.NET Core MVC introduc-
ing some new ideas for Dependency I njection (DI), we’re going to take a deeper look at the idea of
Other Gems
ASP.NET Core MVC contains some great improvements over previous versions and we are going to
explore them throughout the book.
■■ Configuration and Logging: Long considered afterthoughts in the .NET space, these critical
application aspects have been revamped, simplified, and made into first-class citizens. Read
more about these in Chapter 12, “Configuration and Logging.”
■■ Tag Helpers: Along with a few other aspects of simplifying front end development, in Chapter
18, “Reusable Components,” we’ll examine Tag Helpers and how they more closely resemble the
HTML we’re trying to return to the client.
■■ Identity: A user is more than just a name and a password. In Chapter 13, “Identity, Security &
Rights,” we’ll explore the new features, uses, and components around security and rights man-
agement in ASP.NET Core MVC.
Summary
Each iteration of the MVC Framework has helped shape part of what it’s become today. Some lessons
learned along the way have helped to bring better assets to developers and the models, views, and
controllers we have at the heart of our applications today take up only a small part of our development
efforts.
Before they knew it, the morning had escaped them and Danielle had all but plastered the white-
board with dry erase marker. Adrian flopped back in his chair and said, “Geez, Danielle. Someone
should write a book on this.”
Symbols AJAX 8
Alpine Ski House
37 Signals 18 build 51–56
201 status code 14 AMD modules 241
.aspx extension 8 Angular 23–24
@ character 152 anti-corruption layer 43
@inject directive 346 Any method 138
_Layout.cshtml 31 Apache 2.0 license 15
.NET Base Class Library 22 Apache Mesos 116
.NET Core 23–24 API keys
@type/chartjs package 258 developer-level 194
@types/lodash 258 ApplicationDbContext class 130–133
Application Lifecycle Management group 65
ApplicationModel 327
A applications
Access-Control-Allow-Origin headers 218 configuration of 169–177
access keys 85 deployment 57–74, 106
access rights 195 hosting 68
access tokens 194, 205 in containers 108–118
AccountController class 211 internationalization of 341–352
account lockouts 208 isolating 106–107
action methods 136–140 isomorphic 338–339
ActionResult 20 MVC 10–13
ActionResults 11–12 packaging 67–68
Active Directory (AD) 197 portable mode 66
ActiveRecord 21 publishing 64–66
Active Scripting 6–7 running inside of Linux container 110–114
Active Server Pages 18 self-contained mode 67
Active Server Pages (ASP) 6–7 single page 10, 338
adapter pattern 43 web. See web applications
AddConsole extension method 182 ApplicationUser class 130–131, 132
AddDbContext method 226 ApplicationUserContext class 132–133
Add* extension method 225 Apply method 327
AddMvc() 212 App Services 70–73
AddPolicy() 218 appSettings.Development.json file 100
addTagHelper directive 300 appsettings.json file 201
admin view 42 app.UseIdentity() 206
387
AppVeyor
388
command line tools
389
commands
390
domain class
391
Don’t Repeat Yourself (DRY)
G I
Gartner’s Magic Quadrant Reports 69 IConfigurationBuilder 175
GET action 11 IConfigurationProvider 174
GET action method 137 IConfigurationSource 174
GET requests 41, 60, 283 IControllerModelConvention 326
GitHub 15, 24, 261 IDataReader 120
VSTS and 54 IDbCommand 120
global filters 210 IDbConnection 120
globalization, of applications 342–343 IDbTransaction 120
glob patterns 297 identity 33, 35
Gmail 10 ASP.NET Core 202–205
Google IdentityRoles 205
containers 116–118 IdentityRoleUserClaims 205
grunt 255 IdentityUserClaim 205
unit testing and 323 IdentityUser class 130–131, 203
Grunt 22, 237–238 IdentityUserLogin 205
Gruntfile.js 238 IdentityUserTokens 205
grunt-ts library 238 IgnoreBody 160
gulp 239–240, 255 IIS. See Internet Information Server (IIS)
Gulp 22 image files 234
unit testing and 323 ImageProcessing library 89
gulp-karma plugin 323 images
optimization of 240
storing in blob containers 86–87
H Index action method 136–137, 138, 140
hashing passwords 204–205 Index method 20
headers information
Content-Security Policy 232 protection of sensitive 85
heat mapping 365 information logs 180
helper templates 12–13 infrastructure as a service (IaaS) 69
Homakov, Egor 29 inheritance 271–272
hosted services 69 INotificationHandler<PurchaseCompleted> interface
hosting 145
elastic 69 INotification interface 144
external 69 input tag helpers 296
internal 68 installation
hosting configuration options 59 packages
HTML 148, 149, 153, 154 with NuGet 252–254
JavaScript and 232 integration tests 50, 324
HTML content IntelliSense
of tag helpers 301 for custom tag helpers 300
HTTP protocol 283 IntelliTest 359
HTTPRrequest object 18 internal threats 194–195
Hub 114 internal users 197
Hyper-V containers 115 internationalization 341–352
HyperV hypervisor 110, 114 localizable text 343–348
setting current culture 348–351
393
Internet Explorer
J
Jakarta Struts 18 L
Jasmine 320–321
labels 116
Jasmine JavaScript unit framework 255
lambda syntax 244
Java 245
landing pages 282
JavaScript , 231–250, 221–230
layouts 13
Angular 23–24
foundations of 159–161
build tools 235–243
working with 158–161
Bundler & Minifie 236–237 legacy code 358
choosing 243 legacy support 18
Grunt 237–238 LESS 269
gulp 239–240 let variable scoping operator 245
WebPack 240–243 libraries 251–252
code writing principles in 232–233 base class 102
external script files 233 client side 260
files 234 definition files and 246–247
frameworks for 249–250 portable class 102
isomorphic applications and 338–339 shared 108
mixing with HTML 232 link tag helper 297–299
module formats 241 Linux 93–94
module loading 247–248 Alpine Ski House on 98–101
need for 233 code editors 98
organization 233–234 SQL Server and 100
popularity of 23 Ubuntu 94–98
React 23–24 Linux containers 110–114
security vulnerabilities 232–233 load testing 324
Single Page Application 234–235 localization middleware 348–349
testing 233, 320–323 localization, of applications 341–352
TypeScript and 243–247 logging 35, 92, 177–188, 365
variable scoping in 245 as a service 186–188
Jenkins 65, 71 as development strategy 179–180
jQuery 249, 298 exception handling 178
394
Ninject
395
Node.js
O PayWave 39
PCLs. See portable class libraries (PCLs)
object oriented programming 355 performance
Object Relational Mapper (ORM) 120 isolation and 106–107
Entity Framework (EF) Core 120–146 performance testing 50–51
micro-ORMs 120 Perl 6
System.Data 120 PhantomJS 323
Octopus Deploy 67 PHP 18
OmniSharp 98 pipelines
OneDrive 70 branching 332–333
OnModelCreating method 142 configuration 329–330
OpenID Connect 201 Pipes and Filters architecture 328
open source 24 plain old CLR object (POCO) 12
Open Web Interface for .NET (OWIN) 24–25, 58 Plain Old CLR Objects (POCOs) 120
Open Web Interface for .NET (OWIN) standard 13 platform as a service (PaaS) 69
operating systems 93, 107 Platform as a Service (PaaS) 117
options delegates 225 Platform-as-a-Service (PaaS) 80–83, 88–89
options pattern 176–177 platform services 80–82
orchestration system building applications using 83–89
containers 109 pods 116
Origin headers 218 policies
ORM. See Object Relational Mapping applying globally 212–213
outbound traffic 92 custom authorization 214–215
396
relationships
defining for selected use 213–214 Radio Frequency Identification (RFID) chips 39–40
for authorization 212–215 Rails. See Ruby on Rails
limitations of 214–215 Razor 11–12, 18
portable class libraries 102 syntax 152, 154–155
portable class libraries (PCLs) 66–67 Razor views 30, 147–168
portable mode 66 advanced functionality 162–166
POST action 11 alternative view engines 167
POST action method 137, 140 avoiding duplication in 167
POST method 138 C# features 155–157
PowerQuest Drive Image 106 code 153–154
pre-processors, CSS 269 compilation 151
principles of least privilege 194–195 defining model 156–157
production environments 106 errors in 150
production servers essentials of 149–155
update scripts for 129–130 including sections in 160–161
Program.cs 58 injecting services into 162
project.json file 47, 252 layouts 158–161
Project Parsley localization of 346
admin view 42 markup 154
API 41–42, 43 parser control cheat sheet for 154–155
ApplicationDbContext 130–133 partial views 161, 305–306
application integration 42–43 role of 149
customer view 39–41 style sheets and 268
deployment 58–74 tag helpers 296
domain for 43 Tag Helpers 163–166
Entity Framework (EF) Core and 119–146, 120–146, view components and 302
147–168 view data 156–157
SkiCardContext class 133–140 web development and 148–149
source code 38 writing expressions 152
projects React 23–24, 249–250
adding services to 225–227 readme files 374
customer view 39–41 records
keeping code in multiple 374–375 change tracking 124–125
scoping 37–44 querying for multiple 123
structure of 374–382 querying for single 122
proxy servers 59, 283, 284 saving 123
PSake 47 recycleOnFileChange setting 62
publishing 64–66 redirects 11
publish-subscribe messaging pattern 144 Redis 287
PurchaseCompleted class 145 refactoring 353–365
data driven changes and 365
defined 354–355
Q microservices 355
time for 357–358
QueueTriggerAttribute 89
with safety net 358–365
referential integrity 134–135
R RefluxJS 249–250
registers 282
R# 370 relationships
Rack 25 across context boundaries 134–135
397
Remove Additional Files At Destination
S servers
build 48, 49, 51
SASS. See Syntactically Awesome Style Sheets proxy 283, 284
SASS script functions 273–274 source control 49, 51
Sassy CSS (SCSS) 268–275 Server Side Includes 6
basics of 269–273 server side programming 231, 235–236
directives 274 Service Locator pattern 224
imports and partials 270 services 117
398
Taglet
399
tags
400
web servers
401
WebSockets
load on 282
Nginx 62–63
reverse proxy and 59–61
WebSockets 22
Where method 123
Wikipedia 232
wildcard patterns 297
windows authentication tokens 61
Windows Communication Foundation (WCF) 13,
14–15
Windows containers 114–116
Windows Nano 107
containers 115
Windows Server Containers 115
Windows Server Core
containers 115
WinForms 8
WS-BPEL 13
WS-Security 13
wwwroot 33
wwwroot directory 233–234
X
XSS. See cross-site scripting attacks
xUnit 308–310, 316
Y
Yarn 258–260
yarn.lock file 259
402