Skip to content

Light Freshness Edit: ASP.NET and EF Core - 3 tutorials#37014

Open
GitHubber17 wants to merge 6 commits intodotnet:mainfrom
GitHubber17:568764-a
Open

Light Freshness Edit: ASP.NET and EF Core - 3 tutorials#37014
GitHubber17 wants to merge 6 commits intodotnet:mainfrom
GitHubber17:568764-a

Conversation

@GitHubber17
Copy link
Copy Markdown
Contributor

@GitHubber17 GitHubber17 commented Apr 16, 2026

This PR contains light freshness updates to the following articles:

  • Tutorial: Implement CRUD Functionality - ASP.NET MVC with EF Core
  • Tutorial 2: Razor Pages with EF Core in ASP.NET Core - CRUD (duplicate content in moniker sections reduced)
  • Tutorial: Add sorting, filtering, and paging - ASP.NET MVC with EF Core

For details, see ADO request 568764.


Internal previews

📄 File 🔗 Preview link
aspnetcore/data/ef-mvc/advanced.md Tutorial: Learn about advanced scenarios - ASP.NET MVC with EF Core
aspnetcore/data/ef-mvc/crud.md Tutorial: Implement basic CRUD functionality - ASP.NET MVC with EF Core
aspnetcore/data/ef-mvc/sort-filter-page.md Add Sort, Filter, Paging - ASP.NET MVC with EF Core
aspnetcore/data/ef-rp/crud.md customer intent: As an ASP.NET developer, I want to make changes to the auto-generated CRUD code, so I can customize my Razor pages.

Comment thread aspnetcore/data/ef-mvc/crud.md Outdated
In a desktop application, state changes are typically set automatically. You read an entity and make changes to some of its property values. This behavior causes its entity state to automatically change to `Modified`. When you call the `SaveChanges` method, the Entity Framework generates a SQL `UPDATE` statement that updates only the actual properties that you changed.

In a web app, the `DbContext` that initially reads an entity and displays its data to be edited is disposed after a page is rendered. When the HttpPost `Edit` action method is called, a new web request is made and you have a new instance of the `DbContext`. If you re-read the entity in that new context, you simulate desktop processing.
In a web app, the `DbContext` method that initially reads an entity and displays its data to be edited is disposed after a page is rendered. When the HttpPost `Edit` action method is called, a new web request is made and you have a new instance of the `DbContext` method. If you re-read the entity in that new context, you simulate desktop processing.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In a web app, the `DbContext` method that initially reads an entity and displays its data to be edited is disposed after a page is rendered. When the HttpPost `Edit` action method is called, a new web request is made and you have a new instance of the `DbContext` method. If you re-read the entity in that new context, you simulate desktop processing.
In a web app, the `DbContext` that initially reads an entity and displays its data to be edited is disposed after a page is rendered. When the HttpPost `Edit` action method is called, a new web request is made and you have a new instance of the `DbContext`. If you re-read the entity in that new context, you simulate desktop processing.

I know this is still a draft, but since I spotted this I'll mention the DbContext is not a method, it is an instance of a class. Since we already describe what it is and how it is used just after, I would not use "instance" either and just drop the "method" added here (and anywhere else it was added).

Comment thread aspnetcore/data/ef-rp/crud.md Outdated

:::moniker-end
> [!div class="nextstepaction"]
> [Tutorial 3: Razor Pages with EF Core in ASP.NET Code - Sort, Filter, Paging](sort-filter-page.md) No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> [Tutorial 3: Razor Pages with EF Core in ASP.NET Code - Sort, Filter, Paging](sort-filter-page.md)
> [Tutorial 3: Razor Pages with EF Core in ASP.NET Core - Sort, Filter, Paging](sort-filter-page.md)

I know this is still in draft, but spotted this, so I'll mention it. Changing typo "Code" to "Core". The product name is "ASP.NET Core"

@wadepickett wadepickett changed the title [DRAFT] Light Freshness Edit: ASP.NET [DRAFT] Light Freshness Edit: ASP.NET and EF Core - 3 tutorials Apr 17, 2026
@GitHubber17 GitHubber17 marked this pull request as ready for review April 17, 2026 19:05
@GitHubber17 GitHubber17 changed the title [DRAFT] Light Freshness Edit: ASP.NET and EF Core - 3 tutorials Light Freshness Edit: ASP.NET and EF Core - 3 tutorials Apr 17, 2026
@GitHubber17
Copy link
Copy Markdown
Contributor Author

@tdykstra @wadepickett - Refreshed articles ready for review. See the top comment for details. Thanks

Cc @cmastr

@wadepickett wadepickett requested a review from tdykstra April 18, 2026 17:46
Comment on lines +24 to +27
> * Customize pages: **Details**, **Create**, **Edit**, and **Delete**
> * Explore how to protect against overposting
> * Use different approaches for HttpPost `Edit` code and `Delete`
> * Work with no-tracking queries
Copy link
Copy Markdown
Contributor

@wadepickett wadepickett Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> * Customize pages: **Details**, **Create**, **Edit**, and **Delete**
> * Explore how to protect against overposting
> * Use different approaches for HttpPost `Edit` code and `Delete`
> * Work with no-tracking queries
> * Customize the Details page by adding enrollment data with eager loading
> * Update the Create page with security and error handling
> * Update the Edit page to prevent overposting
> * Update the Delete page with error reporting
> * Close database connections

For the "In this tutorial, you" section: The verbs in the original are chosen carefully. "Customize" means adding entirely new functionality to the scaffolded code, while "Update" means refining the existing scaffolded code. That said, you hit on a real and important clarity problem to address: Briefly stating why each page is being changed helps the developer quickly decide if this tutorial is relevant to them. I'll make a suggestion here.

Just a side note: if you can use the reviewer's suggested changes as is, it is nice to just hit the "Apply Suggestion" button so their commit gets added. It gives reviewers credit for collaborating. If that messes up your process though and need to add it to your own locally as your own commit, that's understandable and no worries.

You removed the `ID` property from the `Bind` attribute because the ID is the primary key value that SQL Server sets automatically when it inserts the row. Input from the user doesn't set the ID value.

