diff --git a/aspnet/signalr/overview/testing-and-debugging/enabling-signalr-tracing/samples/sample3.xml b/aspnet/signalr/overview/testing-and-debugging/enabling-signalr-tracing/samples/sample3.xml index 4c9a835090..a49142c27a 100644 --- a/aspnet/signalr/overview/testing-and-debugging/enabling-signalr-tracing/samples/sample3.xml +++ b/aspnet/signalr/overview/testing-and-debugging/enabling-signalr-tracing/samples/sample3.xml @@ -1,8 +1,8 @@ - + - + - \ No newline at end of file + diff --git a/aspnetcore/data/ef-mvc/index.md b/aspnetcore/data/ef-mvc/index.md index 7661a84082..44b4d79b81 100644 --- a/aspnetcore/data/ef-mvc/index.md +++ b/aspnetcore/data/ef-mvc/index.md @@ -12,9 +12,7 @@ uid: data/ef-mvc/index --- # Getting started with ASP.NET Core MVC and Entity Framework Core using Visual Studio -Note: A Razor Pages version of this tutorial is available [here](xref:data/ef-rp/intro). The Razor Pages version is easier to follow and covers more EF features. - -This series of tutorials teaches you how to create ASP.NET Core MVC web applications that use Entity Framework Core for data access. The tutorials require Visual Studio 2017. +[!INCLUDE[RP better than MVC](../../includes/RP-EF/rp-over-mvc.md)] 1. [Getting started](intro.md) 2. [Create, Read, Update, and Delete operations](crud.md) diff --git a/aspnetcore/data/ef-mvc/intro.md b/aspnetcore/data/ef-mvc/intro.md index 6b9a647344..219eb557e8 100644 --- a/aspnetcore/data/ef-mvc/intro.md +++ b/aspnetcore/data/ef-mvc/intro.md @@ -14,7 +14,7 @@ uid: data/ef-mvc/intro By [Tom Dykstra](https://github.com/tdykstra) and [Rick Anderson](https://twitter.com/RickAndMSFT) -A Razor Pages version of this tutorial is available [here](xref:data/ef-rp/intro). The Razor Pages version is easier to follow and covers more EF features. We recommend you follow the [Razor Pages version of this tutorial](xref:data/ef-rp/intro). +[!INCLUDE[RP better than MVC](../../includes/RP-EF/rp-over-mvc.md)] The Contoso University sample web application demonstrates how to create ASP.NET Core 2.0 MVC web applications using Entity Framework (EF) Core 2.0 and Visual Studio 2017. diff --git a/aspnetcore/data/ef-rp/concurrency.md b/aspnetcore/data/ef-rp/concurrency.md index ff84bc79a6..6280f8163b 100644 --- a/aspnetcore/data/ef-rp/concurrency.md +++ b/aspnetcore/data/ef-rp/concurrency.md @@ -193,7 +193,7 @@ Update *pages\departments\edit.cshtml.cs* with the following code: To detect a concurrency issue, the [OriginalValue](https://docs.microsoft.com/dotnet/api/microsoft.entityframeworkcore.changetracking.propertyentry.originalvalue?view=efcore-2.0#Microsoft_EntityFrameworkCore_ChangeTracking_PropertyEntry_OriginalValue) is updated with the `rowVersion` value from the entity it was fetched. EF Core generates a SQL UPDATE command with a WHERE clause containing the original `RowVersion` value. If no rows are affected by the UPDATE command (no rows have the original `RowVersion` value), a `DbUpdateConcurrencyException` exception is thrown. -[!code-csharp[](intro/samples/cu/Pages/Departments/Edit.cshtml.cs?name=snippet_rv&highlight=24-)] +[!code-csharp[](intro/samples/cu/Pages/Departments/Edit.cshtml.cs?name=snippet_rv&highlight=24-999)] In the preceding code, `Department.RowVersion` is the value when the entity was fetched. `OriginalValue` is the value in the DB when `FirstOrDefaultAsync` was called in this method. diff --git a/aspnetcore/data/ef-rp/read-related-data.md b/aspnetcore/data/ef-rp/read-related-data.md index 803687fb23..8fff291e63 100644 --- a/aspnetcore/data/ef-rp/read-related-data.md +++ b/aspnetcore/data/ef-rp/read-related-data.md @@ -175,7 +175,7 @@ Run the app and navigate to the instructors page. Replace *Pages/Instructors/Index.cshtml.cs* with the following code: -[!code-csharp[Main](intro/samples/cu/Pages/Instructors/Index1.cshtml.cs?name=snippet_all&highlight=2,20-)] +[!code-csharp[Main](intro/samples/cu/Pages/Instructors/Index1.cshtml.cs?name=snippet_all&highlight=2,20-99)] The `OnGetAsync` method accepts optional route data for the ID of the selected instructor. @@ -244,7 +244,7 @@ Click on the **Select** link. The row style changes. Update the `OnGetAsync` method in *Pages/Instructors/Index.cshtml.cs* with the following code: -[!code-csharp[Main](intro/samples/cu/Pages/Instructors/Index2.cshtml.cs?name=snippet_OnGetAsync&highlight=1,8,16-)] +[!code-csharp[Main](intro/samples/cu/Pages/Instructors/Index2.cshtml.cs?name=snippet_OnGetAsync&highlight=1,8,16-999)] Examine the updated query: @@ -271,7 +271,7 @@ The following code populates the view model's `Enrollments` property when a cour Add the following markup to the end of the *Pages/Courses/Index.cshtml* Razor Page: -[!code-html[](intro/samples/cu/Pages/Instructors/IndexRRD.cshtml?range=60-102&highlight=7-)] +[!code-html[](intro/samples/cu/Pages/Instructors/IndexRRD.cshtml?range=60-102&highlight=7-999)] The preceding markup displays a list of courses related to an instructor when an instructor is selected. diff --git a/aspnetcore/data/ef-rp/sort-filter-page.md b/aspnetcore/data/ef-rp/sort-filter-page.md index ae2712b8ad..26f8a59a68 100644 --- a/aspnetcore/data/ef-rp/sort-filter-page.md +++ b/aspnetcore/data/ef-rp/sort-filter-page.md @@ -65,7 +65,7 @@ These two statements enable the view to set the column heading hyperlinks as fol The method uses LINQ to Entities to specify the column to sort by. The code initializes an `IQueryable ` before the switch statement, and modifies it in the switch statement: -[!code-csharp[Main](intro/samples/cu/Pages/Students/Index.cshtml.cs?name=snippet_SortOnly&highlight=6-)] +[!code-csharp[Main](intro/samples/cu/Pages/Students/Index.cshtml.cs?name=snippet_SortOnly&highlight=6-999)] When an`IQueryable` is created or modified, no query is sent to the database. The query isn't executed until the `IQueryable` object is converted into a collection. `IQueryable` are converted to a collection by calling a method such as `ToListAsync`. Therefore, the `IQueryable` code results in a single query that's not executed until the following statement: @@ -174,7 +174,7 @@ In *Students/Index.cshtml.cs*, update the type of `Student` from `IList Update the *Students/Index.cshtml.cs* `OnGetAsync` with the following code: -[!code-csharp[Main](intro/samples/cu/Pages/Students/Index.cshtml.cs?name=snippet_SortFilterPage&highlight=1-4,7-14,41-)] +[!code-csharp[Main](intro/samples/cu/Pages/Students/Index.cshtml.cs?name=snippet_SortFilterPage&highlight=1-4,7-14,41-999)] The preceding code adds the page index, the current `sortOrder`, and the `currentFilter` to the method signature. @@ -211,7 +211,7 @@ The two question marks in `PaginatedList.CreateAsync` represent the [null-coales Update the markup in *Students/Index.cshtml*. The changes are highlighted: -[!code-html[](intro/samples/cu/Pages/Students/Index.cshtml?highlight=28-31,37-40,68-)] +[!code-html[](intro/samples/cu/Pages/Students/Index.cshtml?highlight=28-31,37-40,68-999)] The column header links use the query string to pass the current search string to the `OnGetAsync` method so that the user can sort within filter results: diff --git a/aspnetcore/data/ef-rp/update-related-data.md b/aspnetcore/data/ef-rp/update-related-data.md index 0cb39a7073..a3a1753a3c 100644 --- a/aspnetcore/data/ef-rp/update-related-data.md +++ b/aspnetcore/data/ef-rp/update-related-data.md @@ -44,7 +44,7 @@ When a new course entity is created, it must have a relationship to an existing Update the Create page model with the following code: -[!code-csharp[Main](intro/samples/cu/Pages/Courses/Create.cshtml.cs?highlight=7,18,32-)] +[!code-csharp[Main](intro/samples/cu/Pages/Courses/Create.cshtml.cs?highlight=7,18,32-999)] The preceding code: @@ -77,7 +77,7 @@ Test the Create page. The Create page displays the department name rather than t Update the edit page model with the following code: -[!code-csharp[Main](intro/samples/cu/Pages/Courses/Edit.cshtml.cs?highlight=8,28,35,36,40,47-)] +[!code-csharp[Main](intro/samples/cu/Pages/Courses/Edit.cshtml.cs?highlight=8,28,35,36,40,47-999)] The changes are similar to those made in the Create page model. In the preceding code, `PopulateDepartmentsDropDownList` passes in the department ID, which select the department specified in the drop-down list. @@ -133,7 +133,7 @@ When editing an instructor record, you may want to update the instructor's offic Update the instructors Edit page model with the following code: -[!code-csharp[Main](intro/samples/cu/Pages/Instructors/Edit1.cshtml.cs?name=snippet&highlight=20-23,32,39-)] +[!code-csharp[Main](intro/samples/cu/Pages/Instructors/Edit1.cshtml.cs?name=snippet&highlight=20-23,32,39-999)] The preceding code: @@ -180,7 +180,7 @@ The `InstructorCoursesPageModel` is the base class you will use for the Edit and Update the instructor Edit page model with the following code: -[!code-csharp[Main](intro/samples/cu/Pages/Instructors/Edit.cshtml.cs?name=snippet&highlight=1,20-24,30,34,41-)] +[!code-csharp[Main](intro/samples/cu/Pages/Instructors/Edit.cshtml.cs?name=snippet&highlight=1,20-24,30,34,41-999)] The preceding code handles office assignment changes. @@ -218,7 +218,7 @@ Test the instructor Create page. Update the Delete page model with the following code: -[!code-csharp[Main](intro/samples/cu/Pages/Instructors/Delete.cshtml.cs?highlight=5,40-)] +[!code-csharp[Main](intro/samples/cu/Pages/Instructors/Delete.cshtml.cs?highlight=5,40-999)] The preceding code makes the following changes: diff --git a/aspnetcore/host-and-deploy/azure-apps/troubleshoot.md b/aspnetcore/host-and-deploy/azure-apps/troubleshoot.md index dacb80e4f4..d628683dda 100644 --- a/aspnetcore/host-and-deploy/azure-apps/troubleshoot.md +++ b/aspnetcore/host-and-deploy/azure-apps/troubleshoot.md @@ -22,7 +22,7 @@ This article provides instructions on how to diagnose an ASP.NET Core app startu **502.5 Process Failure** The worker process fails. The app doesn't start. -The [ASP.NET Core Module](xref:fundamentals/servers/aspnet-core-module) attempts to start the worker process but it fails to start. Examining the Application Event Log often helps troubleshoot this type of problem. Accessing the log is explained in the [Event log](#event-log) section. +The [ASP.NET Core Module](xref:fundamentals/servers/aspnet-core-module) attempts to start the worker process but it fails to start. Examining the Application Event Log often helps troubleshoot this type of problem. Accessing the log is explained in the [Application Event Log](#application-event-log) section. The *502.5 Process Failure* error page is returned when a misconfigured app causes the worker process to fail: diff --git a/aspnetcore/includes/RP-EF/rp-over-mvc.md b/aspnetcore/includes/RP-EF/rp-over-mvc.md new file mode 100644 index 0000000000..22f78cb55b --- /dev/null +++ b/aspnetcore/includes/RP-EF/rp-over-mvc.md @@ -0,0 +1,8 @@ +This tutorial teaches ASP.NET Core MVC and Entity Framework Core with controllers and views. Razor Pages is a new alternative in ASP.NET Core 2.0, a page-based programming model that makes building web UI easier and more productive. We recommend the [Razor Pages](xref:data/ef-rp/intro) tutorial over the MVC version. The Razor Pages tutorial: + +* Is easier to follow. +* Provides more EF Core best practices. +* Uses more efficient queries. +* Is more current with the lastest API. +* Covers more features. +* Is the preferred approach for new application development. \ No newline at end of file diff --git a/aspnetcore/includes/RP/page1.md b/aspnetcore/includes/RP/page1.md index 0e3cc5bc88..d4e5b99416 100644 --- a/aspnetcore/includes/RP/page1.md +++ b/aspnetcore/includes/RP/page1.md @@ -67,13 +67,13 @@ The `@model` directive specifies the type of the model passed to the Razor Page. Consider the following code: -[!code-cshtml[Main](../../tutorials/razor-pages/razor-pages-start/snapshot_sample/RazorPagesMovie/Pages/Movies/Index.cshtml?range=1-6&highlight=4-)] +[!code-cshtml[Main](../../tutorials/razor-pages/razor-pages-start/snapshot_sample/RazorPagesMovie/Pages/Movies/Index.cshtml?range=1-6&highlight=4-999)] The preceding highlighted code is an example of Razor transitioning into C#. The `{` and `}` characters enclose a block of C# code. The `PageModel` base class has a `ViewData` dictionary property that can be used to add data that you want to pass to a View. You add objects into the `ViewData` dictionary using a key/value pattern. In the preceding sample, the "Title" property is added to the `ViewData` dictionary. The "Title" property is used in the *Pages/_Layout.cshtml* file. The following markup shows the first few lines of the *Pages/_Layout.cshtml* file. -[!code-cshtml[Main](../../tutorials/razor-pages/razor-pages-start/snapshot_sample/RazorPagesMovie/Pages/NU/_Layout1.cshtml?highlight=6-)] +[!code-cshtml[Main](../../tutorials/razor-pages/razor-pages-start/snapshot_sample/RazorPagesMovie/Pages/NU/_Layout1.cshtml?highlight=6-999)] The line `@*Markup removed for brevity.*@` is a Razor comment. Unlike HTML comments (``), Razor comments are not sent to the client. diff --git a/aspnetcore/includes/RP/search.md b/aspnetcore/includes/RP/search.md index 1f235f1444..d5e1a1dcaa 100644 --- a/aspnetcore/includes/RP/search.md +++ b/aspnetcore/includes/RP/search.md @@ -55,7 +55,7 @@ The HTML `
` tag uses the [Form Tag Helper](xref:mvc/views/working-with-for Add the the following highlighted properties to *Pages/Movies/Index.cshtml.cs*: -[!code-csharp[Main](../../tutorials/razor-pages/razor-pages-start/sample/RazorPagesMovie/Pages/Movies/Index.cshtml.cs?name=snippet_newProps&highlight=11-)] +[!code-csharp[Main](../../tutorials/razor-pages/razor-pages-start/sample/RazorPagesMovie/Pages/Movies/Index.cshtml.cs?name=snippet_newProps&highlight=11-999)] The `SelectList Genres` contains the list of genres. This allows the user to select a genre from the list. diff --git a/aspnetcore/index.md b/aspnetcore/index.md index bda7981fd2..e83ab10958 100644 --- a/aspnetcore/index.md +++ b/aspnetcore/index.md @@ -10,7 +10,7 @@ ms.technology: aspnet ms.topic: article uid: index --- -# Introduction to ASP.NET Core +# ASP.NET Core By [Daniel Roth](https://github.com/danroth27), [Rick Anderson](https://twitter.com/RickAndMSFT), and [Shaun Luttin](https://twitter.com/dicshaunary) diff --git a/aspnetcore/mvc/views/tag-helpers/authoring.md b/aspnetcore/mvc/views/tag-helpers/authoring.md index c462e7c858..b935c09663 100644 --- a/aspnetcore/mvc/views/tag-helpers/authoring.md +++ b/aspnetcore/mvc/views/tag-helpers/authoring.md @@ -221,7 +221,7 @@ You can also use the `[HtmlTargetElement]` to change the name of the targeted el 4. Add the following markup to the *About.cshtml* view. The highlighted markup displays the web site information. - [!code-html[Main](authoring/sample/AuthoringTagHelpers/src/AuthoringTagHelpers/Views/Home/About.cshtml?highlight=1,12-)] + [!code-html[Main](authoring/sample/AuthoringTagHelpers/src/AuthoringTagHelpers/Views/Home/About.cshtml?highlight=1,12-999)] >[!NOTE] > In the Razor markup shown below: diff --git a/aspnetcore/performance/caching/memory.md b/aspnetcore/performance/caching/memory.md index 506c7eedb7..603a8e34c8 100644 --- a/aspnetcore/performance/caching/memory.md +++ b/aspnetcore/performance/caching/memory.md @@ -37,7 +37,7 @@ In-memory caching is a *service* that's referenced from your app using [Dependen Request the `IMemoryCache` instance in the constructor: -[!code-csharp[Main](memory/sample/WebCache/Controllers/HomeController.cs?name=snippet_ctor&highlight=3,5-)] +[!code-csharp[Main](memory/sample/WebCache/Controllers/HomeController.cs?name=snippet_ctor&highlight=3,5-999)] `IMemoryCache` requires NuGet package "Microsoft.Extensions.Caching.Memory". diff --git a/aspnetcore/security/authentication/identity-enable-qrcodes.md b/aspnetcore/security/authentication/identity-enable-qrcodes.md index 683b82c1dc..79f760817e 100644 --- a/aspnetcore/security/authentication/identity-enable-qrcodes.md +++ b/aspnetcore/security/authentication/identity-enable-qrcodes.md @@ -83,8 +83,6 @@ The correctly formatted URL for the QR Code is available in the: * `AuthenticatorUri` property of the model. * `data-url` property in the `qrCodeData` element. -Use `@Html.Raw` to access the model property in a view (otherwise the ampersands in the url will be double encoded and the label parameter of the QR Code will be ignored). - ## TOTP client and server time skew TOTP authentication depends on both the server and authenticator device having an accurate time. Tokens only last for 30 seconds. If TOTP 2FA logins are failing, check that the server time is accurate, and preferably synchronized to an accurate NTP service. diff --git a/aspnetcore/security/authorization/claims.md b/aspnetcore/security/authorization/claims.md index e7637bd982..cecbf56c56 100644 --- a/aspnetcore/security/authorization/claims.md +++ b/aspnetcore/security/authorization/claims.md @@ -14,7 +14,7 @@ uid: security/authorization/claims -When an identity is created it may be assigned one or more claims issued by a trusted party. A claim is name value pair that represents what the subject is, not what the subject can do. For example, you may have a driver's license, issued by a local driving license authority. Your driver's license has your date of birth on it. In this case the claim name would be `DateOfBirth`, the claim value would be your date of birth, for example `8th June 1970` and the issuer would be the driving license authority. Claims based authorization, at its simplest, checks the value of a claim and allows access to a resource based upon that value. For example if you want access to a night club the authorization process might be: +When an identity is created it may be assigned one or more claims issued by a trusted party. A claim is a name value pair that represents what the subject is, not what the subject can do. For example, you may have a driver's license, issued by a local driving license authority. Your driver's license has your date of birth on it. In this case the claim name would be `DateOfBirth`, the claim value would be your date of birth, for example `8th June 1970` and the issuer would be the driving license authority. Claims based authorization, at its simplest, checks the value of a claim and allows access to a resource based upon that value. For example if you want access to a night club the authorization process might be: The door security officer would evaluate the value of your date of birth claim and whether they trust the issuer (the driving license authority) before granting you access. diff --git a/aspnetcore/security/authorization/secure-data.md b/aspnetcore/security/authorization/secure-data.md index d4b552100b..b91df9e69f 100644 --- a/aspnetcore/security/authorization/secure-data.md +++ b/aspnetcore/security/authorization/secure-data.md @@ -61,7 +61,7 @@ This tutorial is advanced. You should be familiar with: * [Authorization](xref:security/authorization/index) * [Entity Framework Core](xref:data/ef-mvc/intro) -The ASP.NET Core 1.1 version of this tutorial is in [this](https://github.com/aspnet/Docs/tree/master/aspnetcore/security/authorization/secure-data) folder. The 1.1 ASP.NET Core sample is in the [samples](https://github.com/aspnet/Docs/tree/master/aspnetcore/security/authorization/secure-data/samples/final2). +See [this PDF file](https://github.com/aspnet/Docs/tree/master/aspnetcore/security/authorization/secure-data/asp.net_repo_pdf_1-16-18.pdf) for the ASP.NET Core MVC version. The ASP.NET Core 1.1 version of this tutorial is in [this](https://github.com/aspnet/Docs/tree/master/aspnetcore/security/authorization/secure-data) folder. The 1.1 ASP.NET Core sample is in the [samples](https://github.com/aspnet/Docs/tree/master/aspnetcore/security/authorization/secure-data/samples/final2). ## The starter and completed app @@ -81,7 +81,7 @@ The following sections have all the major steps to create the secure user data a Use the ASP.NET [Identity](xref:security/authentication/identity) user ID to ensure users can edit their data, but not other users data. Add `OwnerID` and `ContactStatus` to the `Contact` model: -[!code-csharp[Main](secure-data/samples/final2/Models/Contact.cs?name=snippet1&highlight=5-6,16-)] +[!code-csharp[Main](secure-data/samples/final2/Models/Contact.cs?name=snippet1&highlight=5-6,16-999)] `OwnerID` is the user's ID from the `AspNetUser` table in the [Identity](xref:security/authentication/identity) database. The `Status` field determines if a contact is viewable by general users. @@ -100,7 +100,7 @@ Add [IHostingEnvironment](/dotnet/api/microsoft.aspnetcore.hosting.ihostingenvir In the `ConfigureServices` method of the *Startup.cs* file, add the [RequireHttpsAttribute](/aspnet/core/api/microsoft.aspnetcore.mvc.requirehttpsattribute) authorization filter: -[!code-csharp[Main](secure-data/samples/final2/Startup.cs?name=snippet_SSL&highlight=19-)] +[!code-csharp[Main](secure-data/samples/final2/Startup.cs?name=snippet_SSL&highlight=19-999)] If you're using Visual Studio, enable SSL. @@ -112,7 +112,7 @@ To redirect HTTP requests to HTTPS, see [URL Rewriting Middleware](xref:fundamen Set the default authentication policy to require users to be authenticated. You can opt out of authentication at the Razor Page, controller, or action method level with the `[AllowAnonymous]` attribute. Setting the default authentication policy to require users to be authenticated protects newly added Razor Pages and controllers. Having authentication required by default is safer than relying on new controllers and Razor Pages to include the `[Authorize]` attribute. Add the following to the `ConfigureServices` method of the *Startup.cs* file: -[!code-csharp[Main](secure-data/samples/final2/Startup.cs?name=snippet_defaultPolicy&highlight=31-)] +[!code-csharp[Main](secure-data/samples/final2/Startup.cs?name=snippet_defaultPolicy&highlight=31-999)] Add [AllowAnonymous](/dotnet/api/microsoft.aspnetcore.authorization.allowanonymousattribute) to the Index, About, and Contact pages so anonymous users can get information about the site before they register. @@ -173,7 +173,7 @@ Create a `ContactAdministratorsAuthorizationHandler` class in the *Authorization Services using Entity Framework Core must be registered for [dependency injection](xref:fundamentals/dependency-injection) using [AddScoped](/aspnet/core/api/microsoft.extensions.dependencyinjection.servicecollectionserviceextensions). The `ContactIsOwnerAuthorizationHandler` uses ASP.NET Core [Identity](xref:security/authentication/identity), which is built on Entity Framework Core. Register the handlers with the service collection so they're available to the `ContactsController` through [dependency injection](xref:fundamentals/dependency-injection). Add the following code to the end of `ConfigureServices`: -[!code-csharp[Main](secure-data/samples/final2/Startup.cs?name=ConfigureServices&highlight=41-)] +[!code-csharp[Main](secure-data/samples/final2/Startup.cs?name=ConfigureServices&highlight=41-999)] `ContactAdministratorsAuthorizationHandler` and `ContactManagerAuthorizationHandler` are added as singletons. They're singletons because they don't use EF and all the information needed is in the `Context` parameter of the `HandleRequirementAsync` method. @@ -242,7 +242,7 @@ The preceding markup adds several `using` statements. Update the **Edit** and **Delete** links in *Pages/Contacts/Index.cshtml* so they're only rendered for users with the appropriate permissions: -[!code-cshtml[Main](secure-data/samples/final2/Pages/Contacts/Index.cshtml?highlight=34-36,64-)] +[!code-cshtml[Main](secure-data/samples/final2/Pages/Contacts/Index.cshtml?highlight=34-36,64-999)] > [!WARNING] > Hiding links from users that don't have permission to change data doesn't secure the app. Hiding links makes the app more user-friendly by displaying only valid links. Users can hack the generated URLs to invoke edit and delete operations on data they don't own. The Razor Page or controller must enforce access checks to secure the data. @@ -251,7 +251,7 @@ Update the **Edit** and **Delete** links in *Pages/Contacts/Index.cshtml* so the Update the details view so managers can approve or reject contacts: -[!code-cshtml[Main](secure-data/samples/final2/Pages/Contacts/Details.cshtml?range=48-)] +[!code-cshtml[Main](secure-data/samples/final2/Pages/Contacts/Details.cshtml?range=48-999)] Update the details page model: diff --git a/aspnetcore/security/enforcing-ssl.md b/aspnetcore/security/enforcing-ssl.md index 7849ea212d..ba672d3f56 100644 --- a/aspnetcore/security/enforcing-ssl.md +++ b/aspnetcore/security/enforcing-ssl.md @@ -25,11 +25,11 @@ The [RequireHttpsAttribute](https://docs.microsoft.com/aspnet/core/api/microsoft Add the following code to `ConfigureServices` in `Startup`: -[!code-csharp[Main](authentication/accconfirm/sample/WebApp1/Startup.cs?name=snippet2&highlight=4-)] +[!code-csharp[Main](authentication/accconfirm/sample/WebApp1/Startup.cs?name=snippet2&highlight=4-999)] The highlighted code above requires all requests use `HTTPS`, therefore HTTP requests are ignored. The following highlighted code redirects all HTTP requests to HTTPS: -[!code-csharp[Main](authentication/accconfirm/sample/WebApp1/Startup.cs?name=snippet_AddRedirectToHttps&highlight=7-)] +[!code-csharp[Main](authentication/accconfirm/sample/WebApp1/Startup.cs?name=snippet_AddRedirectToHttps&highlight=7-999)] See [URL Rewriting Middleware](xref:fundamentals/url-rewriting) for more information. diff --git a/aspnetcore/toc.md b/aspnetcore/toc.md index ff8d58b027..280e3abca8 100644 --- a/aspnetcore/toc.md +++ b/aspnetcore/toc.md @@ -27,6 +27,35 @@ ### [Add validation](tutorials/first-mvc-app/validation.md) ### [Examine the Details and Delete methods](tutorials/first-mvc-app/details.md) +## [Build Web APIs](mvc/web-api/index.md) +### [Create a Web API on Mac](xref:tutorials/first-web-api-mac) +### [ASP.NET Core Web API help pages using Swagger](tutorials/web-api-help-pages-using-swagger.md) +### [Create backend services for native mobile apps](mobile/native-mobile-backend.md) + +## [Data access - with EF Core](xref:data/index) +### [Data access - with Razor Pages and EF Core](xref:data/ef-rp/index) + +#### [Get started](xref:data/ef-rp/intro) +#### [Create, Read, Update, and Delete operations](xref:data/ef-rp/crud) +#### [Sort, filter, page, and group](xref:data/ef-rp/sort-filter-page) +#### [Migrations](xref:data/ef-rp/migrations) +#### [Create a complex data model](xref:data/ef-rp/complex-data-model) +#### [Read related data](xref:data/ef-rp/read-related-data) +#### [Update related data](xref:data/ef-rp/update-related-data) +#### [Handle concurrency conflicts](xref:data/ef-rp/concurrency) + +### [Data access - MVC with EF Core](data/ef-mvc/index.md) +#### [Get started](data/ef-mvc/intro.md) +#### [Create, Read, Update, and Delete operations](data/ef-mvc/crud.md) +#### [Sort, filter, page, and group](data/ef-mvc/sort-filter-page.md) +#### [Migrations](data/ef-mvc/migrations.md) +#### [Create a complex data model](data/ef-mvc/complex-data-model.md) +#### [Read related data](data/ef-mvc/read-related-data.md) +#### [Update related data](data/ef-mvc/update-related-data.md) +#### [Handle concurrency conflicts](data/ef-mvc/concurrency.md) +#### [Inheritance](data/ef-mvc/inheritance.md) +#### [Advanced topics](data/ef-mvc/advanced.md) + ## [Cross platform tutorials](xref:tutorials/xplat) ### [Razor Pages web app on a Mac](xref:tutorials/razor-pages-mac/index) #### [Getting started with Razor Pages](xref:tutorials/razor-pages-mac/razor-pages-start) @@ -71,33 +100,7 @@ ### [Web API with Visual Studio for Mac](xref:tutorials/first-web-api-mac) ### [Web API with Visual Studio Code](xref:tutorials/web-api-vsc) -## [Data access - Razor Pages with EF Core](xref:data/index) -### [Get started](xref:data/ef-rp/intro) -### [Create, Read, Update, and Delete operations](xref:data/ef-rp/crud) -### [Sort, filter, page, and group](xref:data/ef-rp/sort-filter-page) -### [Migrations](xref:data/ef-rp/migrations) -### [Create a complex data model](xref:data/ef-rp/complex-data-model) -### [Read related data](xref:data/ef-rp/read-related-data) -### [Update related data](xref:data/ef-rp/update-related-data) -### [Handle concurrency conflicts](xref:data/ef-rp/concurrency) - -## [Data access - MVC with EF Core](data/ef-mvc/index.md) -### [Get started](data/ef-mvc/intro.md) -### [Create, Read, Update, and Delete operations](data/ef-mvc/crud.md) -### [Sort, filter, page, and group](data/ef-mvc/sort-filter-page.md) -### [Migrations](data/ef-mvc/migrations.md) -### [Create a complex data model](data/ef-mvc/complex-data-model.md) -### [Read related data](data/ef-mvc/read-related-data.md) -### [Update related data](data/ef-mvc/update-related-data.md) -### [Handle concurrency conflicts](data/ef-mvc/concurrency.md) -### [Inheritance](data/ef-mvc/inheritance.md) -### [Advanced topics](data/ef-mvc/advanced.md) - ## [Create backend services for mobile apps](mobile/native-mobile-backend.md) -## [Build Web APIs](mvc/web-api/index.md) -## [Create a Web API](xref:tutorials/first-web-api-mac) -### [ASP.NET Core Web API help pages using Swagger](tutorials/web-api-help-pages-using-swagger.md) -### [Create backend services for native mobile apps](mobile/native-mobile-backend.md) # [Fundamentals](fundamentals/index.md) ## [Application startup](fundamentals/startup.md) @@ -178,9 +181,9 @@ ## [Snapshot debugging](/azure/application-insights/app-insights-snapshot-debugger) ## [Snapshot debugging in Visual Studio](/visualstudio/debugger/debug-live-azure-applications) -# [Data access and storage](data/index.md) -## [Get started with Razor Pages and Entity Framework Core using Visual Studio](xref:data/ef-rp/intro) -## [Get started with ASP.NET Core and Entity Framework Core using Visual Studio](data/ef-mvc/index.md) +# [Data access with EF Core and Azure](data/index.md) +## [Get started with Razor Pages and EF Core using Visual Studio](xref:data/ef-rp/intro) +## [Get started with ASP.NET Core and EF Core using Visual Studio](data/ef-mvc/index.md) ## [ASP.NET Core with EF Core - new database](https://docs.microsoft.com/ef/core/get-started/aspnetcore/new-db) ## [ASP.NET Core with EF Core - existing database](https://docs.microsoft.com/ef/core/get-started/aspnetcore/existing-db) ## [Get started with ASP.NET Core and Entity Framework 6](data/entity-framework-6.md) diff --git a/aspnetcore/tutorials/index.md b/aspnetcore/tutorials/index.md index 54b1efb552..6955882bb4 100644 --- a/aspnetcore/tutorials/index.md +++ b/aspnetcore/tutorials/index.md @@ -47,9 +47,10 @@ The following step-by-step guides for developing ASP.NET Core applications are a * [Create backend web services for native mobile apps](../mobile/native-mobile-backend.md) ## Data access and storage -* [Get started with ASP.NET Core and Entity Framework Core using Visual Studio](../data/ef-mvc/index.md) -* [ASP.NET Core with EF Core - new database](https://docs.microsoft.com/ef/core/get-started/aspnetcore/new-db) -* [ASP.NET Core with EF Core - existing database](https://docs.microsoft.com/ef/core/get-started/aspnetcore/existing-db) +* [Get started with Razor Pages and EF Core using Visual Studio](xref:data/ef-rp/intro) +* [Get started with ASP.NET Core MVC and EF Core using Visual Studio](../data/ef-mvc/index.md) +* [ASP.NET Core MVC with EF Core - new database](https://docs.microsoft.com/ef/core/get-started/aspnetcore/new-db) +* [ASP.NET Core MVC with EF Core - existing database](https://docs.microsoft.com/ef/core/get-started/aspnetcore/existing-db) ## Authentication and authorization * [Enable authentication using Facebook, Google, and other external providers](../security/authentication/social/index.md) diff --git a/aspnetcore/tutorials/razor-pages/search.md b/aspnetcore/tutorials/razor-pages/search.md index b0a73a4943..8bcd873dd2 100644 --- a/aspnetcore/tutorials/razor-pages/search.md +++ b/aspnetcore/tutorials/razor-pages/search.md @@ -65,7 +65,7 @@ The HTML `` tag uses the [Form Tag Helper](xref:mvc/views/working-with-for Add the the following highlighted properties to *Pages/Movies/Index.cshtml.cs*: -[!code-csharp[Main](razor-pages-start/sample/RazorPagesMovie/Pages/Movies/Index.cshtml.cs?name=snippet_newProps&highlight=11-)] +[!code-csharp[Main](razor-pages-start/sample/RazorPagesMovie/Pages/Movies/Index.cshtml.cs?name=snippet_newProps&highlight=11-999)] The `SelectList Genres` contains the list of genres. This allows the user to select a genre from the list. diff --git a/aspnetcore/tutorials/web-api-help-pages-using-swagger.md b/aspnetcore/tutorials/web-api-help-pages-using-swagger.md index 567c423eec..6f1086cf79 100644 --- a/aspnetcore/tutorials/web-api-help-pages-using-swagger.md +++ b/aspnetcore/tutorials/web-api-help-pages-using-swagger.md @@ -1,22 +1,20 @@ --- -title: ASP.NET Core Web API Help Pages using Swagger +title: ASP.NET Core Web API help pages using Swagger author: spboyer description: This tutorial provides a walkthrough of adding Swagger to generate documentation and help pages for a Web API application. manager: wpickett ms.author: spboyer -ms.date: 09/01/2017 +ms.date: 02/02/2018 ms.prod: asp.net-core ms.technology: aspnet ms.topic: article uid: tutorials/web-api-help-pages-using-swagger --- -# ASP.NET Core Web API Help Pages using Swagger - - +# ASP.NET Core Web API help pages using Swagger By [Shayne Boyer](https://twitter.com/spboyer) and [Scott Addie](https://twitter.com/Scott_Addie) -Understanding the various methods of an API can be a challenge for a developer when building a consuming application. +Understanding the various methods of an API can be a challenge for a developer when building a consuming app. Generating good documentation and help pages for your Web API, using [Swagger](https://swagger.io/) with the .NET Core implementation [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore), is as easy as adding a couple of NuGet packages and modifying the *Startup.cs*. @@ -26,7 +24,7 @@ Generating good documentation and help pages for your Web API, using [Swagger](h This tutorial builds on the sample on [Building Your First Web API with ASP.NET Core MVC and Visual Studio](xref:tutorials/first-web-api). If you'd like to follow along, download the sample at [https://github.com/aspnet/Docs/tree/master/aspnetcore/tutorials/first-web-api/sample](https://github.com/aspnet/Docs/tree/master/aspnetcore/tutorials/first-web-api/sample). -## Getting Started +## Get started There are three main components to Swashbuckle: @@ -36,7 +34,7 @@ There are three main components to Swashbuckle: * `Swashbuckle.AspNetCore.SwaggerUI`: an embedded version of the Swagger UI tool which interprets Swagger JSON to build a rich, customizable experience for describing the Web API functionality. It includes built-in test harnesses for the public methods. -## NuGet Packages +## NuGet packages Swashbuckle can be added with the following approaches: @@ -84,7 +82,7 @@ dotnet add TodoApi.csproj package Swashbuckle.AspNetCore Add the Swagger generator to the services collection in the `ConfigureServices` method of *Startup.cs*: -[!code-csharp[Main](../tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Startup2.cs?name=snippet_ConfigureServices&highlight=7-10)] +[!code-csharp[](web-api-help-pages-using-swagger/sample/TodoApi/Startup2.cs?name=snippet_ConfigureServices&highlight=7-10)] Add the following using statement for the `Info` class: @@ -94,11 +92,12 @@ using Swashbuckle.AspNetCore.Swagger; In the `Configure` method of *Startup.cs*, enable the middleware for serving the generated JSON document and the SwaggerUI: -[!code-csharp[Main](../tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Startup2.cs?name=snippet_Configure&highlight=4,7-10)] +[!code-csharp[](web-api-help-pages-using-swagger/sample/TodoApi/Startup2.cs?name=snippet_Configure&highlight=4,7-10)] Launch the app, and navigate to `http://localhost:/swagger/v1/swagger.json`. The generated document describing the endpoints appears. -**Note:** Microsoft Edge, Google Chrome, and Firefox display JSON documents natively. There are extensions for Chrome that format the document for easier reading. *The following example is reduced for brevity.* +> [!NOTE] +> Microsoft Edge, Google Chrome, and Firefox display JSON documents natively. There are extensions for Chrome that format the document for easier reading. *The following example is reduced for brevity.* ```json { @@ -177,21 +176,21 @@ Each public action method in `TodoController` can be tested from the UI. Click a ![Example Swagger GET test](web-api-help-pages-using-swagger/_static/get-try-it-out.png) -## Customization & Extensibility +## Customize & extend Swagger provides options for documenting the object model and customizing the UI to match your theme. -### API Info and Description +### API info and description The configuration action passed to the `AddSwaggerGen` method can be used to add information such as the author, license, and description: -[!code-csharp[Main](../tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Startup.cs?range=20-30,36)] +[!code-csharp[](web-api-help-pages-using-swagger/sample/TodoApi/Startup.cs?range=20-30,36)] The following image depicts the Swagger UI displaying the version information: ![Swagger UI with version information: description, author, and see more link](web-api-help-pages-using-swagger/_static/custom-info.png) -### XML Comments +### XML comments XML comments can be enabled with the following approaches: @@ -213,7 +212,7 @@ XML comments can be enabled with the following approaches: Manually add the following snippet to the *.csproj* file: -[!code-xml[Main](../tutorials/web-api-help-pages-using-swagger/sample/TodoApi/TodoApi.csproj?range=7-9)] +[!code-xml[](web-api-help-pages-using-swagger/sample/TodoApi/TodoApi.csproj?range=8-9,11)] # [.NET Core CLI](#tab/netcore-cli) @@ -221,17 +220,25 @@ See Visual Studio Code. --- -Enabling XML comments provides debug information for undocumented public types and members. Undocumented types and members are indicated by the warning message: *Missing XML comment for publicly visible type or member*. +Enabling XML comments provides debug information for undocumented public types and members. Undocumented types and members are indicated by the warning message. For example, the following message indicates a violation of warning code 1591: + +``` +warning CS1591: Missing XML comment for publicly visible type or member 'TodoController.GetAll()' +``` + +Suppress warnings by defining a semicolon-delimited list of warning codes to ignore in the *.csproj* file: + +[!code-xml[](web-api-help-pages-using-swagger/sample/TodoApi/TodoApi.csproj?name=snippet_SuppressWarnings&highlight=3)] Configure Swagger to use the generated XML file. For Linux or non-Windows operating systems, file names and paths can be case sensitive. For example, a *ToDoApi.XML* file would be found on Windows but not CentOS. -[!code-csharp[Main](../tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Startup.cs?name=snippet_ConfigureServices&highlight=20-22)] +[!code-csharp[](web-api-help-pages-using-swagger/sample/TodoApi/Startup.cs?name=snippet_ConfigureServices&highlight=20-22)] -In the preceding code, `ApplicationBasePath` gets the base path of the app. The base path is used to locate the XML comments file. *TodoApi.xml* only works for this example, since the name of the generated XML comments file is based on the application name. +In the preceding code, `ApplicationBasePath` gets the base path of the app. The base path is used to locate the XML comments file. *TodoApi.xml* only works for this example, since the name of the generated XML comments file is based on the app name. Adding the triple-slash comments to the method enhances the Swagger UI by adding the description to the section header: -[!code-csharp[Main](../tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Controllers/TodoController.cs?name=snippet_Delete&highlight=2)] +[!code-csharp[](web-api-help-pages-using-swagger/sample/TodoApi/Controllers/TodoController.cs?name=snippet_Delete&highlight=2)] ![Swagger UI showing XML comment 'Deletes a specific TodoItem.' for the DELETE method](web-api-help-pages-using-swagger/_static/triple-slash-comments.png) @@ -266,19 +273,19 @@ The UI is driven by the generated JSON file, which also contains these comments: Add a [](https://docs.microsoft.com/dotnet/csharp/programming-guide/xmldoc/remarks) tag to the `Create` action method documentation. It supplements information specified in the `` tag and provides a more robust Swagger UI. The `` tag content can consist of text, JSON, or XML. -[!code-csharp[Main](../tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Controllers/TodoController.cs?name=snippet_Create&highlight=4-14)] +[!code-csharp[](web-api-help-pages-using-swagger/sample/TodoApi/Controllers/TodoController.cs?name=snippet_Create&highlight=4-14)] Notice the UI enhancements with these additional comments. ![Swagger UI with additional comments shown](web-api-help-pages-using-swagger/_static/xml-comments-extended.png) -### Data Annotations +### Data annotations Decorate the model with attributes, found in `System.ComponentModel.DataAnnotations`, to help drive the Swagger UI components. Add the `[Required]` attribute to the `Name` property of the `TodoItem` class: -[!code-csharp[Main](../tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Models/TodoItem.cs?highlight=10)] +[!code-csharp[](web-api-help-pages-using-swagger/sample/TodoApi/Models/TodoItem.cs?highlight=10)] The presence of this attribute changes the UI behavior and alters the underlying JSON schema: @@ -308,7 +315,7 @@ The presence of this attribute changes the UI behavior and alters the underlying Add the `[Produces("application/json")]` attribute to the API controller. Its purpose is to declare that the controller's actions support a return a content type of *application/json*: -[!code-csharp[Main](../tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Controllers/TodoController.cs?name=snippet_TodoController&highlight=3)] +[!code-csharp[](web-api-help-pages-using-swagger/sample/TodoApi/Controllers/TodoController.cs?name=snippet_TodoController&highlight=3)] The **Response Content Type** drop-down selects this content type as the default for the controller's GET actions: @@ -316,19 +323,19 @@ The **Response Content Type** drop-down selects this content type as the default As the usage of data annotations in the Web API increases, the UI and API help pages become more descriptive and useful. -### Describing Response Types +### Describe response types Consuming developers are most concerned with what is returned — specifically response types and error codes (if not standard). These are handled in the XML comments and data annotations. The `Create` action returns `201 Created` on success or `400 Bad Request` when the posted request body is null. Without proper documentation in the Swagger UI, the consumer lacks knowledge of these expected outcomes. That problem is fixed by adding the highlighted lines in the following example: -[!code-csharp[Main](../tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Controllers/TodoController.cs?name=snippet_Create&highlight=17,18,20,21)] +[!code-csharp[](web-api-help-pages-using-swagger/sample/TodoApi/Controllers/TodoController.cs?name=snippet_Create&highlight=17,18,20,21)] The Swagger UI now clearly documents the expected HTTP response codes: ![Swagger UI showing POST Response Class description 'Returns the newly created Todo item' and '400 - If the item is null' for status code and reason under Response Messages](web-api-help-pages-using-swagger/_static/data-annotations-response-types.png) -### Customizing the UI +### Customize the UI The stock UI is both functional and presentable; however, when building documentation pages for your API, you want it to represent your brand or theme. Accomplishing that task with the Swashbuckle components requires adding the resources to serve static files and then building the folder structure to host those files. @@ -340,7 +347,7 @@ If targeting .NET Framework, add the `Microsoft.AspNetCore.StaticFiles` NuGet pa Enable the static files middleware: -[!code-csharp[Main](../tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Startup.cs?name=snippet_Configure&highlight=3)] +[!code-csharp[](web-api-help-pages-using-swagger/sample/TodoApi/Startup.cs?name=snippet_Configure&highlight=3)] Acquire the contents of the *dist* folder from the [Swagger UI GitHub repository](https://github.com/swagger-api/swagger-ui/tree/2.x/dist). This folder contains the necessary assets for the Swagger UI page. @@ -348,11 +355,11 @@ Create a *wwwroot/swagger/ui* folder, and copy into it the contents of the *dist Create a *wwwroot/swagger/ui/css/custom.css* file with the following CSS to customize the page header: -[!code-css[Main](../tutorials/web-api-help-pages-using-swagger/sample/TodoApi/wwwroot/swagger/ui/css/custom.css)] +[!code-css[](web-api-help-pages-using-swagger/sample/TodoApi/wwwroot/swagger/ui/css/custom.css)] Reference *custom.css* in the *index.html* file: -[!code-html[Main](../tutorials/web-api-help-pages-using-swagger/sample/TodoApi/wwwroot/swagger/ui/index.html?range=14)] +[!code-html[](web-api-help-pages-using-swagger/sample/TodoApi/wwwroot/swagger/ui/index.html?range=14)] Browse to the *index.html* page at `http://localhost:/swagger/ui/index.html`. Enter `http://localhost:/swagger/v1/swagger.json` in the header's textbox, and click the **Explore** button. The resulting page looks as follows: diff --git a/aspnetcore/tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Startup.cs b/aspnetcore/tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Startup.cs index 34ac118f0f..cf0fe82cd3 100644 --- a/aspnetcore/tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Startup.cs +++ b/aspnetcore/tutorials/web-api-help-pages-using-swagger/sample/TodoApi/Startup.cs @@ -1,10 +1,9 @@ -using System; -using System.IO; -using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Builder; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.PlatformAbstractions; using Swashbuckle.AspNetCore.Swagger; +using System; +using System.IO; using TodoApi.Models; namespace TodoApi diff --git a/aspnetcore/tutorials/web-api-help-pages-using-swagger/sample/TodoApi/TodoApi.csproj b/aspnetcore/tutorials/web-api-help-pages-using-swagger/sample/TodoApi/TodoApi.csproj index 311e369171..6e0f4f38a1 100644 --- a/aspnetcore/tutorials/web-api-help-pages-using-swagger/sample/TodoApi/TodoApi.csproj +++ b/aspnetcore/tutorials/web-api-help-pages-using-swagger/sample/TodoApi/TodoApi.csproj @@ -4,9 +4,12 @@ netcoreapp2.0 + bin\Debug\netcoreapp2.0\TodoApi.xml + 1701;1702;1705;1591 +