From 550f771061d89e891916e1a47d6724eb4178780d Mon Sep 17 00:00:00 2001 From: David Pine Date: Wed, 22 Apr 2020 13:19:23 -0500 Subject: [PATCH 01/18] Added suggested warning about lack of database support --- docs/csharp/linq/perform-grouped-joins.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/csharp/linq/perform-grouped-joins.md b/docs/csharp/linq/perform-grouped-joins.md index 97d85e5b37101..217d3cc64ca4a 100644 --- a/docs/csharp/linq/perform-grouped-joins.md +++ b/docs/csharp/linq/perform-grouped-joins.md @@ -1,7 +1,7 @@ --- title: Perform grouped joins (LINQ in C#) description: Learn how to perform grouped joins using LINQ in C#. -ms.date: 12/01/2016 +ms.date: 04/22/2020 ms.assetid: 9667daf9-a5fd-4b43-a5c4-a9c2b744000e --- # Perform grouped joins @@ -13,6 +13,9 @@ For example, a class or a relational database table named `Student` might contai > [!NOTE] > Each element of the first collection appears in the result set of a group join regardless of whether correlated elements are found in the second collection. In the case where no correlated elements are found, the sequence of correlated elements for that element is empty. The result selector therefore has access to every element of the first collection. This differs from the result selector in a non-group join, which cannot access elements from the first collection that have no match in the second collection. +> [!WARNING] +> has no direct equivalent in traditional relational database terms. However, this method does implement a superset of inner joins and left outer joins. Both of these operations can be written in terms of a grouped join. For more information, see [Join Operations](../programming-guide/concepts/linq/join-operations.md). + The first example in this article shows you how to perform a group join. The second example shows you how to use a group join to create XML elements. ## Example - Group join From ba6a38f4f13e15247756dcaa1382278da6419529 Mon Sep 17 00:00:00 2001 From: David Pine Date: Wed, 22 Apr 2020 13:23:11 -0500 Subject: [PATCH 02/18] Added EF Core GroupJoin link too. --- docs/csharp/linq/perform-grouped-joins.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/csharp/linq/perform-grouped-joins.md b/docs/csharp/linq/perform-grouped-joins.md index 217d3cc64ca4a..e69792b3d4ee2 100644 --- a/docs/csharp/linq/perform-grouped-joins.md +++ b/docs/csharp/linq/perform-grouped-joins.md @@ -14,7 +14,7 @@ For example, a class or a relational database table named `Student` might contai > Each element of the first collection appears in the result set of a group join regardless of whether correlated elements are found in the second collection. In the case where no correlated elements are found, the sequence of correlated elements for that element is empty. The result selector therefore has access to every element of the first collection. This differs from the result selector in a non-group join, which cannot access elements from the first collection that have no match in the second collection. > [!WARNING] -> has no direct equivalent in traditional relational database terms. However, this method does implement a superset of inner joins and left outer joins. Both of these operations can be written in terms of a grouped join. For more information, see [Join Operations](../programming-guide/concepts/linq/join-operations.md). +> has no direct equivalent in traditional relational database terms. However, this method does implement a superset of inner joins and left outer joins. Both of these operations can be written in terms of a grouped join. For more information, see [Join Operations](../programming-guide/concepts/linq/join-operations.md) and [Entity Framework Core, GroupJoin](https://docs.microsoft.com/ef/core/querying/complex-query-operators#groupjoin). The first example in this article shows you how to perform a group join. The second example shows you how to use a group join to create XML elements. From d09d021c0b29807e7394917e80c34af21d2ebad9 Mon Sep 17 00:00:00 2001 From: David Pine Date: Wed, 22 Apr 2020 14:21:10 -0500 Subject: [PATCH 03/18] Made uninstall wording more explicit and added script variables --- .../versions/remove-runtime-sdk-versions.md | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/docs/core/versions/remove-runtime-sdk-versions.md b/docs/core/versions/remove-runtime-sdk-versions.md index 81e6b8bc90b8e..abeb02155eb71 100644 --- a/docs/core/versions/remove-runtime-sdk-versions.md +++ b/docs/core/versions/remove-runtime-sdk-versions.md @@ -1,7 +1,7 @@ --- title: Remove the .NET Core runtime and SDK description: This article describes how to determine which versions of the .NET Core Runtime and SDK are currently installed, and then, how to remove them on Windows, Mac, and Linux. -ms.date: 12/17/2019 +ms.date: 04/22/2020 author: billwagner ms.author: wiwagn ms.custom: "updateeachrelease" @@ -221,26 +221,30 @@ Note that there's no version attached to `dotnet-host`. If you installed using a tarball, you must remove .NET Core using the manual method. -You remove the SDKs and runtimes separately, by removing the directory that contains that version. For example, to remove the 1.0.1 SDK and runtime, you would use the following bash commands: +On Linux, you must remove the SDKs and runtimes separately, by removing the versioned directories. To be clear, this deletes the SDK and runtime from disk. For example, to remove the 1.0.1 SDK and runtime, you would use the following bash commands: ```bash -sudo rm -rf /usr/share/dotnet/sdk/1.0.1 -sudo rm -rf /usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.1 -sudo rm -rf /usr/share/dotnet/shared/Microsoft.AspNetCore.App/1.0.1 -sudo rm -rf /usr/share/dotnet/host/fxr/1.0.1 +version="1.0.1" +sudo rm -rf /usr/local/share/dotnet/sdk/$version +sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.NETCore.App/$version +sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.AspNetCore.All/$version +sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.AspNetCore.App/$version +sudo rm -rf /usr/local/share/dotnet/host/fxr/$version ``` The parent directories for the SDK and runtime are listed in the output from the `dotnet --list-sdks` and `dotnet --list-runtimes` command, as shown in the earlier table. # [macOS](#tab/macos) -On Mac, you must remove the SDKs and runtimes separately, by removing the directory that contains that version. For example, to remove the 1.0.1 SDK and runtime, you would use the following bash commands: +On Mac, you must remove the SDKs and runtimes separately, by removing the versioned directories. To be clear, this deletes the SDK and runtime from disk. For example, to remove the 1.0.1 SDK and runtime, you would use the following bash commands: ```bash -sudo rm -rf /usr/local/share/dotnet/sdk/1.0.1 -sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.NETCore.App/1.0.1 -sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.AspNetCore.App/1.0.1 -sudo rm -rf /usr/local/share/dotnet/host/fxr/1.0.1 +version="1.0.1" +sudo rm -rf /usr/local/share/dotnet/sdk/$version +sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.NETCore.App/$version +sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.AspNetCore.All/$version +sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.AspNetCore.App/$version +sudo rm -rf /usr/local/share/dotnet/host/fxr/$version ``` The parent directories for the SDK and runtime are listed in the output from the `dotnet --list-sdks` and `dotnet --list-runtimes` command, as shown in the earlier table. From c07e81523f358b3fb3e3e9c1b972a88c0eec4a57 Mon Sep 17 00:00:00 2001 From: Petr Kulikov Date: Thu, 23 Apr 2020 15:46:25 +0200 Subject: [PATCH 04/18] String concatenation: clarify behavior for null (#18014) --- docs/csharp/language-reference/operators/addition-operator.md | 4 ++-- .../language-reference/operators/snippets/AdditionOperator.cs | 2 ++ docs/csharp/language-reference/operators/snippets/Program.cs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/csharp/language-reference/operators/addition-operator.md b/docs/csharp/language-reference/operators/addition-operator.md index 9774edd615841..e36452463a74b 100644 --- a/docs/csharp/language-reference/operators/addition-operator.md +++ b/docs/csharp/language-reference/operators/addition-operator.md @@ -1,6 +1,6 @@ --- title: "+ and += operators - C# reference" -ms.date: 05/24/2019 +ms.date: 04/23/2020 f1_keywords: - "+_CSharpKeyword" - "+=_CSharpKeyword" @@ -22,7 +22,7 @@ For information about the arithmetic `+` operator, see the [Unary plus and minus ## String concatenation -When one or both operands are of type [string](../builtin-types/reference-types.md#the-string-type), the `+` operator concatenates the string representations of its operands: +When one or both operands are of type [string](../builtin-types/reference-types.md#the-string-type), the `+` operator concatenates the string representations of its operands (the string representation of `null` is an empty string): [!code-csharp-interactive[string concatenation](snippets/AdditionOperator.cs#AddStrings)] diff --git a/docs/csharp/language-reference/operators/snippets/AdditionOperator.cs b/docs/csharp/language-reference/operators/snippets/AdditionOperator.cs index 1f0878a56e1af..db376738bef5b 100644 --- a/docs/csharp/language-reference/operators/snippets/AdditionOperator.cs +++ b/docs/csharp/language-reference/operators/snippets/AdditionOperator.cs @@ -26,9 +26,11 @@ private static void StringConcatenation() // Console.WriteLine("Forgot" + "white space"); Console.WriteLine("Probably the oldest constant: " + Math.PI); + Console.WriteLine(null + "Nothing to add."); // Output: // Forgotwhite space // Probably the oldest constant: 3.14159265358979 + // Nothing to add. // // diff --git a/docs/csharp/language-reference/operators/snippets/Program.cs b/docs/csharp/language-reference/operators/snippets/Program.cs index 8b1879f90162d..fc1cb4e9879d1 100644 --- a/docs/csharp/language-reference/operators/snippets/Program.cs +++ b/docs/csharp/language-reference/operators/snippets/Program.cs @@ -103,7 +103,7 @@ static async Task Main(string[] args) UserDefinedConversions.Main(); Console.WriteLine(); - Console.WriteLine("========= switch expression example ========="); + Console.WriteLine("========= switch expression example ============"); SwitchExpressions.Examples(); Console.WriteLine(); From b25275a9148c408f85be7320f109f70aa571c36b Mon Sep 17 00:00:00 2001 From: Petr Kulikov Date: Thu, 23 Apr 2020 15:53:08 +0200 Subject: [PATCH 05/18] nameof: clarify behavior for @-identifiers (#18017) --- docs/csharp/language-reference/operators/nameof.md | 6 +++++- .../language-reference/operators/snippets/NameOfOperator.cs | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/csharp/language-reference/operators/nameof.md b/docs/csharp/language-reference/operators/nameof.md index 2fea8e972f63d..9e7a087ebb539 100644 --- a/docs/csharp/language-reference/operators/nameof.md +++ b/docs/csharp/language-reference/operators/nameof.md @@ -1,6 +1,6 @@ --- title: "nameof expression - C# reference" -ms.date: 07/12/2019 +ms.date: 04/23/2020 f1_keywords: - "nameof_CSharpKeyword" - "nameof" @@ -16,6 +16,10 @@ A `nameof` expression produces the name of a variable, type, or member as the st As the preceding example shows, in the case of a type and a namespace, the produced name is usually not [fully qualified](~/_csharplang/spec/basic-concepts.md#fully-qualified-names). +In the case of [verbatim identifiers](../tokens/verbatim.md), the `@` character is not the part of a name, as the following example shows: + +[!code-csharp-interactive[nameof verbatim](snippets/NameOfOperator.cs#Verbatim)] + A `nameof` expression is evaluated at compile time and has no effect at run time. You can use a `nameof` expression to make the argument-checking code more maintainable: diff --git a/docs/csharp/language-reference/operators/snippets/NameOfOperator.cs b/docs/csharp/language-reference/operators/snippets/NameOfOperator.cs index a19459769e94f..6de7758a03960 100644 --- a/docs/csharp/language-reference/operators/snippets/NameOfOperator.cs +++ b/docs/csharp/language-reference/operators/snippets/NameOfOperator.cs @@ -18,6 +18,11 @@ public static void Examples() Console.WriteLine(nameof(numbers.Count)); // output: Count Console.WriteLine(nameof(numbers.Add)); // output: Add // + + // + var @new = 5; + Console.WriteLine(nameof(@new)); // output: new + // } private class Person From 37d3acc4213acbecd6ca468b9625e7ec87ec84e0 Mon Sep 17 00:00:00 2001 From: Maira Wenzel Date: Thu, 23 Apr 2020 07:20:18 -0700 Subject: [PATCH 06/18] Fix broken link (#18030) * Fix broken link * fix broken link --- docs/visual-basic/toc.yml | 2 +- docs/whats-new/2019-10.md | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/visual-basic/toc.yml b/docs/visual-basic/toc.yml index 074e4808a8375..1f5ef8ec4d490 100644 --- a/docs/visual-basic/toc.yml +++ b/docs/visual-basic/toc.yml @@ -1414,6 +1414,6 @@ - name: Language Specification href: reference/language-specification/ - name: Sample Applications - href: https://github.com/dotnet/samples/tree/master/snippets/visualbasic + href: https://github.com/dotnet/docs/tree/master/samples/snippets/visualbasic - name: Walkthroughs href: walkthroughs.md diff --git a/docs/whats-new/2019-10.md b/docs/whats-new/2019-10.md index 57e84dd4e081e..7d0b26646fc11 100644 --- a/docs/whats-new/2019-10.md +++ b/docs/whats-new/2019-10.md @@ -198,7 +198,6 @@ The following people have contributed to .NET docs in October 2019. Thank you! Y - [JackTrapper](https://github.com/JackTrapper) - [jgscherber](https://github.com/jgscherber) - Jacob Scherber - [jiimaho](https://github.com/jiimaho) - Jim Aho -- [JohnGaltt](https://github.com/JohnGaltt) - Oleksandr Zholob - [JosephAmalfitanoSSA](https://github.com/JosephAmalfitanoSSA) - Joseph Amalfitano - [KexyBiscuit](https://github.com/KexyBiscuit) - Kexy Biscuit - [kolletzki](https://github.com/kolletzki) - Lukas Kolletzki From d044adda8a0785d2f34bfe4542aa00eb89634261 Mon Sep 17 00:00:00 2001 From: Jeremy Likness Date: Thu, 23 Apr 2020 07:55:04 -0700 Subject: [PATCH 07/18] Serverless eBook updates (#17926) * Serverless eBook updates * fix trailing lines * Update cover * Update index.md Add edition under book cover and fix PDF link * Update index.md Fix version --- .../serverless/azure-functions.md | 93 +++------------ docs/architecture/serverless/event-grid.md | 4 +- docs/architecture/serverless/index.md | 14 ++- .../media/index/serverless-apps-cover-v3.png | Bin 0 -> 77774 bytes .../serverless-architecture-considerations.md | 6 +- .../serverless-business-scenarios.md | 111 +++++++++++------- 6 files changed, 93 insertions(+), 135 deletions(-) create mode 100644 docs/architecture/serverless/media/index/serverless-apps-cover-v3.png diff --git a/docs/architecture/serverless/azure-functions.md b/docs/architecture/serverless/azure-functions.md index 7590b818f4199..25af51f990d4d 100644 --- a/docs/architecture/serverless/azure-functions.md +++ b/docs/architecture/serverless/azure-functions.md @@ -3,7 +3,7 @@ title: Azure Functions - Serverless apps description: Azure functions provide serverless capabilities across multiple languages (C#, JavaScript, Java) and platforms to provide event-driven instant scale code. author: JEREMYLIKNESS ms.author: jeliknes -ms.date: 06/26/2018 +ms.date: 04/06/2020 --- # Azure Functions @@ -11,36 +11,23 @@ Azure functions provide a serverless compute experience. A function is invoked b ![Azure functions logo](./media/azure-functions-logo.png) -There are two versions of the Azure Functions framework. The legacy version supports the full .NET Framework and the new runtime supports cross-platform .NET Core applications. Additional languages besides C# such as JavaScript, F#, and Java are supported. Functions created in the portal provide a rich scripting syntax. Functions created as standalone projects can be deployed with full platform support and capabilities. +The current runtime version 3.0 supports cross-platform .NET Core 3.1 applications. Additional languages besides C# such as JavaScript, F#, and Java are supported. Functions created in the portal provide a rich scripting syntax. Functions created as standalone projects can be deployed with full platform support and capabilities. For more information, see [Azure Functions documentation](https://docs.microsoft.com/azure/azure-functions). -## Functions v1 vs. v2 - -There are two versions of the Azure Functions runtime: 1.x and 2.x. Version 1.x is generally available (GA). It supports .NET development from the portal or Windows machines and uses the .NET Framework. 1.x supports C#, JavaScript, and F#, with experimental support for Python, PHP, TypeScript, Batch, Bash, and PowerShell. - -[Version 2.x is also generally available now](https://azure.microsoft.com/blog/introducing-azure-functions-2-0/). It leverages .NET Core and supports cross-platform development on Windows, macOS, and Linux machines. 2.x adds first-class support for Java but doesn't yet directly support any of the experimental languages. Version 2.x uses a new binding extensibility model that enables third-party extensions to the platform, independent versioning of bindings, and a more streamlined execution environment. - -> **There is a known issue in 1.x with [binding redirect support](https://github.com/Azure/azure-functions-host/issues/992).** The issue is specific to .NET development. Projects with dependencies on libraries that are a different version from the libraries included in the runtime are impacted. The functions team has committed to making concrete progress on the problem. The team will address binding redirects in 2.x before it goes into general availability. The official team statement with suggested fixes and workarounds is available here: [Assembly resolution in Azure Functions](https://github.com/Azure/azure-functions-host/wiki/Assembly-Resolution-in-Azure-Functions). - -For more information, see [Compare 1.x and 2.x](https://docs.microsoft.com/azure/azure-functions/functions-versions). - ## Programming language support -The following languages are supported either in general availability (GA), preview, or experimental. - -|Language |1.x |2.x | -|--------------|------------|---------| -|**C#** |GA |Preview | -|**JavaScript**|GA |Preview | -|**F#** |GA | | -|**Java** | |Preview | -|**Python** |Experimental| | -|**PHP** |Experimental| | -|**TypeScript**|Experimental| | -|**Batch** |Experimental| | -|**Bash** |Experimental| | -|**PowerShell**|Experimental| | +The following languages are all supported in general availability (GA). + +|Language |Supported runtimes| +|--------------|------------------| +|**C#** |.NET Core 3.1 | +|**JavaScript**|Node 10 & 12 | +|**F#** |.NET Core 3.1 | +|**Java** |Java 8 | +|**Python** |Python 3.6, 3.7, & 3.8| +|**TypeScript**|Node 10 & 12 (via JavaScript)| +|**PowerShell**|PowerShell Core 6| For more information, see [Supported languages](https://docs.microsoft.com/azure/azure-functions/supported-languages). @@ -48,6 +35,8 @@ For more information, see [Supported languages](https://docs.microsoft.com/azure Functions are backed by an *app service plan*. The plan defines the resources used by the functions app. You can assign plans to a region, determine the size and number of virtual machines that will be used, and pick a pricing tier. For a true serverless approach, function apps may use the **consumption** plan. The consumption plan will scale the back end automatically based on load. +Another hosting option for function apps is the [Premium plan](https://docs.microsoft.com/azure/azure-functions/functions-premium-plan). This plan provides an "always on" instance to avoid cold start, supports advanced features like VNet connectivity, and runs on premium hardware. + For more information, see [App service plans](https://docs.microsoft.com/azure/app-service/azure-web-sites-web-hosting-plans-in-depth-overview). ## Create your first function @@ -121,58 +110,6 @@ The example is a simple function that takes the name of the file that was modifi For a full list of triggers and bindings, see [Azure Functions triggers and bindings concepts](https://docs.microsoft.com/azure/azure-functions/functions-triggers-bindings). -## Proxies - -Proxies provide redirect functionality for your application. Proxies expose an endpoint and map that endpoint to another resource. With proxies, you can: - -- Reroute an incoming request to another endpoint. -- Modify the incoming request before it's passed along. -- Modify or provide a response. - -Proxies are used for scenarios such as: - -- Simplifying, shortening, or changing the URL. -- Providing a consistent API prefix to multiple back-end services. -- Mocking a response to an endpoint being developed. -- Providing a static response to a well-known endpoint. -- Keeping an API endpoint consistent while the back end is moved or migrated. - -Proxies are stored as JSON definitions. Here is an example: - -```json -{ - "$schema": "http://json.schemastore.org/proxies", - "proxies": { - "Domain Redirect": { - "matchCondition": { - "route": "/{shortUrl}" - }, - "backendUri": "http://%WEBSITE_HOSTNAME%/api/UrlRedirect/{shortUrl}" - }, - "Root": { - "matchCondition": { - "route": "/" - }, - "responseOverrides": { - "response.statusCode": "301", - "response.statusReason": "Moved Permanently", - "response.headers.location": "https://docs.microsoft.com/" - } - } - } -} -``` - -The `Domain Redirect` proxy takes a shortened route and maps it to the longer function resource. The transformation looks like: - -`https://--shorturl--/123` -> `https://--longurl--.azurewebsites.net/api/UrlRedirect/123` - -The `Root` proxy takes anything sent to the root URL (`https://--shorturl--/`) and redirects it to the documentation site. - -An example of using proxies is shown in the video [Azure: Bring your app to the cloud with serverless Azure Functions](https://channel9.msdn.com/events/Connect/2017/E102). In real time, an ASP.NET Core application running on local SQL Server is migrated to the Azure Cloud. Proxies are used to help refactor a traditional Web API project to use functions. - -For more information about Proxies, see [Work with Azure Functions Proxies](https://docs.microsoft.com/azure/azure-functions/functions-proxies). - >[!div class="step-by-step"] >[Previous](azure-serverless-platform.md) >[Next](application-insights.md) diff --git a/docs/architecture/serverless/event-grid.md b/docs/architecture/serverless/event-grid.md index 3502843043992..f6f874701a37d 100644 --- a/docs/architecture/serverless/event-grid.md +++ b/docs/architecture/serverless/event-grid.md @@ -3,7 +3,7 @@ title: Azure Event Grid - Serverless apps description: Azure Event Grid is a serverless solution for reliable event delivery and routing at massive scale on a pay-per-event model. author: JEREMYLIKNESS ms.author: jeliknes -ms.date: 06/26/2018 +ms.date: 04/06/2020 --- # Event Grid @@ -126,14 +126,12 @@ In this chapter you learned about the Azure serverless platform that is composed - [Azure Logic Apps](https://docs.microsoft.com/azure/logic-apps) - [Azure Service Bus](https://docs.microsoft.com/azure/service-bus-messaging) - [Azure Table Storage](https://docs.microsoft.com/azure/cosmos-db/table-storage-overview) -- [Compare functions 1.x and 2.x](https://docs.microsoft.com/azure/azure-functions/functions-versions) - [Connecting to on-premises data sources with Azure On-premises Data Gateway](https://docs.microsoft.com/azure/analysis-services/analysis-services-gateway) - [Create your first function in the Azure portal](https://docs.microsoft.com/azure/azure-functions/functions-create-first-azure-function) - [Create your first function using the Azure CLI](https://docs.microsoft.com/azure/azure-functions/functions-create-first-azure-function-azure-cli) - [Create your first function using Visual Studio](https://docs.microsoft.com/azure/azure-functions/functions-create-your-first-function-visual-studio) - [Functions supported languages](https://docs.microsoft.com/azure/azure-functions/supported-languages) - [Monitor Azure Functions](https://docs.microsoft.com/azure/azure-functions/functions-monitoring) -- [Work with Azure Functions Proxies](https://docs.microsoft.com/azure/azure-functions/functions-proxies) >[!div class="step-by-step"] >[Previous](logic-apps.md) diff --git a/docs/architecture/serverless/index.md b/docs/architecture/serverless/index.md index 8fb41b2ec8e27..4511bd77af6f5 100644 --- a/docs/architecture/serverless/index.md +++ b/docs/architecture/serverless/index.md @@ -3,14 +3,16 @@ title: "Serverless apps: Architecture, patterns, and Azure implementation" description: Guide to serverless architecture. Learn when, why, and how to implement a serverless architecture (as opposed to Infrastructure as a Service [IaaS] or Platform as a Service [PaaS]) for your enterprise applications. author: JEREMYLIKNESS ms.author: jeliknes -ms.date: 06/26/2018 +ms.date: 04/22/2020 --- # Serverless apps: Architecture, patterns, and Azure implementation -![Screenshot that shows the Serverless Apps e-book cover.](./media/index/serverless-apps-cover.jpg) +![Screenshot that shows the Serverless Apps e-book cover.](./media/index/serverless-apps-cover-v3.png) -> DOWNLOAD available at: +**EDITION v3.0** - Updated to Azure Functions v3 + +> DOWNLOAD available at: PUBLISHED BY @@ -22,7 +24,7 @@ One Microsoft Way Redmond, Washington 98052-6399 -Copyright © 2018 by Microsoft Corporation +Copyright © 2018-2020 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. @@ -38,7 +40,7 @@ All other marks and logos are property of their respective owners. Author: -> **[Jeremy Likness](https://twitter.com/jeremylikness)**, Senior Cloud Advocate, Microsoft Corp. +> **[Jeremy Likness](https://twitter.com/jeremylikness)**, Senior .NET Data Program Manager, Microsoft Corp. Contributor: @@ -92,7 +94,7 @@ IaaS still requires heavy overhead because operations is still responsible for v - Keeping the operating system up-to-date. - Monitoring the application. -The next evolution reduced the overhead by providing Platform as a Service (PaaS). With PaaS, the cloud provider handles operating systems, security patches, and even the required packages to support a specific platform. Instead of building a VM then configuring the .NET Framework and standing up Internet Information Services (IIS) servers, developers simply choose a "platform target" such as "web application" or "API endpoint" and deploy code directly. The infrastructure questions are reduced to: +The next evolution reduced the overhead by providing Platform as a Service (PaaS). With PaaS, the cloud provider handles operating systems, security patches, and even the required packages to support a specific platform. Instead of building a VM then configuring .NET and standing up Internet Information Services (IIS) servers, developers simply choose a "platform target" such as "web application" or "API endpoint" and deploy code directly. The infrastructure questions are reduced to: - What size services are needed? - How do the services scale out (add more servers or nodes)? diff --git a/docs/architecture/serverless/media/index/serverless-apps-cover-v3.png b/docs/architecture/serverless/media/index/serverless-apps-cover-v3.png new file mode 100644 index 0000000000000000000000000000000000000000..d11a6f8d9aa8a9e564770a8820301f9016eb9ee2 GIT binary patch literal 77774 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�xzvl>(6#S}75|H`RsxIgen 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 literal 0 HcmV?d00001 diff --git a/docs/architecture/serverless/serverless-architecture-considerations.md b/docs/architecture/serverless/serverless-architecture-considerations.md index a49988af30249..11ac12984256c 100644 --- a/docs/architecture/serverless/serverless-architecture-considerations.md +++ b/docs/architecture/serverless/serverless-architecture-considerations.md @@ -3,7 +3,7 @@ title: Serverless architecture considerations - Serverless apps description: Understand the challenges of architecting serverless applications, from state management and persistent storage to scale, logging, tracing and diagnostics. author: JEREMYLIKNESS ms.author: jeliknes -ms.date: 06/26/2018 +ms.date: 04/06/2020 --- # Serverless architecture considerations @@ -17,7 +17,7 @@ There are several solutions to adopt state without compromising the benefits of - Use a temporary data store or distributed cache, like Redis - Store state in a database, like SQL or CosmosDB -- Handle state through a workflow engine like durable functions +- Handle state through a workflow engine like [durable functions](https://docs.microsoft.com/azure/azure-functions/durable/durable-functions-overview) The bottom line is that you should be aware of the need for any state management within processes you're considering to implement with serverless. @@ -73,7 +73,7 @@ For more information, see [Implementing the Circuit Breaker pattern](../microser ## Versioning and green/blue deployments -A major benefit of serverless is the ability to upgrade a specific function without having to redeploy the entire application. For upgrades to be successful, functions must be versioned so that services calling them are routed to the correct version of code. A strategy for deploying new versions is also important. A common approach is to use "green/blue deployments." The green deployment is the current function. A new "blue" version is deployed to production and tested. When testing passes, the green and blue versions are swapped so the new version comes live. If any issues are encountered, they can be swapped back. Supporting versioning and green/blue deployments requires a combination of authoring the functions to accommodate version changes and working with the serverless platform to handle deployments. One possible approach is to use proxies, which are described in the [Azure serverless platform](azure-functions.md#proxies) chapter. +A major benefit of serverless is the ability to upgrade a specific function without having to redeploy the entire application. For upgrades to be successful, functions must be versioned so that services calling them are routed to the correct version of code. A strategy for deploying new versions is also important. A common approach is to use "green/blue deployments." The green deployment is the current function. A new "blue" version is deployed to production and tested. When testing passes, the green and blue versions are swapped so the new version comes live. If any issues are encountered, they can be swapped back. Supporting versioning and green/blue deployments requires a combination of authoring the functions to accommodate version changes and working with the serverless platform to handle deployments. >[!div class="step-by-step"] >[Previous](serverless-architecture.md) diff --git a/docs/architecture/serverless/serverless-business-scenarios.md b/docs/architecture/serverless/serverless-business-scenarios.md index 14e74bf41c645..3cab0a92946ae 100644 --- a/docs/architecture/serverless/serverless-business-scenarios.md +++ b/docs/architecture/serverless/serverless-business-scenarios.md @@ -1,95 +1,116 @@ --- title: Sample business scenarios and use cases for serverless apps -description: Learn serverless with a hands-on approach by accessing samples that range from image processing to mobile back ends and ETL pipelines. +description: Learn serverless with a hands-on approach by accessing samples that range from image processing to mobile support and ETL pipelines. author: JEREMYLIKNESS ms.author: jeliknes -ms.date: 06/26/2018 +ms.date: 04/17/2020 --- # Serverless business scenarios and use cases There are many use cases and scenarios for serverless applications. This chapter includes samples that illustrate the different scenarios. The scenarios include links to related documentation and public source code repositories. The samples in this chapter enable you to get started on your own building and implementing serverless solutions. -## Analyze and archive images +## Big data processing -This sample demonstrates serverless events (Event Grid), workflows (Logic App), and code (Azure Functions). It also shows how to integrate with another resource, in this case Cognitive Services for image analysis. +![Map/reduce diagram](https://docs.microsoft.com/samples/azure-samples/durablefunctions-mapreduce-dotnet/big-data-processing-serverless-mapreduce-on-azure/media/mapreducearchitecture.png) -A console application allows you to pass a link to a URL on the web. The app publishes the URL as an event grid message. In parallel, a serverless function app and a logic app subscribe to the message. The serverless function app serializes the image to blob storage. It also stores information in Azure Table Storage. The metadata stores the original image URL and the name of the blob image. The logic app interacts with the Custom Vision API to analyze the image and create a machine-generated caption. The caption is stored in the metadata table. +This example uses serverless to do a map/reduce operation on a big data set. It determines the average speed of New York Yellow taxi trips per day in 2017. -![Analyze and archive images architecture](./media/image-processing-example.png) +[Big Data Processing: Serverless MapReduce on Azure](https://docs.microsoft.com/samples/azure-samples/durablefunctions-mapreduce-dotnet/big-data-processing-serverless-mapreduce-on-azure/) -A separate single page application (SPA) calls a serverless function to get a list of images and metadata. For each image, it calls another function that delivers the image data from the archive. The final result is a gallery with automatic captions. +## Create serverless applications: hands-on lab -![Automated image gallery](./media/automated-image-gallery.png) +Learn how to use functions to execute server-side logic and build serverless architectures. -The full repository and instructions to build the logic app are available here: [Event grid glue](https://github.com/JeremyLikness/Event-Grid-Glue). +- Choosing the best Azure service for your business +- Creating Azure Functions +- Using triggers +- Chaining functions +- Long-running workflows +- Monitoring +- Development, testing, and deployment -## Cross-platform mobile client using Xamarin.Forms and functions +[Create serverless applications](https://docs.microsoft.com/learn/paths/create-serverless-applications/) -See how to implement a simple serverless Azure Function in the Azure Web Portal or in Visual Studio. Build a client with Xamarin.Forms that runs on Android, iOS, and Windows. The application is then refined to use JavaScript Object Notation (JSON) as a communication medium between the server and the mobile clients with a serverless back end. +## Customer reviews -For more information, see [Implementing a simple Azure Function with a Xamarin.Forms client](https://docs.microsoft.com/samples/azure-samples/functions-xamarin-getting-started/implementing-a-simple-azure-function-with-a-xamarinforms-client/). +This sample showcases the new Azure Functions tooling for C# Class Libraries in Visual Studio. Create a website where customers submit product reviews that are stored in Azure storage blobs and CosmosDB. Add an Azure Function to perform automated moderation of the customer reviews using Azure Cognitive Services. Use an Azure storage queue to decouple the website from the function. -## Generate a photo mosaic with serverless image recognition +[Customer Reviews App with Cognitive Services](https://docs.microsoft.com/samples/azure-samples/functions-customer-reviews/customer-reviews-cognitive-services/) -The sample uses Azure Functions and Microsoft Cognitive Services Custom Vision Service to generate a photo mosaic from an input image. The model is trained to recognize images. When an image is uploaded, it recognizes the image and searches with Bing. The original image is recomposed using the search results. +## Docker Linux image support -![Orlando eye photo and mosaic](./media/orlando-eye-both.png) +This sample demonstrates how to create a `Dockerfile` to build and run Azure Functions on a Linux Docker container. -For example, you can train your model with Orlando landmarks, such as the Orlando Eye. Custom Vision will recognize an image of the Orlando Eye, and the function will create a photo mosaic composed of Bing image search results for "Orlando Eye." +[Azure Functions on Linux](https://docs.microsoft.com/samples/azure-samples/functions-linux-custom-image/azure-functions-on-linux-custom-image-tutorial-sample-project/) -For more information, see [Azure Functions photo mosaic generator](https://github.com/Azure-Samples/functions-dotnet-photo-mosaic). +## File processing and validation -## Migrate an existing application to the cloud +This example parses a set of CSV files from hypothetical customers. It ensures that all files required for a customer "batch" are ready, then validates the structure of each file. Different solutions are presented using Azure Functions, Logic Apps, and Durable Functions. -As discussed in previous chapters, it's common to embrace an N-Tier architecture to host your application on-premises. Although migrating resources "as is" using virtual machines is the least risky path to the cloud, many companies choose to use the opportunity to refactor their applications. Fortunately, refactoring doesn't have to be an "all-or-nothing" effort. In fact, it's possible to migrate your app then piecemeal replace components with cloud native counterparts. +[File processing and validation using Azure Functions, Logic Apps, and Durable Functions](https://docs.microsoft.com/samples/azure-samples/serverless-file-validation/file-processing-and-validation-using-azure-functions-logic-apps-and-durable-functions/) -The application uses the proxies feature of Azure Functions to enable refactoring an endpoint from legacy on-premises code to a serverless endpoint. +## Game data visualization -![Migration architecture](./media/migration-architecture.png) +![Game telemetry](https://docs.microsoft.com/samples/azure-samples/gaming-in-editor-telemetry/in-editor-telemetry-visualization/media/points.png) -The proxy provides a single API endpoint that is updated to reroute individual requests as they're moved into serverless functions. +An example of how a developer could implement an in-editor data visualization solution for their game. In fact, an Unreal Engine 4 Plugin and Unity Plugin were developed using this sample as its backend. The service component is game engine agnostic. -You can view a video that walks through the entire migration: [Lift and shift with serverless Azure functions](https://channel9.msdn.com/Events/Connect/2017/E102). Access the sample code: [Bring your own app](https://github.com/JeremyLikness/bring-own-app-connect-17). +[In-editor game telemetry visualization](https://docs.microsoft.com/samples/azure-samples/gaming-in-editor-telemetry/in-editor-telemetry-visualization/) -## Parse a CSV file and insert into a database +## GraphQL -Extract, Transform, and Load (ETL) is a common business function that integrates different systems. Traditional approaches often involve setting up dedicated FTP servers then deploying scheduled jobs to parse files and translate them for business use. Serverless architecture makes the job easier because a trigger can fire when the file is uploaded. Azure Functions tackles tasks like ETL through its ideal composition of small pieces of code that focus on a specific problem. +Create a serverless function that exposes a GraphQL API. -![Screenshot that shows the csv parsing process.](./media/serverless-business-scenarios/csv-parse-database-import.png) +[Serverless functions for GraphQL](https://github.com/softchris/graphql-workshop-dotnet/blob/master/docs/workshop/4.md) -For source code and a hands-on lab, see [CSV import lab](https://github.com/JeremyLikness/azure-fn-file-process-hol). +## Internet of Things (IoT) reliable edge relay -## Shorten links and track metrics +![IoT Architecture](https://docs.microsoft.com/samples/azure-samples/iot-reliable-edge-relay/iot-reliable-edge-relay/media/architecture.png) -Link shortening tools originally helped encode URLs in short twitter posts to accommodate the 140 character limit. They've grown to encompass several uses, most commonly to track click-throughs for analytics. The link shortener scenario is an entirely serverless application that manages links and reports metrics. +This sample implements a new communication protocol to enable reliable upstream communication from IoT devices. It automates data gap detection and backfill. -Azure Functions is used to serve a Single Page Application (SPA) that allows you to paste the long URL and generate short URLs. The URLs are tagged to track things like campaigns (topics) and mediums (such as social networks that the links are posted to). The short code is stored in Azure Table Storage as the key, with the long URL as the value. When you click on the short link, another function looks up the long URL, sends a redirect, and places information about the event on a queue. Another Azure Function processes the queue and places the information into Azure Cosmos DB. +[IoT Reliable Edge Relay](https://docs.microsoft.com/samples/azure-samples/iot-reliable-edge-relay/iot-reliable-edge-relay/) -![Link shortener architecture](./media/link-shortener-architecture.png) +## Microservices reference architecture -You can then create a Power BI dashboard to gather insights about the data collected. On the back end, Application Insights provides important metrics. Telemetry includes how long it takes for the average user to redirect and how long it takes to access Azure Table Storage. +![Reference architecture](https://docs.microsoft.com/samples/azure-samples/serverless-microservices-reference-architecture/serverless-microservices-reference-architecture/media/macro-architecture.png) -![Power BI example](./media/power-bi-example.png) +A reference architecture that walks you through the decision-making process involved in designing, developing, and delivering the Rideshare by Relecloud application (a fictitious company). It includes hands-on instructions for configuring and deploying all of the architecture's components. -The full link shortener repository with instructions is available here: [Serverless URL shortener](https://github.com/jeremylikness/serverless-url-shortener). You can read about a simplified version here: [Azure Storage for serverless .NET apps in minutes](https://devblogs.microsoft.com/aspnet/azure-storage-for-serverless-net-apps-in-minutes/). +[Serverless Microservices reference architecture](https://docs.microsoft.com/samples/azure-samples/serverless-microservices-reference-architecture/serverless-microservices-reference-architecture/) -## Verify device connectivity using a ping +## Migrate console apps to serverless -The sample consists of an Azure IoT Hub and an Azure Function. A new message on the IoT Hub triggers the Azure Function. The serverless code sends the same message content back to the device that sent it. The project has all the code and deployment configuration needed for the solution. +This sample is a generic function (`.csx` file) that can be used to convert any console application to an HTTP web service in Azure Functions. All you have to do is edit a configuration file and specify what input parameters will be passed as arguments to the `.exe`. -For more information, see [Azure IoT Hub ping](https://github.com/Azure-Samples/iot-hub-node-ping). +[Run Console Apps on Azure Functions](https://docs.microsoft.com/samples/azure-samples/functions-dotnet-migrating-console-apps/run-console-apps-on-azure-functions/) + +## Serverless for mobile + +Azure Functions are easy to implement and maintain, and accessible through HTTP. They are a great way to implement an API for a mobile application. Microsoft offers great cross-platform tools for iOS, Android, and Windows with Xamarin. As such, Xamarin and Azure Functions are working great together. This article shows how to implement an Azure Function in the Azure Web Portal or in Visual Studio at first, and build a cross-platform client with Xamarin.Forms, running on Android, iOS, and Windows. + +[Implementing a simple Azure Function with a Xamarin.Forms client](https://docs.microsoft.com/samples/azure-samples/functions-xamarin-getting-started/implementing-a-simple-azure-function-with-a-xamarinforms-client/) + +## Serverless messaging + +This sample shows how to utilize Durable Functions' fan out pattern to load an arbitrary number of messages across any number of sessions/partitions. It targets Service Bus, Event Hubs, or Storage Queues. The sample also adds the ability to consume those messages with another Azure Function and load the resulting timing data in to another Event Hub. The data is then ingested into analytics services like Azure Data Explorer. + +[Produce and Consume messages through Service Bus, Event Hubs, and Storage Queues with Azure Functions](https://docs.microsoft.com/samples/azure-samples/durable-functions-producer-consumer/product-consume-messages-az-functions/) ## Recommended resources -- [Azure Functions photo mosaic generator](https://github.com/Azure-Samples/functions-dotnet-photo-mosaic) -- [Azure IoT Hub ping](https://github.com/Azure-Samples/iot-hub-node-ping) -- [Azure Storage for serverless .NET apps in minutes](https://devblogs.microsoft.com/aspnet/azure-storage-for-serverless-net-apps-in-minutes/) -- [Bring your own app](https://github.com/JeremyLikness/bring-own-app-connect-17) -- [CSV import lab](https://github.com/JeremyLikness/azure-fn-file-process-hol) -- [Event grid glue](https://github.com/JeremyLikness/Event-Grid-Glue) +- [Azure Functions on Linux](https://docs.microsoft.com/samples/azure-samples/functions-linux-custom-image/azure-functions-on-linux-custom-image-tutorial-sample-project/) +- [Big Data Processing: Serverless MapReduce on Azure](https://docs.microsoft.com/samples/azure-samples/durablefunctions-mapreduce-dotnet/big-data-processing-serverless-mapreduce-on-azure/) +- [Create serverless applications](https://docs.microsoft.com/learn/paths/create-serverless-applications/) +- [Customer Reviews App with Cognitive Services](https://docs.microsoft.com/samples/azure-samples/functions-customer-reviews/customer-reviews-cognitive-services/) +- [File processing and validation using Azure Functions, Logic Apps, and Durable Functions](https://docs.microsoft.com/samples/azure-samples/serverless-file-validation/file-processing-and-validation-using-azure-functions-logic-apps-and-durable-functions/) - [Implementing a simple Azure Function with a Xamarin.Forms client](https://docs.microsoft.com/samples/azure-samples/functions-xamarin-getting-started/implementing-a-simple-azure-function-with-a-xamarinforms-client/) -- [Lift and shift with serverless Azure functions](https://channel9.msdn.com/Events/Connect/2017/E102) -- [Serverless URL shortener](https://github.com/jeremylikness/serverless-url-shortener) +- [In-editor game telemetry visualization](https://docs.microsoft.com/samples/azure-samples/gaming-in-editor-telemetry/in-editor-telemetry-visualization/) +- [IoT Reliable Edge Relay](https://docs.microsoft.com/samples/azure-samples/iot-reliable-edge-relay/iot-reliable-edge-relay/) +- [Produce and Consume messages through Service Bus, Event Hubs, and Storage Queues with Azure Functions](https://docs.microsoft.com/samples/azure-samples/durable-functions-producer-consumer/product-consume-messages-az-functions/) +- [Run Console Apps on Azure Functions](https://docs.microsoft.com/samples/azure-samples/functions-dotnet-migrating-console-apps/run-console-apps-on-azure-functions/) +- [Serverless functions for GraphQL](https://github.com/softchris/graphql-workshop-dotnet/blob/master/docs/workshop/4.md) +- [Serverless Microservices reference architecture](https://docs.microsoft.com/samples/azure-samples/serverless-microservices-reference-architecture/serverless-microservices-reference-architecture/) >[!div class="step-by-step"] >[Previous](orchestration-patterns.md) From 781e0d07166f716956f1601c133647031bc168b7 Mon Sep 17 00:00:00 2001 From: Raj Shah <32351151+rnshah9@users.noreply.github.com> Date: Thu, 23 Apr 2020 08:37:37 -0700 Subject: [PATCH 08/18] Fix typo (#18028) * Remove Schemas property type reference entirely --- .../data/xml/xml-schema-xsd-validation-with-xmlschemaset.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/standard/data/xml/xml-schema-xsd-validation-with-xmlschemaset.md b/docs/standard/data/xml/xml-schema-xsd-validation-with-xmlschemaset.md index 47e5962dd0f87..e66e75636fb0b 100644 --- a/docs/standard/data/xml/xml-schema-xsd-validation-with-xmlschemaset.md +++ b/docs/standard/data/xml/xml-schema-xsd-validation-with-xmlschemaset.md @@ -27,7 +27,7 @@ XML documents can be validated against an XML schema definition language (XSD) s [!code-xml[XSDInference Examples#6](../../../../samples/snippets/xml/VS_Snippets_Data/XSDInference Examples/XML/contosoBooks.xsd#6)] - In the code example that follows, the schema above is added to the property of the object. The object is passed as a parameter to the method of the object, which validates the XML document above. + In the code example that follows, the schema above is added to the property of the object. The object is passed as a parameter to the method of the object, which validates the XML document above. The property of the object is set to `Schema` to enforce validation of the XML document by the method of the object. A is added to the object to handle any or events raised by errors found during the validation process of both the XML document and the schema. From 7ec1ffceb2fd68d188a5f5cc619538c75388cd11 Mon Sep 17 00:00:00 2001 From: Genevieve Warren Date: Thu, 23 Apr 2020 09:05:08 -0700 Subject: [PATCH 09/18] Add cryptography as a BC category (#18034) --- .github/ISSUE_TEMPLATE/dotnet-breaking-change.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/dotnet-breaking-change.md b/.github/ISSUE_TEMPLATE/dotnet-breaking-change.md index 31171ed2b546d..09085aba04e80 100644 --- a/.github/ISSUE_TEMPLATE/dotnet-breaking-change.md +++ b/.github/ISSUE_TEMPLATE/dotnet-breaking-change.md @@ -44,11 +44,12 @@ Also, remove this comment before submitting the issue. - C# - Core - Core .NET libraries +- Cryptography - Data - Debugger - Deployment for .NET Core - Globalization -- interop +- Interop - JIT - LINQ - Managed Extensibility Framework (MEF) From 1f778d869a75916a06e6b823afb128967573f090 Mon Sep 17 00:00:00 2001 From: Genevieve Warren Date: Thu, 23 Apr 2020 09:06:32 -0700 Subject: [PATCH 10/18] add exception handling breaking change (#18026) --- docs/core/compatibility/corefx.md | 5 +++ docs/core/compatibility/fx-core.md | 5 +++ .../corefx/1.0/corrupted-state-exceptions.md | 34 +++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 includes/core-changes/corefx/1.0/corrupted-state-exceptions.md diff --git a/docs/core/compatibility/corefx.md b/docs/core/compatibility/corefx.md index 93a555b690e8c..9cdeb94366cce 100644 --- a/docs/core/compatibility/corefx.md +++ b/docs/core/compatibility/corefx.md @@ -29,6 +29,7 @@ The following breaking changes are documented on this page: | [Change in default value of UseShellExecute](#change-in-default-value-of-useshellexecute) | 2.1 | | [OpenSSL versions on macOS](#openssl-versions-on-macos) | 2.1 | | [UnauthorizedAccessException thrown by FileSystemInfo.Attributes](#unauthorizedaccessexception-thrown-by-filesysteminfoattributes) | 1.0 | +| [Handling corrupted-process-state exceptions is not supported](#handling-corrupted-state-exceptions-is-not-supported) | 1.0 | ## .NET Core 3.0 @@ -107,3 +108,7 @@ The following breaking changes are documented on this page: [!INCLUDE [UnauthorizedAccessException thrown by FileSystemInfo.Attributes](~/includes/core-changes/corefx/1.0/filesysteminfo-attributes-exceptions.md)] *** + +[!INCLUDE [corrupted-state-exceptions](~/includes/core-changes/corefx/1.0/corrupted-state-exceptions.md)] + +*** diff --git a/docs/core/compatibility/fx-core.md b/docs/core/compatibility/fx-core.md index c06b3c40ea8ed..d248b65f6a630 100644 --- a/docs/core/compatibility/fx-core.md +++ b/docs/core/compatibility/fx-core.md @@ -15,6 +15,7 @@ If you're migrating an app from .NET Framework to .NET Core, the breaking change - [Change in default value of UseShellExecute](#change-in-default-value-of-useshellexecute) - [UnauthorizedAccessException thrown by FileSystemInfo.Attributes](#unauthorizedaccessexception-thrown-by-filesysteminfoattributes) +- [Handling corrupted-process-state exceptions is not supported](#handling-corrupted-state-exceptions-is-not-supported) ### .NET Core 2.1 @@ -28,6 +29,10 @@ If you're migrating an app from .NET Framework to .NET Core, the breaking change *** +[!INCLUDE [corrupted-state-exceptions](~/includes/core-changes/corefx/1.0/corrupted-state-exceptions.md)] + +*** + ## Cryptography - [Boolean parameter of SignedCms.ComputeSignature is respected](#boolean-parameter-of-signedcmscomputesignature-is-respected) diff --git a/includes/core-changes/corefx/1.0/corrupted-state-exceptions.md b/includes/core-changes/corefx/1.0/corrupted-state-exceptions.md new file mode 100644 index 0000000000000..3c299fc797f37 --- /dev/null +++ b/includes/core-changes/corefx/1.0/corrupted-state-exceptions.md @@ -0,0 +1,34 @@ +### Handling corrupted state exceptions is not supported + +Handling corrupted-process-state exceptions in .NET Core is not supported. + +#### Change description + +Previously, corrupted-process-state exceptions could be caught and handled by managed code exception handlers, for example, by using a [try-catch](../../../../docs/csharp/language-reference/keywords/try-catch.md) statement in C#. + +Starting in .NET Core 1.0, corrupted-process-state exceptions cannot be handled by managed code. The common language runtime doesn't deliver corrupted-process-state exceptions to managed code. + +#### Version introduced + +1.0 + +#### Recommended action + +Avoid the need to handle corrupted-process-state exceptions by addressing the situations that lead to them instead. If it's absolutely necessary to handle corrupted-process-state exceptions, write the exception handler in C or C++ code. + +#### Category + +Core .NET libraries + +#### Affected APIs + +- +- [legacyCorruptedStateExceptionsPolicy element](~/docs/framework/configure-apps/file-schema/runtime/legacycorruptedstateexceptionspolicy-element.md) + + From fc319b2d0c922238e3548a7cdc7f2ea71f6599fa Mon Sep 17 00:00:00 2001 From: Genevieve Warren Date: Thu, 23 Apr 2020 09:07:00 -0700 Subject: [PATCH 11/18] Add breaking change for root certs (#18025) * add breaking change --- docs/core/compatibility/2.2-3.0.md | 5 ++ docs/core/compatibility/2.2-3.1.md | 5 ++ docs/core/compatibility/cryptography.md | 7 ++- .../3.0/begin-trusted-cert-linux.md | 50 +++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 includes/core-changes/cryptography/3.0/begin-trusted-cert-linux.md diff --git a/docs/core/compatibility/2.2-3.0.md b/docs/core/compatibility/2.2-3.0.md index 6a19b2d941433..07ec61f515d94 100644 --- a/docs/core/compatibility/2.2-3.0.md +++ b/docs/core/compatibility/2.2-3.0.md @@ -335,11 +335,16 @@ If you're migrating from version 2.2 to version 3.0 of .NET Core, ASP.NET Core, ## Cryptography +- [BEGIN TRUSTED CERTIFICATE syntax no longer supported on Linux](#begin-trusted-certificate-syntax-no-longer-supported-for-root-certificates-on-linux) - [EnvelopedCms defaults to AES-256 encryption](#envelopedcms-defaults-to-aes-256-encryption) - [Minimum size for RSAOpenSsl key generation has increased](#minimum-size-for-rsaopenssl-key-generation-has-increased) - [.NET Core 3.0 prefers OpenSSL 1.1.x to OpenSSL 1.0.x](#net-core-30-prefers-openssl-11x-to-openssl-10x) - [Better argument validation in the Pkcs8PrivateKeyInfo constructor](#better-argument-validation-in-the-pkcs8privatekeyinfo-constructor) +[!INCLUDE [begin-trusted-cert-linux](~/includes/core-changes/cryptography/3.0/begin-trusted-cert-linux.md)] + +*** + [!INCLUDE[EnvelopedCms defaults to AES-256 encryption](~/includes/core-changes/cryptography/3.0/envelopedcms-defaults-to-aes256.md)] *** diff --git a/docs/core/compatibility/2.2-3.1.md b/docs/core/compatibility/2.2-3.1.md index edc6d3e19def9..38bef24ac15e0 100644 --- a/docs/core/compatibility/2.2-3.1.md +++ b/docs/core/compatibility/2.2-3.1.md @@ -338,11 +338,16 @@ If you're migrating from version 2.2 to version 3.1 of .NET Core, ASP.NET Core, ## Cryptography +- [BEGIN TRUSTED CERTIFICATE syntax no longer supported on Linux](#begin-trusted-certificate-syntax-no-longer-supported-for-root-certificates-on-linux) - [EnvelopedCms defaults to AES-256 encryption](#envelopedcms-defaults-to-aes-256-encryption) - [Minimum size for RSAOpenSsl key generation has increased](#minimum-size-for-rsaopenssl-key-generation-has-increased) - [.NET Core 3.0 prefers OpenSSL 1.1.x to OpenSSL 1.0.x](#net-core-30-prefers-openssl-11x-to-openssl-10x) - [Better argument validation in the Pkcs8PrivateKeyInfo constructor](#better-argument-validation-in-the-pkcs8privatekeyinfo-constructor) +[!INCLUDE [begin-trusted-cert-linux](~/includes/core-changes/cryptography/3.0/begin-trusted-cert-linux.md)] + +*** + [!INCLUDE[EnvelopedCms defaults to AES-256 encryption](~/includes/core-changes/cryptography/3.0/envelopedcms-defaults-to-aes256.md)] *** diff --git a/docs/core/compatibility/cryptography.md b/docs/core/compatibility/cryptography.md index 104c5e230a6a9..f8f1e03986073 100644 --- a/docs/core/compatibility/cryptography.md +++ b/docs/core/compatibility/cryptography.md @@ -1,7 +1,7 @@ --- title: Cryptography breaking changes description: Lists cryptography-related breaking changes in .NET Core. -ms.date: 02/10/2020 +ms.date: 04/22/2020 --- # Cryptography breaking changes @@ -9,6 +9,7 @@ The following breaking changes are documented on this page: | Breaking change | Version introduced | | - | :-: | +| [BEGIN TRUSTED CERTIFICATE syntax no longer supported on Linux](#begin-trusted-certificate-syntax-no-longer-supported-for-root-certificates-on-linux) | 3.0 | | [EnvelopedCms defaults to AES-256 encryption](#envelopedcms-defaults-to-aes-256-encryption) | 3.0 | | [Minimum size for RSAOpenSsl key generation has increased](#minimum-size-for-rsaopenssl-key-generation-has-increased) | 3.0 | | [.NET Core 3.0 prefers OpenSSL 1.1.x to OpenSSL 1.0.x](#net-core-30-prefers-openssl-11x-to-openssl-10x) | 3.0 | @@ -17,6 +18,10 @@ The following breaking changes are documented on this page: ## .NET Core 3.0 +[!INCLUDE [begin-trusted-cert-linux](~/includes/core-changes/cryptography/3.0/begin-trusted-cert-linux.md)] + +*** + [!INCLUDE[EnvelopedCms defaults to AES-256 encryption](~/includes/core-changes/cryptography/3.0/envelopedcms-defaults-to-aes256.md)] *** diff --git a/includes/core-changes/cryptography/3.0/begin-trusted-cert-linux.md b/includes/core-changes/cryptography/3.0/begin-trusted-cert-linux.md new file mode 100644 index 0000000000000..d3fe3d8338f32 --- /dev/null +++ b/includes/core-changes/cryptography/3.0/begin-trusted-cert-linux.md @@ -0,0 +1,50 @@ +### "BEGIN TRUSTED CERTIFICATE" syntax no longer supported for root certificates on Linux + +Root certificates on Linux and other Unix-like systems (but not macOS) can be presented in two forms: the standard `BEGIN CERTIFICATE` PEM header, and the OpenSSL-specific `BEGIN TRUSTED CERTIFICATE` PEM header. The latter syntax allows for additional configuration that has caused compatibility issues with .NET Core's class. `BEGIN TRUSTED CERTIFICATE` root certificate contents are no longer loaded by the chain engine starting in .NET Core 3.0. + +#### Change description + +Previously, both the `BEGIN CERTIFICATE` and `BEGIN TRUSTED CERTIFICATE` syntaxes were used to populate the root trust list. If the `BEGIN TRUSTED CERTIFICATE` syntax was used and additional options were specified in the file, may have reported that the chain trust was explicitly disallowed (). However, if the certificate was also specified with the `BEGIN CERTIFICATE` syntax in a previously loaded file, the chain trust was allowed. + +Starting in .NET Core 3.0, `BEGIN TRUSTED CERTIFICATE` contents are no longer read. If the certificate is not also specified via a standard `BEGIN CERTIFICATE` syntax, the reports that the root is not trusted (). + +#### Version introduced + +3.0 + +#### Recommended action + +Most applications are unaffected by this change, but applications that cannot see both root certificate sources because of permissions problems may experience unexpected `UntrustedRoot` errors after upgrading. + +Many Linux distributions (or distros) write root certificates into two locations: a one-certificate-per-file directory, and a one-file concatenation. On some distros, the one-certificate-per-file directory uses the `BEGIN TRUSTED CERTIFICATE` syntax while the file concatenation uses the standard `BEGIN CERTIFICATE` syntax. Ensure that any custom root certificates are added as `BEGIN CERTIFICATE` in at least one of these locations, and that both locations can be read by your application. + +The typical directory is */etc/ssl/certs/* and the typical concatenated file is */etc/ssl/cert.pem*. Use the command `openssl version -d` to determine the platform-specific root, which may differ from */etc/ssl/*. For example, on Ubuntu 18.04, the directory is */usr/lib/ssl/certs/* and the file is */usr/lib/ssl/cert.pem*. However, */usr/lib/ssl/certs/* is a symlink to */etc/ssl/certs/* and */usr/lib/ssl/cert.pem* does not exist. + +```bash +$ openssl version -d +OPENSSLDIR: "/usr/lib/ssl" +$ ls -al /usr/lib/ssl +total 12 +drwxr-xr-x 3 root root 4096 Dec 12 17:10 . +drwxr-xr-x 73 root root 4096 Feb 20 15:18 .. +lrwxrwxrwx 1 root root 14 Mar 27 2018 certs -> /etc/ssl/certs +drwxr-xr-x 2 root root 4096 Dec 12 17:10 misc +lrwxrwxrwx 1 root root 20 Nov 12 16:58 openssl.cnf -> /etc/ssl/openssl.cnf +lrwxrwxrwx 1 root root 16 Mar 27 2018 private -> /etc/ssl/private +``` + +### Category + +Cryptography + +### Affected APIs + +- + + From 87ad04ff8fd76039b6c81756fb2e098997fff30f Mon Sep 17 00:00:00 2001 From: Taylor Southwick Date: Thu, 23 Apr 2020 09:54:14 -0700 Subject: [PATCH 12/18] Reorder and expand porting guidance steps --- docs/core/porting/index.md | 81 +++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 10 deletions(-) diff --git a/docs/core/porting/index.md b/docs/core/porting/index.md index be519d1fea7a6..63c9bf395ebd5 100644 --- a/docs/core/porting/index.md +++ b/docs/core/porting/index.md @@ -13,35 +13,96 @@ You might have code that currently runs on the .NET Framework that you're intere ## Overview of the porting process +Porting to .NET Core (or .NET Standard) from .NET Framework for many projects is relatively straight forward. There are a number of changes that are required, but many of them follow the patterns outlined below. Projects where the app-model is available in .NET Core (such as libraries, console apps, and desktop applications) usually require little changes. Projects that require a new app model, such as moving to ASP.NET Core from ASP.NET, require a bit more work, but many patterns have analogs that can be used during the conversion. This document should help with identifying the main strategies that have been employed by users to successfully convert their code bases to target .NET Standard or .NET Core and will address the conversion at two levels: solution-wide and project specific. See the links at the bottom for directions on app-model specific conversions. + +We recommend you use the following process when porting your project to .NET Core. Each of these steps introduces potential places for behavior changes, so ensure that you adequately test your library or application before continuing on to later steps. The first steps are to get your project ready for a switch to .NET Standard or .NET Core. If you have unit tests, it's best to convert them first so that you can continue testing changes in the product you're working on. Because porting to .NET Core is such a significant change to your codebase, it's highly recommended to port your test projects so that you can run tests as you port your code over. MSTest, xUnit, and NUnit all work on .NET Core. + +## Getting started + +The following tools will be used throughout the process: + +- Visual Studio 2019 +- Download [.NET Portability Analyzer](../../standard/analyzers/portability-analyzer.md) +- _Optional_ Install [dotnet try-convert](https://github.com/dotnet/try-convert) + +## Porting a solution + +When there are multiple projects in a solution the porting can seem more complicated because you must address projects in a specific order. The conversion process should be a bottom-up approach, where the projects with no dependencies on other projects in the solution are converted first, and continue up through the whole solution. + +In order to identify the order projects should be migrated, you can use the following tools: + +- [Dependency Diagrams in Visual Studio](/visualstudio/modeling/create-layer-diagrams-from-your-code) can create a directed graph of the code in a solution. +- Run `msbuild _SolutionPath_ /t:GenerateRestoreGraphFile /p:RestoreGraphOutputPath=graph.dg.json` to generate a json document that includes list of project references. + +## Per project steps + We recommend you use the following process when porting your project to .NET Core: +1. Convert all of your `packages.config` dependencies to the [PackageReference](/nuget/consume-packages/package-references-in-project-files) format with the [conversion tool in Visual Studio](/nuget/consume-packages/migrate-packages-config-to-package-reference). + + This step involves converting your dependencies from the legacy `packages.config` format. `packages.config` doesn't work on .NET Core, so this conversion is required if you have package dependencies. It also only requires the dependencies you are directly using in a project which will make later steps easier by reducing the amount of dependencies you must manage. + +1. Convert your project file to the new SDK-style files structure. You can create new projects for .NET Core and copy over source files, or attempt to convert your existing project file with a tool. + + .NET Core uses a simplified (and different) [project file format](../tools/csproj.md) than .NET Framework. You'll need to convert your project files into this format to continue. This project style allows you to also target .NET Framework, which at this point you'll still want to target. + + You can attempt to port smaller solutions or individual projects in one operation to the .NET Core project file format with the [dotnet try-convert](https://github.com/dotnet/try-convert) tool. `dotnet try-convert` is not guaranteed to work for all your projects, and it may cause subtle changes in behavior that you depended on. Use it as a _starting point_ that automates the basic things that can be automated. It isn't a guaranteed solution to migrating a project, as there are many differences in the targets used by the SDK style projects compared to the old-style project files. + 1. Retarget all projects you wish to port to target .NET Framework 4.7.2 or higher. This step ensures that you can use API alternatives for .NET Framework-specific targets when .NET Core doesn't support a particular API. -2. Use the [.NET Portability Analyzer](../../standard/analyzers/portability-analyzer.md) to analyze your assemblies and see if they're portable to .NET Core. +1. Update all dependencies to the latest version. Projects may be using older versions of libraries that may not have .NET Standard support. However, later versions may support it with a simple switch. This may require code changes if there are breaking changes in libraries. + +1. Use the [.NET Portability Analyzer](../../standard/analyzers/portability-analyzer.md) to analyze your assemblies and see if they're portable to .NET Core. - The API Portability Analyzer tool analyzes your compiled assemblies and generates a report. This report shows a high-level portability summary and a breakdown of each API you're using that isn't available on NET Core. + The .NET Portability Analyzer tool analyzes your compiled assemblies and generates a report. This report shows a high-level portability summary and a breakdown of each API you're using that isn't available on NET Core. While using the tool, only submit the individual project you are converting to focus on the API changes that are potentially needed. Many of the APIs have equivalent availability in .NET Core, which you'll want to switch to. -3. Install the [.NET API analyzer](../../standard/analyzers/api-analyzer.md) into your projects to identify APIs that throw on some platforms and some other potential compatibility issues. + While reading the reports generated by the analyzer, the important information is the actual APIs that are being used and not necessarily the percentage of support for the target platform. Many APIs have equivalent options in .NET Standard/Core, and so understanding the scenarios your library or application needs the API for will help determine the implication for portability. + + There are some cases where APIs are not equivalent and you'll need to do some compiler preprocessor directives (i.e. `#if NET45`) to special case the platforms. At this point, you're project will still be targeting .NET Framework. For each of these targeted cases, it is recommended to use well-known conditionals that can be understood as a scenario. For example, AppDomain support in .NET Core is limited, but for the scenario of loading and unloading assemblies, there is a new API that is not available in .NET Core. A common way to handle this in code would be something like this: + + ```csharp + #if FEATURE_APPDOMAIN_LOADING + // Code that uses appdomains + #elif FEATURE_ASSEMBLY_LOAD_CONTEXT + // Code that uses assembly load context + #else + #error Unsupported platform + #endif + ``` + +1. Install the [.NET API analyzer](../../standard/analyzers/api-analyzer.md) into your projects to identify APIs that throw on some platforms and some other potential compatibility issues. This tool is similar to the portability analyzer, but instead of analyzing if code can build on .NET Core, it analyzes whether you're using an API in a way that will throw a at run time. Although this isn't common if you're moving from .NET Framework 4.7.2 or higher, it's good to check. For more information about APIs that throw exceptions on .NET Core, see [APIs that always throw exceptions on .NET Core](../compatibility/unsupported-apis.md). -4. Convert all of your `packages.config` dependencies to the [PackageReference](/nuget/consume-packages/package-references-in-project-files) format with the [conversion tool in Visual Studio](/nuget/consume-packages/migrate-packages-config-to-package-reference). +1. At this point, you can switch to targeting .NET Core (generally for applications) or .NET Standard (for libraries). + + The choice between .NET Core and .NET Standard is largely dependent on where the project will be run. If it is a library that will be consumed by other applications or distributed via NuGet, the preference is usually to target .NET Standard. However, there may be APIs that are only available on .NET Core for performance or other reasons; if that's the case, .NET Core should be targeted with potentially a .NET Standard build available as well with reduced performance or funcitonality. By targeting .NET Standard, the project will be ready to run on new platforms (such as WebAssembly). If the project has dependencies on specific app frameworks (such as ASP.NET Core), then the target will be limited by what the dependencies support. + + If there are no preprocessor directives to conditional compile code for .NET Framework or .NET Standard, this will be as simple as finding the following in the project file: - This step involves converting your dependencies from the legacy `packages.config` format. `packages.config` doesn't work on .NET Core, so this conversion is required if you have package dependencies. + ```xml + net472 + ``` -5. Create new projects for .NET Core and copy over source files, or attempt to convert your existing project file with a tool. + and switch it to the desired framework. For .NET Core 3.1, this would be: - .NET Core uses a simplified (and different) [project file format](../tools/csproj.md) than .NET Framework. You'll need to convert your project files into this format to continue. + ```xml + netcoreapp3.1 + ``` -6. Port your test code. + However, if this is a library that you want to continue supporting .NET Framework specific builds for some reason, you can [multi-target](../../standard/library-guidance/cross-platform-targeting.md) by replacing it with the following: - Because porting to .NET Core is such a significant change to your codebase, it's highly recommended to port your test projects so that you can run tests as you port your code over. MSTest, xUnit, and NUnit all work on .NET Core. + ```xml + net472;netstandard2.0 + ``` -Additionally, you can attempt to port smaller solutions or individual projects in one operation to the .NET Core project file format with the [dotnet try-convert](https://github.com/dotnet/try-convert) tool. `dotnet try-convert` is not guaranteed to work for all your projects, and it may cause subtle changes in behavior that you depended on. Use it as a _starting point_ that automates the basic things that can be automated. It isn't a guaranteed solution to migrating a project. + If you're using Windows-specific APIs (such as registry access), you should install the [Windows Compatibility Pack](./windows-compat-pack.md). ## Next steps >[!div class="nextstepaction"] >[Analyze dependencies](third-party-deps.md) +>[Package NuGet Package](../deploying/creating-nuget-packages.md) +>[ASP.NET to ASP.NET Core Migration](/aspnet/core/migration/proper-to-2x) From 30bf6142d9bdea644d3c2d6799513bfb64de8150 Mon Sep 17 00:00:00 2001 From: Tom Dykstra Date: Thu, 23 Apr 2020 10:49:28 -0700 Subject: [PATCH 13/18] Add WeatherForecast example (#18036) * add WeatherForecast example * add link to migration doc * remove extra see also link * code style s.t.j. --- docs/standard/serialization/system-text-json-how-to.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/standard/serialization/system-text-json-how-to.md b/docs/standard/serialization/system-text-json-how-to.md index c1024bb383d52..24eb9ea9945e0 100644 --- a/docs/standard/serialization/system-text-json-how-to.md +++ b/docs/standard/serialization/system-text-json-how-to.md @@ -11,12 +11,16 @@ helpviewer_keywords: # How to serialize and deserialize (marshal and unmarshal) JSON in .NET -This article shows how to use the namespace to serialize and deserialize to and from JavaScript Object Notation (JSON). +This article shows how to use the namespace to serialize and deserialize to and from JavaScript Object Notation (JSON). If you're porting existing code from `Newtonsoft.Json`, see [How to migrate to `System.Text.Json`](system-text-json-migrate-from-newtonsoft-how-to.md). The directions and sample code use the library directly, not through a framework such as [ASP.NET Core](/aspnet/core/). Most of the serialization sample code sets to `true` to "pretty-print" the JSON (with indentation and whitespace for human readability). For production use, you would typically accept the default value of `false` for this setting. +The code examples refer to the following class and variants of it: + +[!code-csharp[](~/samples/snippets/core/system-text-json/csharp/WeatherForecast.cs?name=SnippetWF)] + ## Namespaces The namespace contains all the entry points and the main types. The namespace contains attributes and APIs for advanced scenarios and customization specific to serialization and deserialization. The code examples shown in this article require `using` directives for one or both of these namespaces: From 75401a6bdbdad87252b648aafbaa88983c2b4671 Mon Sep 17 00:00:00 2001 From: Tom Dykstra Date: Thu, 23 Apr 2020 13:22:02 -0700 Subject: [PATCH 14/18] Fix code error (#18040) --- docs/standard/memory-and-spans/memory-t-usage-guidelines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/standard/memory-and-spans/memory-t-usage-guidelines.md b/docs/standard/memory-and-spans/memory-t-usage-guidelines.md index 20d85060222a5..ac423069b8bf8 100644 --- a/docs/standard/memory-and-spans/memory-t-usage-guidelines.md +++ b/docs/standard/memory-and-spans/memory-t-usage-guidelines.md @@ -330,7 +330,7 @@ public unsafe Task ManagedWrapperAsync(Memory data) private static void MyCompletedCallbackImplementation(IntPtr state, int result) { GCHandle handle = (GCHandle)state; - var actualState = (MyCompletedCallbackState)state; + var actualState = (MyCompletedCallbackState)(handle.Target); handle.Free(); actualState.MemoryHandle.Dispose(); From 1d7305af1733162ab3702d23ec7c2439b1c1dce2 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 23 Apr 2020 16:42:07 -0400 Subject: [PATCH 15/18] Add nested loops (#18039) * Add nested loops The beginner loops tutorial does not contain any examples of nested loops. Add a beginner example to both the interactive and local versions. Fixes #17208 * fix markdown lint error * fix variable name * Apply suggestions from code review Co-Authored-By: Petr Kulikov * Apply suggestions from code review Co-Authored-By: Tom Dykstra Co-authored-by: Petr Kulikov Co-authored-by: Tom Dykstra --- .../branches-and-loops-local.md | 36 +++++++++++++++++ .../intro-to-csharp/branches-and-loops.yml | 40 +++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/docs/csharp/tutorials/intro-to-csharp/branches-and-loops-local.md b/docs/csharp/tutorials/intro-to-csharp/branches-and-loops-local.md index a489d95525ef9..3bf2b130268b1 100644 --- a/docs/csharp/tutorials/intro-to-csharp/branches-and-loops-local.md +++ b/docs/csharp/tutorials/intro-to-csharp/branches-and-loops-local.md @@ -276,6 +276,42 @@ Experiment with these yourself. Try each of the following: When you're done, let's move on to write some code yourself to use what you've learned. +## Created nested loops + +A `while`, `do` or `for` loop can be nested inside another loop to create a matrix using the combination of each item in the outer loop with each item in the inner loop. Let's do that to build a set of alphanumeric pairs to represent rows and columns. + +One `for` loop can generate the rows: + +```csharp +for (int row = 1; row < 11; row++) +{ + Console.WriteLine($"The row is {row}"); +} +``` + +Another loop can generate the columns: + +```csharp +for (char column = 'a'; column < 'k'; column++) +{ + Console.WriteLine($"The column is {column}"); +} +``` + +You can nest one loop inside the other to form pairs: + +```csharp +for (int row = 1; row < 11; row++) +{ + for (char column = 'a'; column < 'k'; column++) + { + Console.WriteLine($"The cell is ({row}, {column})"); + } +} +``` + +You can see that the outer loop increments once for each full run of the inner loop. Reverse the row and column nesting, and see the changes for yourself. + ## Combine branches and loops Now that you've seen the `if` statement and the looping diff --git a/docs/csharp/tutorials/intro-to-csharp/branches-and-loops.yml b/docs/csharp/tutorials/intro-to-csharp/branches-and-loops.yml index a107753d23efa..93a48cab84e15 100644 --- a/docs/csharp/tutorials/intro-to-csharp/branches-and-loops.yml +++ b/docs/csharp/tutorials/intro-to-csharp/branches-and-loops.yml @@ -237,6 +237,46 @@ items: > [!NOTE] > This online coding experience is in preview mode. If you encounter problems, please report them [on the dotnet/try repo](https://github.com/dotnet/try/issues). +- title: Created nested loops + durationInMinutes: 10 + content: | + A `while`, `do` or `for` loop can be nested inside another loop to create a matrix + using the combination of each item in the outer loop with each item in the inner + loop. Let's do that to build a set of alphanumeric pairs to represent rows and columns. + + One `for` loop can generate the rows: + + ```csharp + for (int row = 1; row < 11; row++) + { + Console.WriteLine($"The row is {row}"); + } + ``` + + Another loop can generate the columns: + + ```csharp + for (char column = 'a'; column < 'k'; column++) + { + Console.WriteLine($"The column is {column}"); + } + ``` + + You can nest one loop inside the other to form pairs: + + ```csharp + for (int row = 1; row < 11; row++) + { + for (char column = 'a'; column < 'k'; column++) + { + Console.WriteLine($"The cell is ({row}, {column})"); + } + } + ``` + + You can see that the outer loop increments once for each full run of the + inner loop. Reverse the row and column nesting, and see the changes for yourself. + - title: Combine branches and loops durationInMinutes: 12 content: | From a4ad7cc6ae843c70ad0451ca054eb05a340d661c Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 23 Apr 2020 17:43:58 -0400 Subject: [PATCH 16/18] clarify boxing conversions (#18044) * clarify boxing conversionsq Fixes #17335 The original explanation implied that value types aren't objects. Modify the language in the two paragraphs on boxing and unboxing. The new language should suggest that value types are being assigned to object references, not converted. * Update docs/csharp/tour-of-csharp/types-and-variables.md Co-Authored-By: Tom Dykstra * clarify wording on "box" Co-authored-by: Tom Dykstra --- docs/csharp/tour-of-csharp/types-and-variables.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/csharp/tour-of-csharp/types-and-variables.md b/docs/csharp/tour-of-csharp/types-and-variables.md index d8fa226e78230..161387fd572d3 100644 --- a/docs/csharp/tour-of-csharp/types-and-variables.md +++ b/docs/csharp/tour-of-csharp/types-and-variables.md @@ -78,9 +78,9 @@ C#’s type system is unified such that a value of any type can be treated as an [!code-csharp[Boxing](../../../samples/snippets/csharp/tour/types-and-variables/Program.cs#L1-L10)] -When a value of a value type is converted to type `object`, an `object` instance, also called a "box", is allocated to hold the value, and the value is copied into that box. Conversely, when an `object` reference is cast to a value type, a check is made that the referenced `object` is a box of the correct value type, and, if the check succeeds, the value in the box is copied out. +When a value of a value type is assigned to an `object` reference, a "box" is allocated to hold the value. That box is an instance of a reference type, and the value is copied into that box. Conversely, when an `object` reference is cast to a value type, a check is made that the referenced `object` is a box of the correct value type. If the check succeeds, the value in the box is copied to the value type. -C#’s unified type system effectively means that value types can become objects "on demand." Because of the unification, general-purpose libraries that use type `object` can be used with both reference types and value types. +C#’s unified type system effectively means that value types are treated as `object` references "on demand." Because of the unification, general-purpose libraries that use type `object` can be used with all types that derive from `object`, including both reference types and value types. There are several kinds of *variables* in C#, including fields, array elements, local variables, and parameters. Variables represent storage locations, and every variable has a type that determines what values can be stored in the variable, as shown below. From 096cef22825da296682f460f6b81064a0ad03086 Mon Sep 17 00:00:00 2001 From: Genevieve Warren Date: Thu, 23 Apr 2020 15:14:05 -0700 Subject: [PATCH 17/18] Code fence APIs for wrapping (#18046) * code fence apis --- .../aspnetcore/3.0/obsolete-apis-removed.md | 134 +++++++++--------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/includes/core-changes/aspnetcore/3.0/obsolete-apis-removed.md b/includes/core-changes/aspnetcore/3.0/obsolete-apis-removed.md index b88e33048ed0d..7a80149f9bdeb 100644 --- a/includes/core-changes/aspnetcore/3.0/obsolete-apis-removed.md +++ b/includes/core-changes/aspnetcore/3.0/obsolete-apis-removed.md @@ -24,86 +24,86 @@ The following types and members were marked as obsolete for ASP.NET Core 2.1 and **Types** -- Microsoft.AspNetCore.Diagnostics.Views.WelcomePage -- Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue -- Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView -- Microsoft.AspNetCore.DiagnosticsViewPage.Views.HelperResult -- Microsoft.AspNetCore.Mvc.Formatters.Xml.ProblemDetails21Wrapper -- Microsoft.AspNetCore.Mvc.Formatters.Xml.ValidationProblemDetails21Wrapper -- Microsoft.AspNetCore.Mvc.Razor.Compilation.ViewsFeatureProvider -- Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageArgumentBinder -- Microsoft.AspNetCore.Routing.IRouteValuesAddressMetadata -- Microsoft.AspNetCore.Routing.RouteValuesAddressMetadata +- `Microsoft.AspNetCore.Diagnostics.Views.WelcomePage` +- `Microsoft.AspNetCore.DiagnosticsViewPage.Views.AttributeValue` +- `Microsoft.AspNetCore.DiagnosticsViewPage.Views.BaseView` +- `Microsoft.AspNetCore.DiagnosticsViewPage.Views.HelperResult` +- `Microsoft.AspNetCore.Mvc.Formatters.Xml.ProblemDetails21Wrapper` +- `Microsoft.AspNetCore.Mvc.Formatters.Xml.ValidationProblemDetails21Wrapper` +- `Microsoft.AspNetCore.Mvc.Razor.Compilation.ViewsFeatureProvider` +- `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageArgumentBinder` +- `Microsoft.AspNetCore.Routing.IRouteValuesAddressMetadata` +- `Microsoft.AspNetCore.Routing.RouteValuesAddressMetadata` **Constructors** -- Microsoft.AspNetCore.Cors.Infrastructure.CorsService(Microsoft.Extensions.Options.IOptions{Microsoft.AspNetCore.Cors.Infrastructure.CorsOptions}) -- Microsoft.AspNetCore.Routing.Tree.TreeRouteBuilder(Microsoft.Extensions.Logging.ILoggerFactory,System.Text.Encodings.Web.UrlEncoder,Microsoft.Extensions.ObjectPool.ObjectPool{Microsoft.AspNetCore.Routing.Internal.UriBuildingContext},Microsoft.AspNetCore.Routing.IInlineConstraintResolver) -- Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext -- Microsoft.AspNetCore.Mvc.ApiExplorer.DefaultApiDescriptionProvider(Microsoft.Extensions.Options.IOptions{Microsoft.AspNetCore.Mvc.MvcOptions},Microsoft.AspNetCore.Routing.IInlineConstraintResolver,Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider) -- Microsoft.AspNetCore.Mvc.ApiExplorer.DefaultApiDescriptionProvider(Microsoft.Extensions.Options.IOptions{Microsoft.AspNetCore.Mvc.MvcOptions},Microsoft.AspNetCore.Routing.IInlineConstraintResolver,Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider,Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultTypeMapper) -- Microsoft.AspNetCore.Mvc.Formatters.FormatFilter(Microsoft.Extensions.Options.IOptions{Microsoft.AspNetCore.Mvc.MvcOptions}) -- Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ArrayModelBinder`1(Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder) -- Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ByteArrayModelBinder +- `Microsoft.AspNetCore.Cors.Infrastructure.CorsService(IOptions{CorsOptions})` +- `Microsoft.AspNetCore.Routing.Tree.TreeRouteBuilder(ILoggerFactory,UrlEncoder,ObjectPool{UriBuildingContext},IInlineConstraintResolver)` +- `Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext` +- `Microsoft.AspNetCore.Mvc.ApiExplorer.DefaultApiDescriptionProvider(IOptions{MvcOptions},IInlineConstraintResolver,IModelMetadataProvider)` +- `Microsoft.AspNetCore.Mvc.ApiExplorer.DefaultApiDescriptionProvider(IOptions{MvcOptions},IInlineConstraintResolver,IModelMetadataProvider,IActionResultTypeMapper)` +- `Microsoft.AspNetCore.Mvc.Formatters.FormatFilter(IOptions{MvcOptions})` +- ``Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ArrayModelBinder`1(IModelBinder)`` +- `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ByteArrayModelBinder` - [Microsoft.AspNetCore.Mvc.ModelBinding.Binders.CollectionModelBinder`1(IModelBinder)](https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.mvc.modelbinding.binders.collectionmodelbinder-1.-ctor?view=aspnetcore-2.2#Microsoft_AspNetCore_Mvc_ModelBinding_Binders_CollectionModelBinder_1__ctor_Microsoft_AspNetCore_Mvc_ModelBinding_IModelBinder_) - [Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder(IDictionary`2)](https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.mvc.modelbinding.binders.complextypemodelbinder.-ctor?view=aspnetcore-2.2#Microsoft_AspNetCore_Mvc_ModelBinding_Binders_ComplexTypeModelBinder__ctor_System_Collections_Generic_IDictionary_Microsoft_AspNetCore_Mvc_ModelBinding_ModelMetadata_Microsoft_AspNetCore_Mvc_ModelBinding_IModelBinder__) -- Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DictionaryModelBinder`2(Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder,Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder) -- Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DoubleModelBinder(System.Globalization.NumberStyles) -- Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FloatModelBinder(System.Globalization.NumberStyles) -- Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormCollectionModelBinder -- Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormFileModelBinder -- Microsoft.AspNetCore.Mvc.ModelBinding.Binders.HeaderModelBinder -- Microsoft.AspNetCore.Mvc.ModelBinding.Binders.KeyValuePairModelBinder`2(Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder,Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder) -- Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder(System.Type) -- Microsoft.AspNetCore.Mvc.ModelBinding.ModelAttributes(System.Collections.Generic.IEnumerable{System.Object}) -- Microsoft.AspNetCore.Mvc.ModelBinding.ModelAttributes(System.Collections.Generic.IEnumerable{System.Object},System.Collections.Generic.IEnumerable{System.Object}) -- Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactory(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider,Microsoft.Extensions.Options.IOptions{Microsoft.AspNetCore.Mvc.MvcOptions}) -- Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider,Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderFactory,Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IObjectModelValidator) +- ``Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DictionaryModelBinder`2(IModelBinder,IModelBinder)`` +- `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DoubleModelBinder(System.Globalization.NumberStyles)` +- `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FloatModelBinder(System.Globalization.NumberStyles)` +- `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormCollectionModelBinder` +- `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormFileModelBinder` +- `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.HeaderModelBinder` +- ``Microsoft.AspNetCore.Mvc.ModelBinding.Binders.KeyValuePairModelBinder`2(IModelBinder,IModelBinder)`` +- `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder(System.Type)` +- `Microsoft.AspNetCore.Mvc.ModelBinding.ModelAttributes(IEnumerable{System.Object})` +- `Microsoft.AspNetCore.Mvc.ModelBinding.ModelAttributes(IEnumerable{System.Object},IEnumerable{System.Object})` +- `Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactory(IModelMetadataProvider,IOptions{MvcOptions})` +- `Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder(IModelMetadataProvider,IModelBinderFactory,IObjectModelValidator)` - [Microsoft.AspNetCore.Mvc.Routing.KnownRouteValueConstraint()](https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.mvc.routing.knownroutevalueconstraint.-ctor?view=aspnetcore-2.2#Microsoft_AspNetCore_Mvc_Routing_KnownRouteValueConstraint__ctor) -- Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerInputFormatter -- Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerInputFormatter(System.Boolean) -- Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerInputFormatter(Microsoft.AspNetCore.Mvc.MvcOptions) -- Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter -- Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter(System.Boolean) -- Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter(Microsoft.AspNetCore.Mvc.MvcOptions) +- `Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerInputFormatter` +- `Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerInputFormatter(System.Boolean)` +- `Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerInputFormatter(MvcOptions)` +- `Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter` +- `Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter(System.Boolean)` +- `Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter(MvcOptions)` - [Microsoft.AspNetCore.Mvc.TagHelpers.ImageTagHelper(IHostingEnvironment,IMemoryCache,HtmlEncoder,IUrlHelperFactory)](https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.mvc.taghelpers.imagetaghelper.-ctor?view=aspnetcore-2.2#Microsoft_AspNetCore_Mvc_TagHelpers_ImageTagHelper__ctor_Microsoft_AspNetCore_Hosting_IHostingEnvironment_Microsoft_Extensions_Caching_Memory_IMemoryCache_System_Text_Encodings_Web_HtmlEncoder_Microsoft_AspNetCore_Mvc_Routing_IUrlHelperFactory_) -- Microsoft.AspNetCore.Mvc.TagHelpers.LinkTagHelper(Microsoft.AspNetCore.Hosting.IHostingEnvironment,Microsoft.Extensions.Caching.Memory.IMemoryCache,System.Text.Encodings.Web.HtmlEncoder,System.Text.Encodings.Web.JavaScriptEncoder,Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory) -- Microsoft.AspNetCore.Mvc.TagHelpers.ScriptTagHelper(Microsoft.AspNetCore.Hosting.IHostingEnvironment,Microsoft.Extensions.Caching.Memory.IMemoryCache,System.Text.Encodings.Web.HtmlEncoder,System.Text.Encodings.Web.JavaScriptEncoder,Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory) -- Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAdapter(Microsoft.AspNetCore.Mvc.Razor.RazorPageBase) +- `Microsoft.AspNetCore.Mvc.TagHelpers.LinkTagHelper(IHostingEnvironment,IMemoryCache,HtmlEncoder,JavaScriptEncoder,IUrlHelperFactory)` +- `Microsoft.AspNetCore.Mvc.TagHelpers.ScriptTagHelper(IHostingEnvironment,IMemoryCache,HtmlEncoder,JavaScriptEncoder,IUrlHelperFactory)` +- `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAdapter(RazorPageBase)` **Properties** -- Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.CookieDomain -- Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.CookieName -- Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.CookiePath -- Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.RequireSsl -- Microsoft.AspNetCore.Mvc.ApiBehaviorOptions.AllowInferringBindingSourceForCollectionTypesAsFromQuery -- Microsoft.AspNetCore.Mvc.ApiBehaviorOptions.SuppressUseValidationProblemDetailsForInvalidModelStateResponses -- Microsoft.AspNetCore.Mvc.CookieTempDataProviderOptions.CookieName -- Microsoft.AspNetCore.Mvc.CookieTempDataProviderOptions.Domain -- Microsoft.AspNetCore.Mvc.CookieTempDataProviderOptions.Path -- Microsoft.AspNetCore.Mvc.DataAnnotations.MvcDataAnnotationsLocalizationOptions.AllowDataAnnotationsLocalizationForEnumDisplayAttributes -- Microsoft.AspNetCore.Mvc.Formatters.Xml.MvcXmlOptions.AllowRfc7807CompliantProblemDetailsFormat -- Microsoft.AspNetCore.Mvc.MvcOptions.AllowBindingHeaderValuesToNonStringModelTypes -- Microsoft.AspNetCore.Mvc.MvcOptions.AllowCombiningAuthorizeFilters -- Microsoft.AspNetCore.Mvc.MvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent -- Microsoft.AspNetCore.Mvc.MvcOptions.AllowValidatingTopLevelNodes -- Microsoft.AspNetCore.Mvc.MvcOptions.InputFormatterExceptionPolicy -- Microsoft.AspNetCore.Mvc.MvcOptions.SuppressBindingUndefinedValueToEnumType -- Microsoft.AspNetCore.Mvc.MvcViewOptions.AllowRenderingMaxLengthAttribute -- Microsoft.AspNetCore.Mvc.MvcViewOptions.SuppressTempDataAttributePrefix -- Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions.AllowAreas -- Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions.AllowDefaultHandlingForOptionsRequests -- Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions.AllowMappingHeadRequestsToGetHandler +- `Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.CookieDomain` +- `Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.CookieName` +- `Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.CookiePath` +- `Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.RequireSsl` +- `Microsoft.AspNetCore.Mvc.ApiBehaviorOptions.AllowInferringBindingSourceForCollectionTypesAsFromQuery` +- `Microsoft.AspNetCore.Mvc.ApiBehaviorOptions.SuppressUseValidationProblemDetailsForInvalidModelStateResponses` +- `Microsoft.AspNetCore.Mvc.CookieTempDataProviderOptions.CookieName` +- `Microsoft.AspNetCore.Mvc.CookieTempDataProviderOptions.Domain` +- `Microsoft.AspNetCore.Mvc.CookieTempDataProviderOptions.Path` +- `Microsoft.AspNetCore.Mvc.DataAnnotations.MvcDataAnnotationsLocalizationOptions.AllowDataAnnotationsLocalizationForEnumDisplayAttributes` +- `Microsoft.AspNetCore.Mvc.Formatters.Xml.MvcXmlOptions.AllowRfc7807CompliantProblemDetailsFormat` +- `Microsoft.AspNetCore.Mvc.MvcOptions.AllowBindingHeaderValuesToNonStringModelTypes` +- `Microsoft.AspNetCore.Mvc.MvcOptions.AllowCombiningAuthorizeFilters` +- `Microsoft.AspNetCore.Mvc.MvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent` +- `Microsoft.AspNetCore.Mvc.MvcOptions.AllowValidatingTopLevelNodes` +- `Microsoft.AspNetCore.Mvc.MvcOptions.InputFormatterExceptionPolicy` +- `Microsoft.AspNetCore.Mvc.MvcOptions.SuppressBindingUndefinedValueToEnumType` +- `Microsoft.AspNetCore.Mvc.MvcViewOptions.AllowRenderingMaxLengthAttribute` +- `Microsoft.AspNetCore.Mvc.MvcViewOptions.SuppressTempDataAttributePrefix` +- `Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions.AllowAreas` +- `Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions.AllowDefaultHandlingForOptionsRequests` +- `Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions.AllowMappingHeadRequestsToGetHandler` **Methods** -- Microsoft.AspNetCore.Mvc.LocalRedirectResult.ExecuteResult(Microsoft.AspNetCore.Mvc.ActionContext) -- Microsoft.AspNetCore.Mvc.RedirectResult.ExecuteResult(Microsoft.AspNetCore.Mvc.ActionContext) -- Microsoft.AspNetCore.Mvc.RedirectToActionResult.ExecuteResult(Microsoft.AspNetCore.Mvc.ActionContext) -- Microsoft.AspNetCore.Mvc.RedirectToPageResult.ExecuteResult(Microsoft.AspNetCore.Mvc.ActionContext) -- Microsoft.AspNetCore.Mvc.RedirectToRouteResult.ExecuteResult(Microsoft.AspNetCore.Mvc.ActionContext) -- Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(Microsoft.AspNetCore.Mvc.ActionContext,Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider,Microsoft.AspNetCore.Mvc.Abstractions.ParameterDescriptor) +- `Microsoft.AspNetCore.Mvc.LocalRedirectResult.ExecuteResult(ActionContext)` +- `Microsoft.AspNetCore.Mvc.RedirectResult.ExecuteResult(ActionContext)` +- `Microsoft.AspNetCore.Mvc.RedirectToActionResult.ExecuteResult(ActionContext)` +- `Microsoft.AspNetCore.Mvc.RedirectToPageResult.ExecuteResult(ActionContext)` +- `Microsoft.AspNetCore.Mvc.RedirectToRouteResult.ExecuteResult(ActionContext)` +- `Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext,IValueProvider,ParameterDescriptor)` - [Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext,IValueProvider,ParameterDescriptor,Object)](https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.mvc.modelbinding.parameterbinder.bindmodelasync?view=aspnetcore-2.2#Microsoft_AspNetCore_Mvc_ModelBinding_ParameterBinder_BindModelAsync_Microsoft_AspNetCore_Mvc_ActionContext_Microsoft_AspNetCore_Mvc_ModelBinding_IValueProvider_Microsoft_AspNetCore_Mvc_Abstractions_ParameterDescriptor_System_Object_)