C# 6 and .NET Core 1.0": Modern Cross-Platform Development - Sample Chapter
C# 6 and .NET Core 1.0": Modern Cross-Platform Development - Sample Chapter
$ 49.99 US
31.99 UK
"Community
Experience
Distilled"
C o m m u n i t y
D i s t i l l e d
E x p e r i e n c e
Mark J. Price
Mark J. Price
Since 1993, Mark has passed more than 90 Microsoft programming exams and
specializes in preparing others to pass them too. His students range from professionals
with decades of experience to 16-year-old apprentices with no experience at all.
He successfully guides all of them by combining educational skills with real-world
experience, consulting on and developing systems for enterprises worldwide.
Between 2001 and 2003, Mark was employed full-time to write official courseware
for Microsoft in Redmond, USA. His team wrote the first training courses for C# and
.NET while they were still an early alpha version. While with Microsoft, he delivered
"train-the-trainer" classes to get other MCTs up to speed in C# and .NET.
In 2010, Mark took a postgraduate certificate in education (PGCE). He taught
GCSE and A-level mathematics in two secondary schools in London. Mark holds
a Computer Science BSc (Hons) degree from the University of Bristol, UK.
Preface
There are many C# books, some, more than a thousand pages long, that aim to be
comprehensive references to the C# programming language and the .NET Framework.
This book is differentit is concise and aims to be a fast-paced read that is packed
with hands-on walkthroughs. I wrote this book to be the best step-by-step guide to
modern cross-platform C# and .NET proven practices.
I will point out the cool corners and gotchas of C# so you can impress colleagues and
employers and quickly get productive. Rather than slowing down and boring some
of you by explaining every little thing, I assume that if a term I use is new to you,
then you know how to Google it with a search engine such as DuckDuckGo.
At the end of each chapter, there is a section entitled Practicing and Exploring, which
contains questions to test your knowledge, and usually a hands-on practical exercise,
and you will explore topics in depth on your own with a little nudge in the right
direction from me.
You can download solutions for the exercises from the GitHub repository at
https://github.com/markjprice/cs6dotnetcore. I will provide instructions on
how to do this using Visual Studio 2015 at the end of Chapter 1, Hello C#!, Welcome
.NET Core!.
Preface
Chapter 2, Speaking C#, is about the C# language, the grammar and vocabulary that
you will use every day to write the source code for your applications. In particular,
you will learn how to declare and work with variables of different types.
Chapter 3, Controlling the Flow, Converting Types, and Handling Exceptions, is about
writing code that makes decisions, repeats blocks of statements, converts between
types, and handles errors. You will also learn the best places to look for help.
Chapter 4, Using Common .NET Types, is about how .NET types are related to C#.
You will learn about .NET Framework, .NET Core, and their class library assemblies
of types that allow your applications to connect together existing components to
perform common practical tasks.
Chapter 5, Using Specialized .NET Types, is about .NET types used to diagnose
problems, support multiple languages and cultures, and access features and
applications outside of .NET.
Chapter 6, Building Your Own Types with Object-Oriented Programming, is about all the
different categories of members that a type can have, including fields for storing data
and methods for performing actions. You will use OOP concepts such as aggregation
and encapsulation.
Chapter 7, Implementing Interfaces and Inheriting Classes, is about deriving new types
from existing ones using OOP. You will learn how to implement interfaces, about
base and derived classes, how to override a type member, how to use polymorphism,
and how to cast between classes in an inheritance hierarchy.
Chapter 8, Working with Relational Data Using the Entity Framework, is about reading
and writing to Microsoft SQL Server (and other databases) using classic ADO.NET
and the object-relational mapping technology known as Entity Framework.
Chapter 9, Querying and Manipulating Data with LINQ, is about Language Integrated
Queries (LINQ)language extensions that add the ability to work with sequences
of items, and filter, sort, and project them into different outputs.
Chapter 10, Working with Files, Streams, and Serialization, is about reading and writing
to files and streams, text encoding, and serialization.
Chapter 11, Protecting Your Data and Applications, is about protecting your data using
encryption and hashing, and checking who is running your application and what
they are allowed to do.
Chapter 12, Improving Performance and Scalability with Multitasking, is about allowing
multiple actions to be executed at the same time to improve performance, scalability,
and user productivity.
Preface
Chapter 13, Building Universal Windows Platform Apps Using XAML, is about learning
the basics of XAML, which can be used to define the user interface for a graphical
app for the Universal Windows Platform (UWP). This app can then run on Windows
10, Windows 10 Mobile, Xbox One, and even HoloLens.
Chapter 14, Building Web Applications and Services Using ASP.NET Core, is about
building web applications and services using a modern HTTP architecture on the
server side using Microsoft ASP.NET Core 1.0. You will learn about the models,
views, and controllers that make up MVC and the Web API.
Chapter 15, Taking C# Cross-Platform, is about introducing you to how you can take
C# cross-platform using .NET Core, ASP.NET Core 1.0, Entity Framework Core 1.0,
and Visual Studio Code.
Chapter 16, Building a Quiz, is about designing and building a quiz application that
helps students learn C#, .NET Core, and related topics.
Appendix A, Answers to the Test Your Knowledge Questions, has the answers to the test
questions at the end of each chapter.
Appendix B, Creating a Virtual Machine for Your Development Environment, shows
how to set up a virtual machine in Microsoft Azure for use as a development
environment.
[ 371 ]
ASP.NET XML Web Services was released in 2002 and enables developers
to build SOAP services. It should be avoided for new projects in favor of
WCF or ASP.NET Web API.
ASP.NET MVC was released in 2009 and is designed to cleanly separate the
concerns of web developers between the models that represent the data, the
views that present that data, and the controllers that fetch the model and pass
it to a view. This separation enables improved scalability and unit testing.
ASP.NET Web API was released in 2012 and enables developers to create
HTTP services that are simpler and more scalable than SOAP services.
ASP.NET Core was released in 2016, and combines MVC and Web API
running on the .NET Core. Therefore, it is cross-platform.
Best Practice
Choose ASP.NET Core to develop web applications and services,
because it includes MVC and Web API, which are modern and
cross-platform.
[ 372 ]
Chapter 14
CSS3: This is used for the format and layout applied to elements
To make it easier to work with HTML5, CSS3, and JavaScript, I recommend that
developers install the free Web Essentials extension for Visual Studio.
[ 373 ]
[ 374 ]
Chapter 14
On the right-hand side, you will see details about the request and the response:
The request method is GET. Other methods that HTTP defines include POST,
PUT, DELETE, HEAD, and PATCH.
The response status code is 200 OK. This means the server found the resource
the browser requested. Other status codes include 404 Missing.
[ 375 ]
The request headers include what formats the browser will accept. In this
case, the browser is saying it understands HTML, XHTML, and others.
The browser has told the server that it understands the GZIP and DEFLATE
compressions algorithms.
The browser has told the server which human languages it would prefer:
US English, British English, and then any other dialect of English.
I have been to this site before, so a cookie that was defined by the site is being
sent to the server so that it can track me. Microsoft has named it omniID.
Does that sound ominous to you?
The server has sent back the response, compressed using the GZIP algorithm,
because it knows that the client can decompress that format.
In the New ASP.NET Project dialog box, in the ASP.NET Core 1.0 Templates
section, select the Web Application template.
[ 376 ]
Chapter 14
At the time of writing this book, the final version of ASP.NET Core 1.0
and its Visual Studio project templates have not been released. So, the
screenshots in this book show the old branding, ASP.NET 5!
[ 377 ]
After a few seconds, your Solution Explorer window will look like this:
Run the application by pressing F5. The web application is hosted in the free version
of IIS Express using a random port number for local testing.
Notice that the home page has a black navigation bar with links to an About page
and a Contact page. The home page has a carousel with four rotating items and four
columns of links underneath:
[ 378 ]
Chapter 14
Click on the links to the About page and the Contact page, and notice the URLs that
are used. To get to the About page, the user could enter /Home/About in the browser
address box:
Resize the width of the browser window and notice that the navigation bar becomes
a clickable "hamburger" menu (three horizontal lines):
[ 379 ]
This is an example of responsive web design. The page looks good on both desktop and
mobile devices, by automatically adapting based on the current width of the window:
Models: This (optional) folder contains C# classes that represent all the data
required for a request
Views: This folder contains .cshtml files that combine HTML and C# code
to enable the dynamic generation of an HTML response
project.json: This file contains a list of NuGet packages (such as the Entity
package management
Framework Core) that your project requires and other project configuration
[ 380 ]
Chapter 14
Startup.cs: This file contains the Main entry point for your application and
The following screenshot shows the parts of a typical ASP.NET Core project:
[ 382 ]
Chapter 14
Here's a table of example URLs and how MVC would work out the names. Notice
that if the user does not supply a name, then the defaults Home and Index are
used, as specified when the route was registered. You could change these defaults
if you wanted:
URL
/
Controller
Action
Home
Index
/Muppet
Muppet
Index
/Muppet/Kermit
Muppet
Kermit
/Muppet/Kermit/Green
Muppet
Kermit
/Products
Products
Index
/Products/Detail
Products
Detail
/Products/Detail/3
Products
Detail
ID
Green
To use the parameters to fetch the correct model and pass it to the correct view
To return the results from the view to the client as an HTTP response
[ 383 ]
All action methods execute a method named View and return the results
to the client
[ 384 ]
Chapter 14
If the preceding commands give errors, then add -pre to the end
of each command to install the pre-release version as shown in the
following screenshot.
[ 385 ]
Enter the following command to tell the .NET Version Manager to use the latest
version of .NET Core:
dnvm use 1.0.0-rc1-update1
At the time of writing this book, .NET Core was a release candidate.
By the time you follow these instructions, the final version should be
available, and use the new .NET CLI so the commands dnvm and dnx
will be replaced by the command dotnet.
Enter the following command to generate classes that represent entities for all the
tables in the Northwind database in the Models subfolder:
dnx ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=No
rthwind;Trusted_Connection=True;" EntityFramework.MicrosoftSqlServer
--outputDir Models
In the Solution Explorer window, expand the Models folder. You will see that a class
has been created for each entity, and a class named NorthwindContext has been
created to represent the whole database:
[ 386 ]
Chapter 14
Best Practice
Create a separate class library project for your entity models. This allows
easier sharing between servers and clients. We have not done this for
this example to keep it simple for now.
Since we are setting the database connection string in the ASP.NET Core startup,
it does not need to be done in the NorthwindContext class.
[ 387 ]
Modify the contents of the Index action method to make it look like this:
var model = new HomeIndexViewModel
[ 388 ]
Chapter 14
{
VisitorCount = (new Random()).Next(1, 1001),
Products = db.Products.ToArray()
};
return View(model); // pass model to view
Note that we will simulate a visitor count using the Random class to generate a
number between 1 and 1000.
If you build the project now, you might get "CS0833
An anonymous type cannot have multiple properties with
the same name" errors due to bugs in the scaffolding feature.
To fix the errors, simply delete the duplicate members.
When the View method is executed in a controller action, MVC looks in the Views
folder for a subfolder with the same name as the current controller, that is, Home.
It then looks for a file with the same name as the current action, that is, Index, About,
or Contact.
In the Index.cshtml file, notice the block of code wrapped in @{ }. This will execute
first and can be used to store data that needs to be passed into a shared layout file:
@{
ViewData["Title"] = "Home Page";
}
[ 389 ]
Note the static HTML content in several DIV elements that uses Bootstrap for styling.
Best Practice
Instead of defining your own styles, use a library, such as Bootstrap,
that implements responsive design using standard CSS3 principles.
In the Shared folder, open the _Layout.cshtml file. Notice that the title is being read
from the ViewData dictionary that was set earlier in the Index.cshtml view:
<title>@ViewData["Title"] Ch14_WebApp</title>
Note the rendering of common styles to support Bootstrap and the two sections.
During development, the fully-commented and nicely formatted versions of CSS
files will be used. For staging and production, the minified versions will be used:
<environment names="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.
css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/
bootstrap/3.3.5/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.
css"
asp-fallback-test-class="sr-only" asp-fallback-testproperty="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-appendversion="true" />
</environment>
Note the rendering of hyperlinks to allow users to click between pages using the
navigation bar at the top of every page. The <a> elements use "tag helper" attributes to
specify the controller name and action name that will execute when the link is clicked:
[ 390 ]
Chapter 14
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-controller="Home" asp-action="Index">Home</a></li>
<li><a asp-controller="Home" asp-action="About">About</a></li>
<li><a asp-controller="Home" asp-action="Contact">Contact</
a></li>
</ul>
</div>
Note the rendering of script blocks at the bottom of the page (so that it doesn't slow
down the display of the page):
<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery2.1.4.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/
bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.
js"
asp-fallback-test="window.jQuery && window.jQuery.fn &&
window.jQuery.fn.modal">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>
You can add you own script blocks into an optional defined section named scripts:
@RenderSection("scripts", required: false)
Notice that the column-count property has a purple squiggle under it. When you
hover over it, you will see that only Internet Explorer 10 (or later) and Opera 11.6 (or
later) currently implement this standard. Luckily, Web Essentials can fix this for us.
Click on the column-count property, hover your mouse over the small blue bar, click
on the button to pop open a menu, and then click on Add missing vendor specifics.
You will see that Web Essentials has added two extra statements. They are faded out
to indicate that they will automatically change when you change the value for the
original column-count property:
#newspaper {
-moz-column-count: 3;
-webkit-column-count: 3;
column-count: 3;
}
To learn more about CSS3 and responsive design, read the book
Responsive Web Design with HTML5 and CSS3 - Second Edition by Packt
Publishing at https://www.packtpub.com/web-development/
responsive-web-design-html5-and-css3-second-edition.
Now whenever we enter @Model, Visual Studio's code editor will know the correct
type and will provide IntelliSense.
To declare the type of the model, use @model (with lowercase m).
To read the model, use @Model (with uppercase M).
In Index.cshtml, delete all the <div> elements and replace them with this code:
<div class="row">
<div class="col-md-12">
<h1>Northwind</h1>
[ 392 ]
Chapter 14
<p class="lead">We have had @Model.VisitorCount visitors this
month.</p>
<h2>Products</h2>
<div id="newspaper">
<ul>
@foreach (var item in @Model.Products)
{
<li><a asp-controller="Home" aspaction="ProductDetail" asp-route-id="@item.ProductID">@item.
ProductName costs @item.UnitPrice.Value.ToString("C")</a></li>
}
</ul>
</div>
</div>
</div>
Note how easy it is to mix static HTML elements, such as <ul> and <li>, with
C# code to output the list of product names.
Note the <div> element with the id attribute of newspaper. This will use the
custom style that we defined earlier, so all the content in that element will
display in three columns.
To test the web application, press F5. The results in Microsoft Edge will look
something like this:
[ 393 ]
Inside the method, we check to see whether the id is null, and if so, it returns a
404 status code and message. Otherwise, we can connect to the database and try to
retrieve a product using the id variable. If we find a product, we pass it to a view;
otherwise, we return a different 404 status code and message:
public IActionResult ProductDetail(int? id)
{
if (!id.HasValue)
{
return HttpNotFound("You must pass a product ID in the route,
for example, /Home/ProductDetail/21");
}
var model = db.Products.SingleOrDefault(p => p.ProductID == id);
if (model == null)
{
return HttpNotFound($"A product with the ID of {id} was not
found.");
}
return View(model); // pass model to view
}
[ 394 ]
Chapter 14
[ 395 ]
When the home page appears with the list of products, click one of them, for
example, product 26. The result should look something like this:
Inside the Views folder, right-click on Home and choose Add | New Item.
Choose MVC View Page and name it ProductsThatCostMoreThan.cshtml.
[ 396 ]
Chapter 14
[ 397 ]
In the Views folder, in the Home folder, open Index.cshtml file and add the
following div element at the bottom of the file. This will provide a form for the
user to enter a price. The user can then click on a submit button to call the action
method that shows only products that cost more than the entered price:
<div class="row">
<form asp-action="ProductsThatCostMoreThan" method="get">
<input name="price" placeholder="Enter a product price" />
<input type="submit" />
</form>
</div>
Run the web application by pressing F5. On the home page, scroll down and enter a
price in the form. Then, click on Submit Query:
[ 398 ]
Chapter 14
You will see a table of the products that cost more than the price you entered:
Annotating models
You might have noticed that the column headings in the table used the names of
the properties by default. This means that if the property is multiple words, it won't
have spaces. We can use data annotations to improve this.
In the Models folder, open the Products class. Import the System.ComponentModel.
DataAnnotations namespace.
Add [Display] attributes before each property if you want to have a different label,
for example, Product Name, Unit Price, Units In Stock, and so on:
[Display(Name = "Product Name")]
public string ProductName { get; set; }
Apply the [Display] attribute to the properties of three other classes: Category's
Category Name, Customer's Company Name, and Supplier's Company Name.
Start the web application by pressing F5.
[ 399 ]
Enter a product price and click on Submit Query. Notice that the column headings
now reflect the display attributes and not the actual property names:
To allow the easy creation of services, ASP.NET Core has combined what used to be
two types of controller.
In earlier versions of ASP.NET, you would derive from ApiController to create a
Web API service, and then register API routes in the same route table that MVC uses.
With ASP.NET Core, you use exactly the same Controller base class used with MVC,
except the routes are usually configured on the controller itself, using attributes, rather
than in the route table.
[ 400 ]
Chapter 14
API controllers do not have views. Instead, they use automatic content negotiation
with the client to return XML, JSON, or X-WWW-FORMURLENCODED data formats.
In ShippersController class, add the following code:
[Route("api/[controller]")]
public class ShippersController : Controller
{
private NorthwindContext db;
public ShippersController(NorthwindContext injectedContext)
{
db = injectedContext;
}
// GET: api/shippers
[HttpGet]
public IEnumerable<Shippers> Get()
{
return db.Shippers.ToArray();
}
[ 401 ]
If you have used older versions of ASP.NET Web API, then you
know that in that technology, you could create C# methods that
begin with any HTTP method (GET, POST, PUT, and so on), and the
controller will automatically execute the correct one. In ASP.NET
Core, this doesn't happen anymore, because we are not inheriting
from ApiController. So you must apply an attribute such as
[HttpGet] to explicitly map HTTP methods to C# methods.
If you test with Chrome rather than Microsoft Edge, then you will
get an XML response because Chrome prefers XML over JSON.
Chapter 14
In Solution Explorer window, right-click on the new project and choose Manage
NuGet Packages. In the search box, enter web api client and press Enter. Click
on Install:
Open MainPage.xaml file and add the following XAML inside the existing
Grid element:
<StackPanel Padding="6">
<TextBlock FontSize="24">Shippers</TextBlock>
<GridView ItemsSource="{Binding}">
<GridView.ItemTemplate>
<DataTemplate>
<Border Margin="6" Padding="10" CornerRadius="10"
Background="LightCyan">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="Shipper ID" />
<TextBlock Text="{Binding ShipperID}" Grid.
Column="1" />
[ 403 ]
This defines a GridView control bound to the DataContext class that we will set
when the page loads to the response coming back from the service.
In the Page element, add an event handler for Loading function:
Loading="Page_Loading"
Add the following statements to the Page_Loading method, and add the async
keyword to the method's declaration:
var client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:59468/");
HttpResponseMessage response = await client.GetAsync("api/shippers");
DataContext = await response.Content.ReadAsAsync<Shipper[]>();
Make sure you use the same random port number that
Visual Studio allocated to your ASP.NET Core application.
It is unlikely to be 59468!
On the Build menu, choose Deploy Ch14_WinApp. In the Solution Explorer window,
right-click on the solution and choose Properties.
Select Multiple startup projects. Set the action for Ch14_WebApp to Start without
debugging. Set the action for Ch14_WinApp to Start:
[ 404 ]
Chapter 14
On the Debug menu, choose Start Debugging or press F5. You will see that the UWP
app called the service, deserialized the JSON data, and bound it to the list box:
[ 405 ]
Chapter 14
Summary
In this chapter, you learned how to build an ASP.NET Core MVC web application,
and an ASP.NET Core Web API service that manages data using Entity Framework
Core. You also learned how to consume a REST/HTTP service using HttpClient.
In the next chapter, you will learn how to build an ASP.NET Core web application
that can be hosted cross-platform on Windows, Linux, or Mac OS X.
[ 407 ]
www.PacktPub.com
Stay Connected: