commit
18d1dc8677
|
@ -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
|
||||
```
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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)]
|
|
@ -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.
|
|
@ -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)
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue