Skip to content

Commit

Permalink
Porting eBook upgrade to .NET 6 (#27555)
Browse files Browse the repository at this point in the history
* Update Porting eBook Cover Image (#27325)

* update front matter, preview notices, and referenes to .NET 5

* update cover

* Update startup details

* update with new features

* updating startup references

* Blazor ebook frontmatter (#27086)

* Update cs5001.md (#27080)

* Update cs5001.md

* Update docs/csharp/misc/cs5001.md

Co-authored-by: David Pine <david.pine@microsoft.com>

* Remove redundant nullable operator (#27023)

* Remove redundant nullable operator

Remove redundant nullable operator for reference type. String is a reference type and always nullable,

* Make undesired error more clear

Co-authored-by: Bill Wagner <wiwagn@microsoft.com>

Co-authored-by: Bill Wagner <wiwagn@microsoft.com>

* update version

* fix typo

Co-authored-by: Machiel visser <16868513+machielvisser@users.noreply.github.com>
Co-authored-by: David Pine <david.pine@microsoft.com>
Co-authored-by: Artur Khutak <rd.artyrchik@gmail.com>
Co-authored-by: Bill Wagner <wiwagn@microsoft.com>

* Blazor Hot Reload (#27166)

* Blazor Hot Reload section

* fixing hot to Hot

* Apply suggestions from code review

Co-authored-by: David Pine <david.pine@microsoft.com>

Co-authored-by: David Pine <david.pine@microsoft.com>

* update ms.date and another startup reference

* Update ms.date

* update references to startup files and older versions of .NET

* fixing links

* Apply suggestions from code review

Co-authored-by: David Pine <david.pine@microsoft.com>

* Update docs/architecture/blazor-for-web-forms-developers/project-structure.md

Co-authored-by: David Pine <david.pine@microsoft.com>

* Update docs/architecture/porting-existing-aspnet-apps/authentication-differences.md

Co-authored-by: Steve Smith <steve@kentsmiths.com>
Co-authored-by: Machiel visser <16868513+machielvisser@users.noreply.github.com>
Co-authored-by: Artur Khutak <rd.artyrchik@gmail.com>
Co-authored-by: Bill Wagner <wiwagn@microsoft.com>
  • Loading branch information
5 people authored Dec 14, 2021
1 parent a6cf9c7 commit 57afec1
Show file tree
Hide file tree
Showing 44 changed files with 184 additions and 123 deletions.
42 changes: 11 additions & 31 deletions docs/architecture/blazor-for-web-forms-developers/app-startup.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,72 +22,52 @@ With ASP.NET Core and Blazor, these methods are either simplified and consolidat

## Blazor Server Startup Structure

Blazor Server applications reside on top of an ASP.NET Core 3.0 or later version. ASP.NET Core web applications are configured using a builder defined in *Program.cs* and optionally a `Startup` class defined in *Startup.cs*. Starting in .NET 6, the default choice is to set up the app in a single *Program.cs* file (but using a `Startup` class remains supported).

In *Program.cs*, you configure the app's required services by adding them to the built-in services container and then set up the app's HTTP request pipeline.
Blazor Server applications reside on top of an ASP.NET Core 3.0 or later version. ASP.NET Core web applications are configured in *Program.cs*, or through a pair of methods in the `Startup.cs` class. A sample *Program.cs* file is shown below:

```csharp
using BlazorApp3.Areas.Identity;
using BlazorApp3.Data;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using BlazorApp1.Data;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
builder.Services.AddSingleton<WeatherForecastService>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

```

The various `services.Add*` methods add services that enable features such as authentication, razor pages, MVC controller routing, SignalR, and Blazor Server interactions among many others. This method was not needed in web forms, as the parsing and handling of the ASPX, ASCX, ASHX, and ASMX files were defined by referencing ASP.NET in the web.config configuration file. More information about dependency injection in ASP.NET Core is available in the [online documentation](/aspnet/core/fundamentals/dependency-injection).
The app's required services are added to the `WebApplicationBuilder` instance's `Services` collection. This is how the various ASP.NET Core framework services are configured with the framework's built-in dependency injection container. The various `builder.Services.Add*` methods add services that enable features such as authentication, razor pages, MVC controller routing, SignalR, and Blazor Server interactions among many others. This method was not needed in web forms, as the parsing and handling of the ASPX, ASCX, ASHX, and ASMX files were defined by referencing ASP.NET in the web.config configuration file. More information about dependency injection in ASP.NET Core is available in the [online documentation](/aspnet/core/fundamentals/dependency-injection).

The `app.Use*` methods define the HTTP pipeline for ASP.NET Core apps. With these calls, we declare from top to bottom the [Middleware](middleware.md) that will handle every request sent to our application. Most of these features in the default configuration were scattered across the web forms configuration files and are now in one place for ease of reference.
After the `app` has been built by the `builder`, the rest of the calls on `app` configure its HTTP pipeline. With these calls, we declare from top to bottom the [Middleware](middleware.md) that will handle every request sent to our application. Most of these features in the default configuration were scattered across the web forms configuration files and are now in one place for ease of reference.

No longer is the configuration of the custom error page placed in a `web.config` file, but now is configured to always be shown if the application environment is not labeled `Development`. Additionally, ASP.NET Core applications are now configured to serve secure pages with TLS by default with the `UseHttpsRedirection` method call.

Next, an unexpected configuration method is listed to `UseStaticFiles`. In ASP.NET Core, support for requests for static files (like JavaScript, CSS, and image files) must be explicitly enabled, and only files in the app's *wwwroot* folder are publicly addressable by default.
Next, an unexpected configuration method call is made to `UseStaticFiles`. In ASP.NET Core, support for requests for static files (like JavaScript, CSS, and image files) must be explicitly enabled, and only files in the app's *wwwroot* folder are publicly addressable by default.

The next line is the first that replicates one of the configuration options from web forms: `UseRouting`. This method adds the ASP.NET Core router to the pipeline and it can be either configured here or in the individual files that it can consider routing to. More information about routing configuration can be found in the [Routing section](pages-routing-layouts.md).

The final `app.Map*` statements define the endpoints that ASP.NET Core is listening on. These routes are the web accessible locations that you can access on the web server and receive some content handled by .NET and returned to you. The first entry, `MapBlazorHub` configures a SignalR hub for use in providing the real-time and persistent connection to the server where the state and rendering of Blazor components is handled. The `MapFallbackToPage` method call indicates the web-accessible location of the page that starts the Blazor application and also configures the application to handle deep-linking requests from the client-side. You will see this feature at work if you open a browser and navigate directly to Blazor handled route in your application, such as `/counter` in the default project template. The request gets handled by the *_Host.cshtml* fallback page, which then runs the Blazor router and renders the counter page.
The final `app.Map*` calls in this section define the endpoints that ASP.NET Core is listening on. These routes are the web accessible locations that you can access on the web server and receive some content handled by .NET and returned to you. The first entry, `MapBlazorHub` configures a SignalR hub for use in providing the real-time and persistent connection to the server where the state and rendering of Blazor components is handled. The `MapFallbackToPage` method call indicates the web-accessible location of the page that starts the Blazor application and also configures the application to handle deep-linking requests from the client-side. You will see this feature at work if you open a browser and navigate directly to Blazor handled route in your application, such as `/counter` in the default project template. The request gets handled by the *_Host.cshtml* fallback page, which then runs the Blazor router and renders the counter page.

The very last line starts the application, something that wasn't required in web forms (since it relied on IIS to be running).

## Upgrading the BundleConfig Process

Expand Down
56 changes: 56 additions & 0 deletions docs/architecture/blazor-for-web-forms-developers/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,23 @@ If the namespace for a component isn't in scope, you can specify a component usi
<MyComponentLib.Counter />
```

## Modify page title from components

When building SPA-style apps, it's common for parts of a page to reload without reloading the entire page. Even so, it can be useful to have the title of the page change based on which component is currently loaded. This can be accomplished by including the `<PageTitle>` tag in the component's Razor page:

```razor
@page "/"
<PageTitle>Home</PageTitle>
```

The contents of this element can be dynamic, for instance showing the current count of messages:

```razor
<PageTitle>@MessageCount messages</PageTitle>
```

Note that if several components on a particular page include `<PageTitle>` tags, only the last one will be displayed (since each one will overwrite the previous one).

## Component parameters

In ASP.NET Web Forms, you can flow parameters and data to controls using public properties. These properties can be set in markup using attributes or set directly in code. Blazor components work in a similar fashion, although the component properties must also be marked with the `[Parameter]` attribute to be considered component parameters.
Expand Down Expand Up @@ -189,6 +206,45 @@ To specify a component parameter in Blazor, use an attribute as you would in ASP
<Counter IncrementAmount="10" />
```

### Query string parameters

Blazor components can also leverage values from the query string of the page they're rendered on as a parameter source. To enable this, add the `[SupplyParameterFromQuery]` attribute to the parameter. For example, the following parameter definition would get its value from the request in the form `?IncBy=2`:

```csharp
[Parameter]
[SupplyParameterFromQuery(Name = "IncBy")]
public int IncrementAmount { get; set; } = 1;
```

If you don't supply a custom `Name` in the `[SupplyParameterFromQuery]` attribute, by default it will match the property name (`IncrementAmount` in this case).

## Components and error boundaries

By default, Blazor apps will detect unhandled exceptions and show an error message at the bottom of the page with no additional detail. To constrain the parts of the app that are impacted by an unhandled error, for instance to limit the impact to a single component, the `<ErrorBoundary>` tag can be wrapped around component declarations.

For example, to protect against possible exceptions thrown from the `Counter` component, declare it within an `<ErrorBoundary>` and optionally specify a message to display if there is an exception:

```razor
<ErrorBoundary>
<ChildContent>
<Counter />
</ChildContent>
<ErrorContent>
Oops! The counter isn't working right now; please try again later.
</ErrorContent>
</ErrorBoundary>
```

If you don't need to specify custom error content, you can just wrap the component directly:

```razor
<ErrorBoundary>
<Counter />
</ErrorBoundary>
```

A default message stating "An error as occurred." will be displayed if an unhandled exception occurs in the wrapped component.

## Event handlers

Both ASP.NET Web Forms and Blazor provide an event-based programming model for handling UI events. Examples of such events include button clicks and text input. In ASP.NET Web Forms, you use HTML server controls to handle UI events exposed by the DOM, or you can handle events exposed by web server controls. The events are surfaced on the server through form post-back requests. Consider the following Web Forms button click example:
Expand Down
4 changes: 2 additions & 2 deletions docs/architecture/blazor-for-web-forms-developers/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: Learn how to configure Blazor apps without using ConfigurationManag
author: csharpfritz
ms.author: jefritz
no-loc: [Blazor]
ms.date: 11/20/2020
ms.date: 12/2/2021
---
# App configuration

Expand Down Expand Up @@ -170,7 +170,7 @@ public class MyConfigSection
}
```

This class hierarchy can be populated by adding the following line to the `Startup.ConfigureServices` method:
This class hierarchy can be populated by adding the following line to the `Startup.ConfigureServices` method (or appropriate location in *Program.cs* using the `builder.Services` property instead of `services`):

```csharp
services.Configure<MyConfig>(Configuration);
Expand Down
7 changes: 4 additions & 3 deletions docs/architecture/blazor-for-web-forms-developers/data.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public class MyDbContext : DbContext
}
```

The `MyDbContext` class provides the one property that defines the access and translation for the `Product` class. Your application configures this class for interaction with the database using the following entries in the `Startup` class's `ConfigureServices` method:
The `MyDbContext` class provides the one property that defines the access and translation for the `Product` class. Your application configures this class for interaction with the database using the following entries in the `Startup` class's `ConfigureServices` method (or appropriate location in *Program.cs* using the `builder.Services` property instead of `services`):

```csharp
services.AddDbContext<MyDbContext>(options =>
Expand Down Expand Up @@ -96,10 +96,11 @@ More information about [EF Core](/ef/core/) can be found on the Microsoft Docs s

## Interact with web services

When ASP.NET was first released, SOAP services were the preferred way for web servers and clients to exchange data. Much has changed since that time, and the preferred interactions with services have shifted to direct HTTP client interactions. With ASP.NET Core and Blazor, you can register the configuration of your `HttpClient` in the `Startup` class's `ConfigureServices` method. Use that configuration when you need to interact with the HTTP endpoint. Consider the following configuration code:
When ASP.NET was first released, SOAP services were the preferred way for web servers and clients to exchange data. Much has changed since that time, and the preferred interactions with services have shifted to direct HTTP client interactions. With ASP.NET Core and Blazor, you can register the configuration of your `HttpClient` in *Program.cs* or in the `Startup` class's `ConfigureServices` method. Use that configuration when you need to interact with the HTTP endpoint. Consider the following configuration code:

```csharp
services.AddHttpClient("github", client =>
// in Program.cs
builder.Services.AddHttpClient("github", client =>
{
client.BaseAddress = new Uri("http://api.github.com/");
// Github API versioning
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/blazor-for-web-forms-developers/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ One Microsoft Way

Redmond, Washington 98052-6399

Copyright © 2021 by Microsoft Corporation
Copyright &copy; 2021 by Microsoft Corporation

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.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: Learn how to create pages in Blazor, work with client-side routing,
author: danroth27
ms.author: daroth
no-loc: [Blazor]
ms.date: 09/19/2019
ms.date: 12/2/2021
---
# Pages, routing, and layouts

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ The project file for a Blazor WebAssembly app looks slightly more involved (exac

Blazor WebAssembly project targets `Microsoft.NET.Sdk.BlazorWebAssembly` instead of `Microsoft.NET.Sdk.Web` sdk because they run in the browser on a WebAssembly-based .NET runtime. You can't install .NET into a web browser like you can on a server or developer machine. Consequently, the project references the Blazor framework using individual package references.

By comparison, a default ASP.NET Web Forms project includes almost 300 lines of XML in its *.csproj* file, most of which is explicitly listing the various code and content files in the project. Since the release of `.NET 5` both `Blazor Server` and `Blazor WebAssembly` app can easily share one unified runtime.
By comparison, a default ASP.NET Web Forms project includes almost 300 lines of XML in its *.csproj* file, most of which is explicitly listing the various code and content files in the project. Since the release of .NET 5, both Blazor Server and Blazor WebAssembly apps can easily share one unified runtime.

Although they're supported, individual assembly references are less common in .NET projects. Most project dependencies are handled as NuGet package references. You only need to reference top-level package dependencies in .NET projects. Transitive dependencies are included automatically. Instead of using the *packages.config* file commonly found in ASP.NET Web Forms projects to reference packages, package references are added to the project file using the `<PackageReference>` element.

Expand Down Expand Up @@ -332,6 +332,20 @@ You can also access additional configuration options. The configuration dialog l

The "developer inner loop" has been greatly streamlined with Hot Reload. Using Hot Reload, a Blazor developer would typically need to restart and rerun the app after every change, navigating to the appropriate part of the app as required. With Hot Reload, changes can be made to the running app without the need to restart in most cases. Hot Reload even retains the state of pages, so there's no need to have to re-enter form values or otherwise get the app back where you need it.

Both Blazor Server and Blazor WebAssembly apps support Hot Reload in Visual Studio. Hot Reload is a feature that automatically updates changes made to a Blazor app live, in the browser. You can toggle whether Hot Reload is enabled from its icon in the toolbar:

![Visual Studio 2022: Hot Reload menu item and icon.](media/project-structure/hot-reload-1.png)

Selecting the caret beside the icon reveals additional options. You can toggle Hot Reload on or off, restart the application, and toggle whether Hot Reload should occur whenever a file is saved.

![Visual Studio 2022: Hot Reload menu item with expanded options.](media/project-structure/hot-reload-2.png)

You can also access additional configuration options. The configuration dialog lets you specify whether Hot Reload should be enabled when debugging (along with Edit and Continue), when starting without debugging, or when a file is saved.

![Visual Studio 2022: Hot Reload configuration options from the "Tools > Options > Debugging > .NET/C++ Hot Reload" dialog.](media/project-structure/hot-reload-3.png)

The "developer inner loop" has been greatly streamlined with Hot Reload. Using Hot Reload, a Blazor developer would typically need to restart and rerun the app after every change, navigating to the appropriate part of the app as required. With Hot Reload, changes can be made to the running app without the need to restart in most cases. Hot Reload even retains the state of pages, so there's no need to have to re-enter form values or otherwise get the app back where you need it.

>[!div class="step-by-step"]
>[Previous](hosting-models.md)
>[Next](app-startup.md)
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Additional migration resources
description: Where can teams find resources to help as they port their .NET Framework apps to .NET Core?
author: ardalis
ms.date: 11/13/2020
ms.date: 12/10/2021
---

# Additional migration resources
Expand Down
Loading

0 comments on commit 57afec1

Please sign in to comment.