Merge pull request #5308 from aspnet/master

Update live with current master
pull/5342/head
Rick Anderson 2018-01-29 21:37:52 -10:00 committed by GitHub
commit 18d1dc8677
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 306 additions and 116 deletions

View File

@ -45,9 +45,9 @@ The development environment can enable features that shouldn't be exposed in pro
The environment for local machine development can be set in the *Properties\launchSettings.json* file of the project. Environment values set in *launchSettings.json* override values set in the system environment.
The following XML shows three profiles from a *launchSettings.json* file:
The following JSON shows three profiles from a *launchSettings.json* file:
[!code-xml[Main](environments/sample/WebApp1/Properties/launchSettings.json?highlight=10,11,18,26)]
[!code-json[Main](environments/sample/WebApp1/Properties/launchSettings.json?highlight=10,11,18,26)]
When the application is launched with `dotnet run`, the first profile with `"commandName": "Project"` will be used. The value of `commandName` specifies the web server to launch. `commandName` can be one of :
@ -88,7 +88,7 @@ The production environment should be configured to maximize security, performanc
* Client-side resources are bundled, minified, and potentially served from a CDN.
* Diagnostic error pages disabled.
* Friendly error pages enabled.
* Production logging and monitoring enabled. For example, [Application Insights](https://azure.microsoft.com/documentation/articles/app-insights-asp-net-five/).
* Production logging and monitoring enabled. For example, [Application Insights](/azure/application-insights/app-insights-asp-net-core).
## Setting the environment
@ -144,7 +144,7 @@ export ASPNETCORE_ENVIRONMENT=Development
```
Machine level environment variables are set in the *.bashrc* or *.bash_profile* file. Edit the file using any text editor and add the following statment.
```
```bash
export ASPNETCORE_ENVIRONMENT=Development
```

View File

@ -114,7 +114,7 @@ Hosting can only show an error page for a captured startup error if the error oc
## ASP.NET MVC error handling
[MVC](../mvc/index.md) apps have some additional options for handling errors, such as configuring exception filters and performing model validation.
[MVC](xref:mvc/overview) apps have some additional options for handling errors, such as configuring exception filters and performing model validation.
### Exception Filters

View File

@ -1,4 +1,5 @@
using System;
using System.ComponentModel.DataAnnotations;
namespace RazorPagesMovie.Models
{
@ -6,6 +7,9 @@ namespace RazorPagesMovie.Models
{
public int ID { get; set; }
public string Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }

View File

@ -0,0 +1,13 @@
# Update the generated pages
By [Rick Anderson](https://twitter.com/RickAndMSFT)
We have a good start to the movie app, but the presentation isn't ideal. We don't want to see the time (12:00:00 AM in the image below) and **ReleaseDate** should be **Release Date** (two words).
![Movie application open in Chrome showing movie data](../../tutorials/razor-pages/sql/_static/m55.png)
## Update the generated code
Open the *Models/Movie.cs* file and add the highlighted lines shown in the following code:
[!code-csharp[Main](code/Models/Movie.cs?highlight=2,11-12)]

View File

@ -0,0 +1,84 @@
We'll cover [DataAnnotations](https://docs.microsoft.com/aspnet/mvc/overview/older-versions/mvc-music-store/mvc-music-store-part-6) in the next tutorial. The [Display](https://docs.microsoft.com//aspnet/core/api/microsoft.aspnetcore.mvc.modelbinding.metadata.displaymetadata) attribute specifies what to display for the name of a field (in this case "Release Date" instead of "ReleaseDate"). The [DataType](https://docs.microsoft.com/aspnet/core/api/microsoft.aspnetcore.mvc.dataannotations.internal.datatypeattributeadapter) attribute specifies the type of the data (Date), so the time information stored in the field isn't displayed.
Browse to Pages/Movies and hover over an **Edit** link to see the target URL.
![Browser window with mouse over the Edit link and a link Url of http://localhost:1234/Movies/Edit/5 is shown](../../tutorials/razor-pages/da1/edit7.png)
The **Edit**, **Details**, and **Delete** links are generated by the [Anchor Tag Helper](xref:mvc/views/tag-helpers/builtin-th/anchor-tag-helper)
in the *Pages/Movies/Index.cshtml* file.
[!code-cshtml[Main](../../tutorials/razor-pages/razor-pages-start/snapshot_sample/RazorPagesMovie/Pages/Movies/Index.cshtml?highlight=16-18&range=32-)]
[Tag Helpers](xref:mvc/views/tag-helpers/intro) enable server-side code to participate in creating and rendering HTML elements in Razor files. In the preceding code, the `AnchorTagHelper` dynamically generates the HTML `href` attribute value from the Razor Page (the route is relative), the `asp-page`, and the route id (`asp-route-id`). See [URL generation for Pages](xref:mvc/razor-pages/index#url-generation-for-pages) for more information.
Use **View Source** from your favorite browser to examine the generated markup. A portion of the generated HTML is shown below:
```html
<td>
<a href="/Movies/Edit?id=1">Edit</a> |
<a href="/Movies/Details?id=1">Details</a> |
<a href="/Movies/Delete?id=1">Delete</a>
</td>
```
The dynamically-generated links pass the movie ID with a query string (for example, `http://localhost:5000/Movies/Details?id=2` ).
Update the Edit, Details, and Delete Razor Pages to use the "{id:int}" route template. Change the page directive for each of these pages from `@page` to `@page "{id:int}"`. Run the app and then view source. The generated HTML adds the ID to the path portion of the URL:
```html
<td>
<a href="/Movies/Edit/1">Edit</a> |
<a href="/Movies/Details/1">Details</a> |
<a href="/Movies/Delete/1">Delete</a>
</td>
```
A request to the page with the "{id:int}" route template that does **not** include the integer will return an HTTP 404 (not found) error. For example, `http://localhost:5000/Movies/Details` will return a 404 error. To make the ID optional, append `?` to the route constraint:
```cshtml
@page "{id:int?}"
```
### Update concurrency exception handling
Update the `OnPostAsync` method in the *Pages/Movies/Edit.cshtml.cs* file. The following highlighted code shows the changes:
[!code-csharp[Main](../../tutorials/razor-pages/razor-pages-start/snapshot_sample/RazorPagesMovie/Pages/Movies/Edit.cshtml.cs?name=snippet1&highlight=16-23)]
The previous code only detects concurrency exceptions when the first concurrent client deletes the movie, and the second concurrent client posts changes to the movie.
To test the `catch` block:
* Set a breakpoint on `catch (DbUpdateConcurrencyException)`
* Edit a movie.
* In another browser window, select the **Delete** link for the same movie, and then delete the movie.
* In the previous browser window, post changes to the movie.
Production code would generally detect concurrency conflicts when two or more clients concurrently updated a record. See [Handling concurrency conflicts](xref:data/ef-rp/concurrency) for more information.
### Posting and binding review
Examine the *Pages/Movies/Edit.cshtml.cs* file:
[!code-csharp[Main](../../tutorials/razor-pages/razor-pages-start/snapshot_sample/RazorPagesMovie/Pages/Movies/Edit.cshtml.cs?name=snippet2)]
When an HTTP GET request is made to the Movies/Edit page (for example, `http://localhost:5000/Movies/Edit/2`):
* The `OnGetAsync` method fetches the movie from the database and returns the `Page` method.
* The `Page` method renders the *Pages/Movies/Edit.cshtml* Razor Page. The *Pages/Movies/Edit.cshtml* file contains the model directive (`@model RazorPagesMovie.Pages.Movies.EditModel`), which makes the movie model available on the page.
* The Edit form is displayed with the values from the movie.
When the Movies/Edit page is posted:
* The form values on the page are bound to the `Movie` property. The `[BindProperty]` attribute enables [Model binding](xref:mvc/models/model-binding).
```csharp
[BindProperty]
public Movie Movie { get; set; }
```
* If there are errors in the model state (for example, `ReleaseDate` cannot be converted to a date), the form is posted again with the submitted values.
* If there are no model errors, the movie is saved.
The HTTP GET methods in the Index, Create, and Delete Razor pages follow a similar pattern. The HTTP POST `OnPostAsync` method in the Create Razor Page follows a similar pattern to the `OnPostAsync` method in the Edit Razor Page.
Search is added in the next tutorial.

View File

@ -0,0 +1,96 @@
# Adding search to a Razor Pages app
By [Rick Anderson](https://twitter.com/RickAndMSFT)
In this document, search capability is added to the Index page that enables searching movies by *genre* or *name*.
Update the Index page's `OnGetAsync` method with the following code:
[!code-cshtml[Main](../../tutorials/razor-pages/razor-pages-start/sample/RazorPagesMovie/Pages/_ViewStart.cshtml)]
[!code-csharp[Main](../../tutorials/razor-pages/razor-pages-start/sample/RazorPagesMovie/Pages/Movies/Index.cshtml.cs?name=snippet_1stSearch)]
The first line of the `OnGetAsync` method creates a [LINQ](https://docs.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/) query to select the movies:
```csharp
var movies = from m in _context.Movie
select m;
```
The query is *only* defined at this point, it has **not** been run against the database.
If the `searchString` parameter contains a string, the movies query is modified to filter on the search string:
[!code-csharp[Main](../../tutorials/razor-pages/razor-pages-start/sample/RazorPagesMovie/Pages/Movies/Index.cshtml.cs?name=snippet_SearchNull)]
The `s => s.Title.Contains()` code is a [Lambda Expression](https://docs.microsoft.com/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions). Lambdas are used in method-based [LINQ](https://docs.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/) queries as arguments to standard query operator methods such as the [Where](https://docs.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/query-syntax-and-method-syntax-in-linq) method or `Contains` (used in the preceding code). LINQ queries are not executed when they're defined or when they're modified by calling a method (such as `Where`, `Contains` or `OrderBy`). Rather, query execution is deferred. That means the evaluation of an expression is delayed until its realized value is iterated over or the `ToListAsync` method is called. See [Query Execution](https://docs.microsoft.com/dotnet/framework/data/adonet/ef/language-reference/query-execution) for more information.
**Note:** The [Contains](https://docs.microsoft.com//dotnet/api/system.data.objects.dataclasses.entitycollection-1.contains) method is run on the database, not in the C# code. The case sensitivity on the query depends on the database and the collation. On SQL Server, `Contains` maps to [SQL LIKE](https://docs.microsoft.com/sql/t-sql/language-elements/like-transact-sql), which is case insensitive. In SQLite, with the default collation, it's case sensitive.
Navigate to the Movies page and append a query string such as `?searchString=Ghost` to the URL (for example, `http://localhost:5000/Movies?searchString=Ghost`). The filtered movies are displayed.
![Index view](../../tutorials/razor-pages/search/_static/ghost.png)
If the following route template is added to the Index page, the search string can be passed as a URL segment (for example, `http://localhost:5000/Movies/ghost`).
```cshtml
@page "{searchString?}"
```
The preceding route constraint allows searching the title as route data (a URL segment) instead of as a query string value. The `?` in `"{searchString?}"` means this is an optional route parameter.
![Index view with the word ghost added to the Url and a returned movie list of two movies, Ghostbusters and Ghostbusters 2](../../tutorials/razor-pages/search/_static/g2.png)
However, you can't expect users to modify the URL to search for a movie. In this step, UI is added to filter movies. If you added the route constraint `"{searchString?}"`, remove it.
Open the *Pages/Movies/Index.cshtml* file, and add the `<form>` markup highlighted in the following code:
[!code-cshtml[Main](../../tutorials/razor-pages/razor-pages-start/sample/RazorPagesMovie/Pages/Movies/Index2.cshtml?highlight=14-19&range=1-22)]
The HTML `<form>` tag uses the [Form Tag Helper](xref:mvc/views/working-with-forms#the-form-tag-helper). When the form is submitted, the filter string is sent to the *Pages/Movies/Index* page. Save the changes and test the filter.
![Index view with the word ghost typed into the Title filter textbox](../../tutorials/razor-pages/search/_static/filter.png)
## Search by genre
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-)]
The `SelectList Genres` contains the list of genres. This allows the user to select a genre from the list.
The `MovieGenre` property contains the specific genre the user selects (for example, "Western").
Update the `OnGetAsync` method with the following code:
[!code-csharp[Main](../../tutorials/razor-pages/razor-pages-start/sample/RazorPagesMovie/Pages/Movies/Index.cshtml.cs?name=snippet_SearchGenre)]
The following code is a LINQ query that retrieves all the genres from the database.
[!code-csharp[Main](../../tutorials/razor-pages/razor-pages-start/sample/RazorPagesMovie/Pages/Movies/Index.cshtml.cs?name=snippet_LINQ)]
The `SelectList` of genres is created by projecting the distinct genres.
<!-- BUG in OPS
Tag snippet_selectlist's start line '75' should be less than end line '29' when resolving "[!code-csharp[Main](../../tutorials/razor-pages/razor-pages-start/sample/RazorPagesMovie/Pages/Movies/Index.cshtml.cs?name=snippet_SelectList)]"
There's no start line.
[!code-csharp[Main](../../tutorials/razor-pages/razor-pages-start/sample/RazorPagesMovie/Pages/Movies/Index.cshtml.cs?name=snippet_SelectList)]
-->
```csharp
Genres = new SelectList(await genreQuery.Distinct().ToListAsync());
```
### Adding search by genre
Update *Index.cshtml* as follows:
[!code-cshtml[Main](../../tutorials/razor-pages/razor-pages-start/sample/RazorPagesMovie/Pages/Movies/IndexFormGenreNoRating.cshtml?highlight=16-18&range=1-26)]
Test the app by searching by genre, by movie title, and by both.
>[!div class="step-by-step"]
[Previous: Updating the pages](xref:tutorials/razor-pages/da1)
[Next: Adding a new field](xref:tutorials/razor-pages/new-field)

View File

@ -89,7 +89,7 @@ Run the app.
![Web application open in Microsoft Edge](mvc/_static/hello-world.png)
See [Controllers](../mvc/controllers/index.md) and [Views](../mvc/views/index.md) for more information.
See [Controllers](xref:mvc/controllers/actions) and [Views](xref:mvc/views/overview) for more information.
Now that we have a minimal working ASP.NET Core project, we can start migrating functionality from the ASP.NET MVC project. We will need to move the following:
@ -151,7 +151,7 @@ See [Manage Client-Side Packages with Bower](../client-side/bower.md) for more i
* Create a *Views/Shared* folder.
* *Optional:* Copy *_ViewImports.cshtml* from the *FullAspNetCore* MVC project's *Views* folder into the ASP.NET Core project's *Views* folder. Remove any namespace declaration in the *_ViewImports.cshtml* file. The *_ViewImports.cshtml* file provides namespaces for all the view files and brings in [Tag Helpers](../mvc/views/tag-helpers/index.md). Tag Helpers are used in the new layout file. The *_ViewImports.cshtml* file is new for ASP.NET Core.
* *Optional:* Copy *_ViewImports.cshtml* from the *FullAspNetCore* MVC project's *Views* folder into the ASP.NET Core project's *Views* folder. Remove any namespace declaration in the *_ViewImports.cshtml* file. The *_ViewImports.cshtml* file provides namespaces for all the view files and brings in [Tag Helpers](xref:mvc/views/tag-helpers/intro). Tag Helpers are used in the new layout file. The *_ViewImports.cshtml* file is new for ASP.NET Core.
* Copy the *_Layout.cshtml* file from the old ASP.NET MVC project's *Views/Shared* folder into the ASP.NET Core project's *Views/Shared* folder.
@ -186,7 +186,7 @@ The updated *_Layout.cshtml* file is shown below:
View the site in the browser. It should now load correctly, with the expected styles in place.
* *Optional:* You might want to try using the new layout file. For this project you can copy the layout file from the *FullAspNetCore* project. The new layout file uses [Tag Helpers](../mvc/views/tag-helpers/index.md) and has other improvements.
* *Optional:* You might want to try using the new layout file. For this project you can copy the layout file from the *FullAspNetCore* project. The new layout file uses [Tag Helpers](xref:mvc/views/tag-helpers/intro) and has other improvements.
## Configure bundling and minification

View File

@ -28,6 +28,21 @@
### [Examine the Details and Delete methods](tutorials/first-mvc-app/details.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)
#### [Adding a model](xref:tutorials/razor-pages-mac/model)
#### [Scaffolded Razor Pages](xref:tutorials/razor-pages-mac/page)
#### [Working with SQLite](xref:tutorials/razor-pages-mac/sql)
#### [Update the pages](xref:tutorials/razor-pages-mac/da1)
#### [Add search](xref:tutorials/razor-pages-mac/search)
### [Razor Pages web app with VS Code](xref:tutorials/razor-pages-vsc/index)
#### [Getting started with Razor Pages](xref:tutorials/razor-pages-vsc/razor-pages-start)
#### [Adding a model](xref:tutorials/razor-pages-vsc/model)
#### [Scaffolded Razor Pages](xref:tutorials/razor-pages-vsc/page)
#### [Working with SQLite](xref:tutorials/razor-pages-vsc/sql)
#### [Update the pages](xref:tutorials/razor-pages-vsc/da1)
### [MVC web app with Visual Studio for Mac](xref:tutorials/first-mvc-app-mac/index)
#### [Getting started](xref:tutorials/first-mvc-app-mac/start-mvc)
@ -41,7 +56,7 @@
#### [Adding Validation](xref:tutorials/first-mvc-app-mac/validation)
#### [Examining the Details and Delete methods](xref:tutorials/first-mvc-app/details)
### [Web app with Visual Studio Code on Mac or Linux](xref:tutorials/first-mvc-app-xplat/index)
### [MVC web app with Visual Studio Code on Mac or Linux](xref:tutorials/first-mvc-app-xplat/index)
#### [Getting started](tutorials/first-mvc-app-xplat/start-mvc.md)
#### [Adding a controller](tutorials/first-mvc-app-xplat/adding-controller.md)
#### [Adding a view](tutorials/first-mvc-app-xplat/adding-view.md)
@ -53,18 +68,6 @@
#### [Adding Validation](tutorials/first-mvc-app-xplat/validation.md)
#### [Examining the Details and Delete methods](tutorials/first-mvc-app/details.md)
### [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)
#### [Adding a model](xref:tutorials/razor-pages-mac/model)
#### [Scaffolded Razor Pages](xref:tutorials/razor-pages-mac/page)
#### [Working with SQLite](xref:tutorials/razor-pages-mac/sql)
### [Razor Pages web app with VS Code](xref:tutorials/razor-pages-vsc/index)
#### [Getting started with Razor Pages](xref:tutorials/razor-pages-vsc/razor-pages-start)
#### [Adding a model](xref:tutorials/razor-pages-vsc/model)
#### [Scaffolded Razor Pages](xref:tutorials/razor-pages-vsc/page)
#### [Working with SQLite](xref:tutorials/razor-pages-vsc/sql)
### [Web API with Visual Studio for Mac](xref:tutorials/first-web-api-mac)
### [Web API with Visual Studio Code](xref:tutorials/web-api-vsc)

View File

@ -0,0 +1,19 @@
---
title: Update the generated pages
author: rick-anderson
description: Update the generated pages with better display.
manager: wpickett
ms.author: riande
ms.date: 08/07/2017
ms.prod: asp.net-core
ms.technology: aspnet
ms.topic: get-started-article
uid: tutorials/razor-pages-mac/da1
---
[!INCLUDE[model1](../../includes/RP/da1.md)]
[!INCLUDE[model1](../../includes/RP/da2.md)]
>[!div class="step-by-step"]
[Previous: Working with SQLlite](xref:tutorials/razor-pages-mac/sql)
[Adding Search](xref:tutorials/razor-pages-mac/search)

View File

@ -22,11 +22,11 @@ This series explains the basics of building a Razor Pages web app with ASP.NET C
1. [Adding a model to a Razor Pages app](xref:tutorials/razor-pages-mac/model)
1. [Scaffolded Razor Pages](xref:tutorials/razor-pages-mac/page)
1. [Working with SQLite](xref:tutorials/razor-pages-mac/sql)
1. [Update the pages](xref:tutorials/razor-pages-mac/da1)
1. [Adding search](xref:tutorials/razor-pages-mac/search)
Until the next section is complete, follow the Visual Studio for Windows version.
1. [Updating the pages](xref:tutorials/razor-pages/da1)
1. [Adding search](xref:tutorials/razor-pages/search)
1. [Adding a new field](xref:tutorials/razor-pages/new-field)
1. [Adding validation](xref:tutorials/razor-pages/validation)

View File

@ -19,4 +19,4 @@ The next tutorial explains SQLite and seeding the database.
>[!div class="step-by-step"]
[Previous: Adding a model](xref:tutorials/razor-pages-mac/model)
[Next: SQLite](xref:tutorials/razor-pages-mac/sql)
[Next: SQLite ](xref:tutorials/razor-pages-mac/sql)

View File

@ -0,0 +1,18 @@
---
title: Adding search to ASP.NET Core Razor Pages
author: rick-anderson
description: Shows how to add search to ASP.NET Core Razor Pages
manager: wpickett
ms.author: riande
ms.date: 08/07/2017
ms.prod: asp.net-core
ms.technology: aspnet
ms.topic: get-started-article
uid: tutorials/razor-pages-mac/search
---
[!INCLUDE[Search](../../includes/RP/search.md)]
>[!div class="step-by-step"]
[Previous: Updating the pages](xref:tutorials/razor-pages-mac/da1)
[Next: Adding a new field](xref:tutorials/razor-pages/new-field)

View File

@ -16,4 +16,4 @@ uid: tutorials/razor-pages-mac/sql
>[!div class="step-by-step"]
[Previous: Adding a model](xref:tutorials/razor-pages-mac/model)
[Next: Updating the pages](xref:tutorials/razor-pages/da1)
[Next: Update the pages](xref:tutorials/razor-pages-mac/da1)

View File

@ -0,0 +1,19 @@
---
title: Update the generated pages
author: rick-anderson
description: Update the generated pages with better display.
manager: wpickett
ms.author: riande
ms.date: 08/07/2017
ms.prod: asp.net-core
ms.technology: aspnet
ms.topic: get-started-article
uid: tutorials/razor-pages-vsc/da1
---
[!INCLUDE[model1](../../includes/RP/da1.md)]
[!INCLUDE[model1](../../includes/RP/da2.md)]
>[!div class="step-by-step"]
[Previous: Working with SQLlite](xref:tutorials/razor-pages-vsc/sql)
[Adding Search](xref:tutorials/razor-pages/search)

View File

@ -11,7 +11,6 @@ ms.topic: get-started-article
uid: tutorials/razor-pages-vsc/index
---
# Create a Razor Pages web app with ASP.NET Core and Visual Studio Code
This is a work in progress.
@ -22,10 +21,10 @@ This series explains the basics of building a Razor Pages web app with ASP.NET C
1. [Adding a model to a Razor Pages app](xref:tutorials/razor-pages-vsc/model)
1. [Scaffolded Razor Pages] (xref:tutorials/razor-pages-vsc/page)
1. [Working with SQLite](xref:tutorials/razor-pages-vsc/sql)
1. [Update the pages](xref:tutorials/razor-pages-vsc/da1)
1. [Adding search](xref:tutorials/razor-pages-vsc/search)
Until the next section is complete, follow the Visual Studio for Windows version.
1. [Updating the pages](xref:tutorials/razor-pages/da1)
1. [Adding search](xref:tutorials/razor-pages/search)
1. [Adding a new field](xref:tutorials/razor-pages/new-field)
1. [Adding validation](xref:tutorials/razor-pages/validation)

View File

@ -0,0 +1,18 @@
---
title: Adding search to ASP.NET Core Razor Pages
author: rick-anderson
description: Shows how to add search to ASP.NET Core Razor Pages
manager: wpickett
ms.author: riande
ms.date: 08/07/2017
ms.prod: asp.net-core
ms.technology: aspnet
ms.topic: get-started-article
uid: tutorials/razor-pages-vsc/search
---
[!INCLUDE[Search](../../includes/RP/search.md)]
>[!div class="step-by-step"]
[Previous: Updating the pages](xref:tutorials/razor-pages-vsc/da1)
[Next: Adding a new field](xref:tutorials/razor-pages/new-field)

View File

@ -16,4 +16,4 @@ uid: tutorials/razor-pages-vsc/sql
>[!div class="step-by-step"]
[Previous: Adding a model](xref:tutorials/razor-pages-vsc/model)
[Next: Updating the pages](xref:tutorials/razor-pages/da1)
[Next: Update the pages](xref:tutorials/razor-pages-vsc/da1)

View File

@ -1,7 +1,7 @@
---
title: Updating the generated pages
title: Update the generated pages
author: rick-anderson
description: Updating the generated pages with better display.
description: Update the generated pages with better display.
manager: wpickett
ms.author: riande
ms.date: 08/07/2017
@ -10,7 +10,7 @@ ms.technology: aspnet
ms.topic: get-started-article
uid: tutorials/razor-pages/da1
---
# Updating the generated pages
# Update the generated pages
By [Rick Anderson](https://twitter.com/RickAndMSFT)
@ -34,90 +34,7 @@ Select `using System.ComponentModel.DataAnnotations;`
Visual studio adds `using System.ComponentModel.DataAnnotations;`.
We'll cover [DataAnnotations](https://docs.microsoft.com/aspnet/mvc/overview/older-versions/mvc-music-store/mvc-music-store-part-6) in the next tutorial. The [Display](https://docs.microsoft.com//aspnet/core/api/microsoft.aspnetcore.mvc.modelbinding.metadata.displaymetadata) attribute specifies what to display for the name of a field (in this case "Release Date" instead of "ReleaseDate"). The [DataType](https://docs.microsoft.com/aspnet/core/api/microsoft.aspnetcore.mvc.dataannotations.internal.datatypeattributeadapter) attribute specifies the type of the data (Date), so the time information stored in the field isn't displayed.
Browse to Pages/Movies and hover over an **Edit** link to see the target URL.
![Browser window with mouse over the Edit link and a link Url of http://localhost:1234/Movies/Edit/5 is shown](da1/edit7.png)
The **Edit**, **Details**, and **Delete** links are generated by the [Anchor Tag Helper](xref:mvc/views/tag-helpers/builtin-th/anchor-tag-helper)
in the *Pages/Movies/Index.cshtml* file.
[!code-cshtml[Main](razor-pages-start/snapshot_sample/RazorPagesMovie/Pages/Movies/Index.cshtml?highlight=16-18&range=32-)]
[Tag Helpers](xref:mvc/views/tag-helpers/intro) enable server-side code to participate in creating and rendering HTML elements in Razor files. In the preceding code, the `AnchorTagHelper` dynamically generates the HTML `href` attribute value from the Razor Page (the route is relative), the `asp-page`, and the route id (`asp-route-id`). See [URL generation for Pages](xref:mvc/razor-pages/index#url-generation-for-pages) for more information.
Use **View Source** from your favorite browser to examine the generated markup. A portion of the generated HTML is shown below:
```html
<td>
<a href="/Movies/Edit?id=1">Edit</a> |
<a href="/Movies/Details?id=1">Details</a> |
<a href="/Movies/Delete?id=1">Delete</a>
</td>
```
The dynamically-generated links pass the movie ID with a query string (for example, `http://localhost:5000/Movies/Details?id=2` ).
Update the Edit, Details, and Delete Razor Pages to use the "{id:int}" route template. Change the page directive for each of these pages from `@page` to `@page "{id:int}"`. Run the app and then view source. The generated HTML adds the ID to the path portion of the URL:
```html
<td>
<a href="/Movies/Edit/1">Edit</a> |
<a href="/Movies/Details/1">Details</a> |
<a href="/Movies/Delete/1">Delete</a>
</td>
```
A request to the page with the "{id:int}" route template that does **not** include the integer will return an HTTP 404 (not found) error. For example, `http://localhost:5000/Movies/Details` will return a 404 error. To make the ID optional, append `?` to the route constraint:
```cshtml
@page "{id:int?}"
```
### Update concurrency exception handling
Update the `OnPostAsync` method in the *Pages/Movies/Edit.cshtml.cs* file. The following highlighted code shows the changes:
[!code-csharp[Main](razor-pages-start/snapshot_sample/RazorPagesMovie/Pages/Movies/Edit.cshtml.cs?name=snippet1&highlight=16-23)]
The previous code only detects concurrency exceptions when the first concurrent client deletes the movie, and the second concurrent client posts changes to the movie.
To test the `catch` block:
* Set a breakpoint on `catch (DbUpdateConcurrencyException)`
* Edit a movie.
* In another browser window, select the **Delete** link for the same movie, and then delete the movie.
* In the previous browser window, post changes to the movie.
Production code would generally detect concurrency conflicts when two or more clients concurrently updated a record. See [Handling concurrency conflicts](xref:data/ef-rp/concurrency) for more information.
### Posting and binding review
Examine the *Pages/Movies/Edit.cshtml.cs* file:
[!code-csharp[Main](razor-pages-start/snapshot_sample/RazorPagesMovie/Pages/Movies/Edit.cshtml.cs?name=snippet2)]
When an HTTP GET request is made to the Movies/Edit page (for example, `http://localhost:5000/Movies/Edit/2`):
* The `OnGetAsync` method fetches the movie from the database and returns the `Page` method.
* The `Page` method renders the *Pages/Movies/Edit.cshtml* Razor Page. The *Pages/Movies/Edit.cshtml* file contains the model directive (`@model RazorPagesMovie.Pages.Movies.EditModel`), which makes the movie model available on the page.
* The Edit form is displayed with the values from the movie.
When the Movies/Edit page is posted:
* The form values on the page are bound to the `Movie` property. The `[BindProperty]` attribute enables [Model binding](xref:mvc/models/model-binding).
```csharp
[BindProperty]
public Movie Movie { get; set; }
```
* If there are errors in the model state (for example, `ReleaseDate` cannot be converted to a date), the form is posted again with the submitted values.
* If there are no model errors, the movie is saved.
The HTTP GET methods in the Index, Create, and Delete Razor pages follow a similar pattern. The HTTP POST `OnPostAsync` method in the Create Razor Page follows a similar pattern to the `OnPostAsync` method in the Edit Razor Page.
Search is added in the next tutorial.
[!INCLUDE[model1](../../includes/RP/da2.md)]
>[!div class="step-by-step"]
[Previous: Working with SQL Server LocalDB](xref:tutorials/razor-pages/sql)