The `ValidateAntiForgeryToken` attribute helps prevent cross-site request forgery (CSRF) attacks. The token is automatically injected into the view by the [FormTagHelper](xref:mvc/views/working-with-forms#the-form-tag-helper) and is included when the form is submitted by the user. The token is validated by the `ValidateAntiForgeryToken` attribute. For more information, see <xref:security/anti-request-forgery>.
Other than the `Bind` attribute, the `try-catch` block is the only change made to the scaffolded code. If an exception that derives from the `DbUpdateException` handler is caught while the changes are being saved, a generic error message is displayed. The cause for a `DbUpdateException` exception can be external to the application rather than a programming error, so the user is advised to try again. A production quality application logs such exception, but that functionality isn't implemented in this sample. For more information, see [Logging in .NET and ASP.NET Core](../../fundamentals/logging/index.md).
Copy link
Copy Markdown
Contributor

@wadepickett wadepickett Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Other than the `Bind` attribute, the `try-catch` block is the only change made to the scaffolded code. If an exception that derives from the `DbUpdateException` handler is caught while the changes are being saved, a generic error message is displayed. The cause for a `DbUpdateException` exception can be external to the application rather than a programming error, so the user is advised to try again. A production quality application logs such exception, but that functionality isn't implemented in this sample. For more information, see [Logging in .NET and ASP.NET Core](../../fundamentals/logging/index.md).
Other than the `Bind` attribute, the `try-catch` block is the only change made to the scaffolded code. If an exception that derives from `DbUpdateException` is caught while the changes are being saved, a generic error message is displayed. The cause for a `DbUpdateException` exception can be external to the application rather than a programming error, so the user is advised to try again. A production quality application logs such exception, but that functionality isn't implemented in this sample. For more information, see [Logging in .NET and ASP.NET Core](../../fundamentals/logging/index.md).

DbUpdateException is an exception class, not a handler. Adding "handler" is technically incorrect. In .NET, "handler" implies something that processes events or exceptions, which is the opposite of what an exception class is. Given the context of "derived from" is already stated, I wouldn't add "class" instead either. The original is clear and accurate in this case.

The `ValidateAntiForgeryToken` attribute helps prevent cross-site request forgery (CSRF) attacks. The token is automatically injected into the view by the [FormTagHelper](xref:mvc/views/working-with-forms#the-form-tag-helper) and is included when the form is submitted by the user. The token is validated by the `ValidateAntiForgeryToken` attribute. For more information, see <xref:security/anti-request-forgery>.
Other than the `Bind` attribute, the `try-catch` block is the only change made to the scaffolded code. If an exception that derives from the `DbUpdateException` handler is caught while the changes are being saved, a generic error message is displayed. The cause for a `DbUpdateException` exception can be external to the application rather than a programming error, so the user is advised to try again. A production quality application logs such exception, but that functionality isn't implemented in this sample. For more information, see [Logging in .NET and ASP.NET Core](../../fundamentals/logging/index.md).

The `ValidateAntiForgeryToken` attribute helps prevent cross-site request forgery (CSRF) attacks. The [Form Tag Helper](../../mvc/views/working-with-forms.md#the-form-tag-helper) method automatically injects the token into the view. The token is also included when the user submits the form. The `ValidateAntiForgeryToken` attribute checks the token. For more information, see t[Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core](../../security/anti-request-forgery.md) and [FormTagHelper Class](/dotnet/api/microsoft.aspnetcore.mvc.taghelpers.formtaghelper) reference.
Copy link
Copy Markdown
Contributor

@wadepickett wadepickett Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The `ValidateAntiForgeryToken` attribute helps prevent cross-site request forgery (CSRF) attacks. The [Form Tag Helper](../../mvc/views/working-with-forms.md#the-form-tag-helper) method automatically injects the token into the view. The token is also included when the user submits the form. The `ValidateAntiForgeryToken` attribute checks the token. For more information, see t[Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core](../../security/anti-request-forgery.md) and [FormTagHelper Class](/dotnet/api/microsoft.aspnetcore.mvc.taghelpers.formtaghelper) reference.
The `ValidateAntiForgeryToken` attribute helps prevent cross-site request forgery (CSRF) attacks. The [Form Tag Helper](../../mvc/views/working-with-forms.md#the-form-tag-helper) automatically injects the token into the view. The token is also included when the user submits the form. The `ValidateAntiForgeryToken` attribute checks the token. For more information, see t[Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core](../../security/anti-request-forgery.md) and [FormTagHelper Class](/dotnet/api/microsoft.aspnetcore.mvc.taghelpers.formtaghelper) reference.

FormTagHelper is a class (a Tag Helper), not a method. Calling it a "method" would be confusing. Given the context already provided, I think it would be best to remove "method" here and not add "class" in its place either.

The `ValidateAntiForgeryToken` attribute helps prevent cross-site request forgery (CSRF) attacks. The token is automatically injected into the view by the [FormTagHelper](xref:mvc/views/working-with-forms#the-form-tag-helper) and is included when the form is submitted by the user. The token is validated by the `ValidateAntiForgeryToken` attribute. For more information, see <xref:security/anti-request-forgery>.
Other than the `Bind` attribute, the `try-catch` block is the only change made to the scaffolded code. If an exception that derives from the `DbUpdateException` handler is caught while the changes are being saved, a generic error message is displayed. The cause for a `DbUpdateException` exception can be external to the application rather than a programming error, so the user is advised to try again. A production quality application logs such exception, but that functionality isn't implemented in this sample. For more information, see [Logging in .NET and ASP.NET Core](../../fundamentals/logging/index.md).

The `ValidateAntiForgeryToken` attribute helps prevent cross-site request forgery (CSRF) attacks. The [Form Tag Helper](../../mvc/views/working-with-forms.md#the-form-tag-helper) method automatically injects the token into the view. The token is also included when the user submits the form. The `ValidateAntiForgeryToken` attribute checks the token. For more information, see t[Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core](../../security/anti-request-forgery.md) and [FormTagHelper Class](/dotnet/api/microsoft.aspnetcore.mvc.taghelpers.formtaghelper) reference.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The `ValidateAntiForgeryToken` attribute helps prevent cross-site request forgery (CSRF) attacks. The [Form Tag Helper](../../mvc/views/working-with-forms.md#the-form-tag-helper) method automatically injects the token into the view. The token is also included when the user submits the form. The `ValidateAntiForgeryToken` attribute checks the token. For more information, see t[Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core](../../security/anti-request-forgery.md) and [FormTagHelper Class](/dotnet/api/microsoft.aspnetcore.mvc.taghelpers.formtaghelper) reference.
The `ValidateAntiForgeryToken` attribute helps prevent cross-site request forgery (CSRF) attacks. The [Form Tag Helper](../../mvc/views/working-with-forms.md#the-form-tag-helper) method automatically injects the token into the view. The token is also included when the user submits the form. The `ValidateAntiForgeryToken` attribute checks the token. For more information, see [Prevent Cross-Site Request Forgery (XSRF/CSRF) attacks in ASP.NET Core](../../security/anti-request-forgery.md) and [FormTagHelper Class](/dotnet/api/microsoft.aspnetcore.mvc.taghelpers.formtaghelper) reference.

Removed a typo of "t" in "t[Prevent"

| Date descending | Ascending | Ascending |

The method uses LINQ to Entities to specify the column to sort by. The code creates an `IQueryable` variable before the switch statement, modifies it in the switch statement, and calls the `ToListAsync` method after the `switch` statement. When you create and modify `IQueryable` variables, no query is sent to the database. The query isn't executed until you convert the `IQueryable` object into a collection by calling a method such as `ToListAsync`. Therefore, this code results in a single query that's not executed until the `return View` statement.
The method uses `LINQ` statements to student entities to specify the column to sort by. The code creates an `IQueryable` variable before the `switch` statement, modifies it in the `switch` statement, and calls the `ToListAsync` method after the `switch` statement. When you create and modify `IQueryable` variables, no query is sent to the database. The query isn't executed until you convert the `IQueryable` object into a collection by calling a method such as `ToListAsync`. Therefore, this code results in a single query that isn't executed until the `return View` statement.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The method uses `LINQ` statements to student entities to specify the column to sort by. The code creates an `IQueryable` variable before the `switch` statement, modifies it in the `switch` statement, and calls the `ToListAsync` method after the `switch` statement. When you create and modify `IQueryable` variables, no query is sent to the database. The query isn't executed until you convert the `IQueryable` object into a collection by calling a method such as `ToListAsync`. Therefore, this code results in a single query that isn't executed until the `return View` statement.
The method uses LINQ to Entities to specify the column to sort by. The code creates an `IQueryable` variable before the `switch` statement, modifies it in the `switch` statement, and calls the `ToListAsync` method after the `switch` statement. When you create and modify `IQueryable` variables, no query is sent to the database. The query isn't executed until you convert the `IQueryable` object into a collection by calling a method such as `ToListAsync`. Therefore, this code results in a single query that isn't executed until the `return View` statement.

"LINQ to Entities" is a specific term, it is the LINQ provider for Entity Framework. "LINQ statements to student entities" is not a meaningful phrase and loses the technical reference. Additionally, LINQ should not be in backticks; it's a technology name, not a code symbol.

You can disable tracking of entity objects in memory by calling the `AsNoTracking` method. Here are some of the common scenarios for this action:

* During the context lifetime you don't need to update any entities, and you don't need EF to [automatically load navigation properties with entities retrieved by separate queries](read-related-data.md). Frequently these conditions are met in a controller's HttpGet action methods.
* During the context lifetime, you don't need to update any entities, and you don't need Entity Framework to [automatically load navigation properties with entities retrieved by separate queries](read-related-data.md). These conditions are frequently met in a controller's HttpGet `Action` methods.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* During the context lifetime, you don't need to update any entities, and you don't need Entity Framework to [automatically load navigation properties with entities retrieved by separate queries](read-related-data.md). These conditions are frequently met in a controller's HttpGet `Action` methods.
* During the context lifetime, you don't need to update any entities, and you don't need Entity Framework to [automatically load navigation properties with entities retrieved by separate queries](read-related-data.md). These conditions are frequently met in a controller's HttpGet action methods.

Putting Action in backticks implies the Action class or attribute in ASP.NET Core. In this case it is referring to controller methods that respond to HTTP requests so keep "action methods" in lowercase, no backticks.

# Tutorial: Add sorting, filtering, and paging - ASP.NET MVC with EF Core

In the previous tutorial, you implemented a set of web pages for basic CRUD operations for Student entities. In this tutorial you'll add sorting, filtering, and paging functionality to the Students Index page. You'll also create a page that does simple grouping.
In the previous tutorial, you implemented a set of web pages for basic CRUD operations for Student entities. You created an MVC application that stores and displays data by using the [Entity Framework (EF) Core](/ef/core/)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In the previous tutorial, you implemented a set of web pages for basic CRUD operations for Student entities. You created an MVC application that stores and displays data by using the [Entity Framework (EF) Core](/ef/core/)
In the previous tutorial, you implemented a set of web pages for basic CRUD operations for Student entities. In this tutorial, you add sorting, filtering, and paging functionality to the Students Index page. You also create a page that does simple grouping.

The last sentance contains content that belongs in the previous tutorial's intro, not this one. I removed the orphaned sentence about creating the MVC application (that's from the first tutorial, not the previous one) and reestored the grouping mention.

Copy link
Copy Markdown
Contributor

@wadepickett wadepickett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GitHubber17, Great work! I provided some suggestions.

If you find them helpful as is, please hit "Apply Suggestion" so reviewer suggestions get added as a commit. However if your process reqiuires that you re-enter reviewer changes locally as your own commit, I understand and no worries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants