Skip to content

Commit f39106a

Browse files
Update MVC tutorial series for .NET 10 and Visual Studio 2026 (#36664)
* Initial plan * Update Part 1 (start-mvc.md) to .NET 10 and Visual Studio 2026 Co-authored-by: meaghanlewis <10103121+meaghanlewis@users.noreply.github.com> * Update Parts 2-10 to .NET 10 moniker ranges and dates Co-authored-by: meaghanlewis <10103121+meaghanlewis@users.noreply.github.com> * Add .NET 10 static folders and validation include file Co-authored-by: meaghanlewis <10103121+meaghanlewis@users.noreply.github.com> * Add EF NuGet CLI include file for .NET 10 Co-authored-by: meaghanlewis <10103121+meaghanlewis@users.noreply.github.com> * update get started * update add controller * update add view * update add model * edit images * update work with a database * update controller methods and views * update search page * update search images * update new field page * update validation page * update images * update details page * fix warnings * add updated code samples * fix policheck errors * attempt 2 at policheck errors --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: meaghanlewis <10103121+meaghanlewis@users.noreply.github.com> Co-authored-by: Meaghan Osagie <mosagie@microsoft.com>
1 parent 6704140 commit f39106a

153 files changed

Lines changed: 79437 additions & 186 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Run the following .NET CLI commands:
2+
3+
```dotnetcli
4+
dotnet tool uninstall --global dotnet-aspnet-codegenerator
5+
dotnet tool install --global dotnet-aspnet-codegenerator
6+
dotnet tool uninstall --global dotnet-ef
7+
dotnet tool install --global dotnet-ef
8+
dotnet add package Microsoft.EntityFrameworkCore.Design
9+
dotnet add package Microsoft.EntityFrameworkCore.SQLite
10+
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
11+
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
12+
dotnet add package Microsoft.EntityFrameworkCore.Tools
13+
```
14+
15+
The preceding commands add:
16+
* The [command-line interface (CLI) tools for EF Core](/ef/core/miscellaneous/cli/dotnet)
17+
* The [aspnet-codegenerator scaffolding tool](xref:fundamentals/tools/dotnet-aspnet-codegenerator).
18+
* Design time tools for EF Core
19+
* The EF Core SQLite provider, which installs the EF Core package as a dependency.
20+
* Packages needed for scaffolding: `Microsoft.VisualStudio.Web.CodeGeneration.Design` and `Microsoft.EntityFrameworkCore.SqlServer`.
21+
22+
For guidance on multiple environment configuration that permits an app to configure its database contexts by environment, see <xref:fundamentals/environments#environment-based-startup-class-and-methods>.
23+
24+
[!INCLUDE[](~/includes/dotnet-tool-install-arch-options.md)]
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
* [Visual Studio 2026](https://visualstudio.microsoft.com/downloads/) with the **ASP.NET and web development** workload.
1+
* [The latest version of Visual Studio](https://visualstudio.microsoft.com/downloads/) with the **ASP.NET and web development** workload.
22

3-
:::image type="content" source="~/tutorials/min-web-api/_static/asp-net-web-dev-2026.png" alt-text="VS22 installer workloads" lightbox="~/tutorials/min-web-api/_static/asp-net-web-dev-2026.png":::
3+
:::image type="content" source="~/tutorials/min-web-api/_static/asp-net-web-dev-2026.png" alt-text="VS26 installer workloads" lightbox="~/tutorials/min-web-api/_static/asp-net-web-dev-2026.png":::

aspnetcore/tutorials/first-mvc-app/adding-controller.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: Part 2, add a controller to an ASP.NET Core MVC app
33
author: wadepickett
44
description: Part 2 of tutorial series on ASP.NET Core MVC.
55
ms.author: wpickett
6-
ms.date: 03/26/2025
6+
ms.date: 01/22/2026
77
monikerRange: '>= aspnetcore-3.1'
88
uid: tutorials/first-mvc-app/adding-controller
99
---
@@ -12,9 +12,7 @@ uid: tutorials/first-mvc-app/adding-controller
1212

1313
[!INCLUDE[](~/includes/not-latest-version.md)]
1414

15-
By [Rick Anderson](https://twitter.com/RickAndMSFT)
16-
17-
:::moniker range=">= aspnetcore-9.0"
15+
:::moniker range=">= aspnetcore-10.0"
1816

1917
The Model-View-Controller (MVC) architectural pattern separates an app into three main components: **M**odel, **V**iew, and **C**ontroller. The MVC pattern helps you create apps that are more testable and easier to update than traditional monolithic apps.
2018

@@ -44,25 +42,25 @@ These concepts are introduced and demonstrated in this tutorial series while bui
4442

4543
In **Solution Explorer**, right-click **Controllers > Add > Controller**.
4644

47-
![Solution Explorer, right click Controllers > Add > Controller](~/tutorials/first-mvc-app/adding-controller/_static/9/add-controller-VS22-17.11.0.png)
45+
:::image type="content" source="~/tutorials/first-mvc-app/adding-controller/media/add-controller.png" alt-text="Solution Explorer, right click Controllers > Add > Controller.":::
4846

4947
In the **Add New Scaffolded Item** dialog box, select **MVC Controller - Empty** > **Add**.
5048

51-
![Add MVC controller](~/tutorials/first-mvc-app/adding-controller/_static/9/add-scaffolded-item-controller-VS22-17.11.0.png)
49+
:::image type="content" source="~/tutorials/first-mvc-app/adding-controller/media/add-new-scaffolded-item.png" alt-text="Add MVC controller.":::
5250

5351
In the **Add New Item - MvcMovie** dialog, enter *`HelloWorldController.cs`* and select **Add**.
5452

5553
# [Visual Studio Code](#tab/visual-studio-code)
5654

5755
Select the **EXPLORER** icon and then control-click (right-click) **Controllers > New File** and name the new file `HelloWorldController.cs`.
5856

59-
![Contextual menu](~/tutorials/first-mvc-app-xplat/adding-controller/_static/new_fileVSC1.51.png)
57+
:::image type="content" source="~/tutorials/first-mvc-app-xplat/adding-controller/_static/new_fileVSC1.51.png" alt-text="Contextual menu.":::
6058

6159
---
6260

6361
Replace the contents of `Controllers/HelloWorldController.cs` with the following code:
6462

65-
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/mvcmovie90/Controllers/HelloWorldController.cs?name=snippet_First)]
63+
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/mvcmovie10/Controllers/HelloWorldController.cs?name=snippet_First)]
6664

6765
Every `public` method in a controller is callable as an HTTP endpoint. In the sample above, both methods return a string. Note the comments preceding each method.
6866

@@ -82,15 +80,15 @@ Run the app without the debugger by pressing <kbd>Ctrl</kbd>+<kbd>F5</kbd>.
8280

8381
Append `/HelloWorld` to the path in the address bar. The `Index` method returns a string.
8482

85-
![Browser window showing an app response of This is my default action](~/tutorials/first-mvc-app/adding-controller/_static/9/hello1.png)
83+
:::image type="content" source="~/tutorials/first-mvc-app/adding-controller/_static/9/hello1.png" alt-text="Browser window showing an app response of This is my default action.":::
8684

8785
MVC invokes controller classes, and the action methods within them, depending on the incoming URL. The default [URL routing logic](xref:mvc/controllers/routing) used by MVC, uses a format like this to determine what code to invoke:
8886

8987
`/[Controller]/[ActionName]/[Parameters]`
9088

9189
The routing format is set in the `Program.cs` file.
9290

93-
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie90/Program.cs?name=snippet_MapControllerRoute&highlight=3)]
91+
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie10/Program.cs?name=snippet_MapControllerRoute&highlight=3)]
9492

9593
When you browse to the app and don't supply any URL segments, it defaults to the "Home" controller and the "Index" method specified in the template line highlighted above. In the preceding URL segments:
9694

@@ -102,13 +100,13 @@ Browse to: `https://localhost:{PORT}/HelloWorld/Welcome`. Replace `{PORT}` with
102100

103101
The `Welcome` method runs and returns the string `This is the Welcome action method...`. For this URL, the controller is `HelloWorld` and `Welcome` is the action method. You haven't used the `[Parameters]` part of the URL yet.
104102

105-
![Browser window showing an application response of This is the Welcome action method](~/tutorials/first-mvc-app/adding-controller/_static/9/welcome.png)
103+
:::image type="content" source="~/tutorials/first-mvc-app/adding-controller/_static/9/welcome.png" alt-text="Browser window showing an application response of This is the Welcome action method.":::
106104

107105
Modify the code to pass some parameter information from the URL to the controller. For example, `/HelloWorld/Welcome?name=Rick&numtimes=4`.
108106

109107
Change the `Welcome` method to include two parameters as shown in the following code.
110108

111-
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/mvcmovie90/Controllers/HelloWorldController.cs?name=snippet_Second)]
109+
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/mvcmovie10/Controllers/HelloWorldController.cs?name=snippet_Second)]
112110

113111
The preceding code:
114112

@@ -120,7 +118,7 @@ Run the app and browse to: `https://localhost:{PORT}/HelloWorld/Welcome?name=Ric
120118

121119
Try different values for `name` and `numtimes` in the URL. The MVC [model binding](xref:mvc/models/model-binding) system automatically maps the named parameters from the query string to parameters in the method. See [Model Binding](xref:mvc/models/model-binding) for more information.
122120

123-
![Browser window showing an application response of Hello Rick, NumTimes is\: 4](~/tutorials/first-mvc-app/adding-controller/_static/9/rick4.png)
121+
:::image type="content" source="~/tutorials/first-mvc-app/adding-controller/_static/9/rick4.png" alt-text="Browser window showing an application response of Hello Rick, NumTimes is 4.":::
124122

125123
In the previous image:
126124

@@ -131,7 +129,7 @@ In the previous image:
131129

132130
Replace the `Welcome` method with the following code:
133131

134-
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie90/Controllers/HelloWorldController.cs?name=snippet_Third)]
132+
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie10/Controllers/HelloWorldController.cs?name=snippet_Third)]
135133

136134
Run the app and enter the following URL: `https://localhost:{PORT}/HelloWorld/Welcome/3?name=Rick`
137135

@@ -141,7 +139,7 @@ In the preceding URL:
141139
* The `Welcome` method contains a parameter `id` that matched the URL template in the `MapControllerRoute` method.
142140
* The trailing `?` starts the [query string](https://wikipedia.org/wiki/Query_string).
143141

144-
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie90/Program.cs?name=snippet_MapControllerRoute&highlight=3)]
142+
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie10/Program.cs?name=snippet_MapControllerRoute&highlight=3)]
145143

146144
In the preceding example:
147145

@@ -155,6 +153,8 @@ In the preceding example:
155153
156154
:::moniker-end
157155

156+
[!INCLUDE[](~/tutorials/first-mvc-app/adding-controller/includes/adding-controller9.md)]
157+
158158
[!INCLUDE[](~/tutorials/first-mvc-app/adding-controller/includes/adding-controller8.md)]
159159

160160
[!INCLUDE[](~/tutorials/first-mvc-app/adding-controller/includes/adding-controller7.md)]
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
:::moniker range="= aspnetcore-9.0"
2+
3+
The Model-View-Controller (MVC) architectural pattern separates an app into three main components: **M**odel, **V**iew, and **C**ontroller. The MVC pattern helps you create apps that are more testable and easier to update than traditional monolithic apps.
4+
5+
MVC-based apps contain:
6+
7+
* **M**odels: Classes that represent the data of the app. The model classes use validation logic to enforce business rules for that data. Typically, model objects retrieve and store model state in a database. In this tutorial, a `Movie` model retrieves movie data from a database, provides it to the view or updates it. Updated data is written to a database.
8+
* **V**iews: Views are the components that display the app's user interface (UI). Generally, this UI displays the model data.
9+
* **C**ontrollers: Classes that:
10+
* Handle browser requests.
11+
* Retrieve model data.
12+
* Call view templates that return a response.
13+
14+
In an MVC app, the view only displays information. The controller handles and responds to user input and interaction. For example, the controller handles URL segments and query-string values, and passes these values to the model. The model might use these values to query the database. For example:
15+
16+
* `https://localhost:5001/Home/Privacy`: specifies the `Home` controller and the `Privacy` action.
17+
* `https://localhost:5001/Movies/Edit/5`: is a request to edit the movie with ID=5 using the `Movies` controller and the `Edit` action, which are detailed later in the tutorial.
18+
19+
Route data is explained later in the tutorial.
20+
21+
The MVC architectural pattern separates an app into three main groups of components: Models, Views, and Controllers. This pattern helps to achieve separation of concerns: The UI logic belongs in the view. Input logic belongs in the controller. Business logic belongs in the model. This separation helps manage complexity when building an app, because it enables work on one aspect of the implementation at a time without impacting the code of another. For example, you can work on the view code without depending on the business logic code.
22+
23+
These concepts are introduced and demonstrated in this tutorial series while building a movie app. The MVC project contains folders for the *Controllers* and *Views*.
24+
25+
## Add a controller
26+
27+
# [Visual Studio](#tab/visual-studio)
28+
29+
In **Solution Explorer**, right-click **Controllers > Add > Controller**.
30+
31+
![Solution Explorer, right click Controllers > Add > Controller](~/tutorials/first-mvc-app/adding-controller/_static/9/add-controller-VS22-17.11.0.png)
32+
33+
In the **Add New Scaffolded Item** dialog box, select **MVC Controller - Empty** > **Add**.
34+
35+
![Add MVC controller](~/tutorials/first-mvc-app/adding-controller/_static/9/add-scaffolded-item-controller-VS22-17.11.0.png)
36+
37+
In the **Add New Item - MvcMovie** dialog, enter *`HelloWorldController.cs`* and select **Add**.
38+
39+
# [Visual Studio Code](#tab/visual-studio-code)
40+
41+
Select the **EXPLORER** icon and then control-click (right-click) **Controllers > New File** and name the new file `HelloWorldController.cs`.
42+
43+
![Contextual menu](~/tutorials/first-mvc-app-xplat/adding-controller/_static/new_fileVSC1.51.png)
44+
45+
---
46+
47+
Replace the contents of `Controllers/HelloWorldController.cs` with the following code:
48+
49+
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/mvcmovie90/Controllers/HelloWorldController.cs?name=snippet_First)]
50+
51+
Every `public` method in a controller is callable as an HTTP endpoint. In the sample above, both methods return a string. Note the comments preceding each method.
52+
53+
An HTTP endpoint:
54+
55+
* Is a targetable URL in the web application, such as `https://localhost:5001/HelloWorld`.
56+
* Combines:
57+
* The protocol used: `HTTPS`.
58+
* The network location of the web server, including the TCP port: `localhost:5001`.
59+
* The target URI: `HelloWorld`.
60+
61+
The first comment states this is an [HTTP GET](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET) method that's invoked by appending `/HelloWorld/` to the base URL.
62+
63+
The second comment specifies an [HTTP GET](https://developer.mozilla.org/docs/Web/HTTP/Methods) method that's invoked by appending `/HelloWorld/Welcome/` to the URL. Later on in the tutorial, the scaffolding engine is used to generate `HTTP POST` methods, which update data.
64+
65+
Run the app without the debugger by pressing <kbd>Ctrl</kbd>+<kbd>F5</kbd>.
66+
67+
Append `/HelloWorld` to the path in the address bar. The `Index` method returns a string.
68+
69+
![Browser window showing an app response of This is my default action](~/tutorials/first-mvc-app/adding-controller/_static/9/hello1.png)
70+
71+
MVC invokes controller classes, and the action methods within them, depending on the incoming URL. The default [URL routing logic](xref:mvc/controllers/routing) used by MVC, uses a format like this to determine what code to invoke:
72+
73+
`/[Controller]/[ActionName]/[Parameters]`
74+
75+
The routing format is set in the `Program.cs` file.
76+
77+
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie90/Program.cs?name=snippet_MapControllerRoute&highlight=3)]
78+
79+
When you browse to the app and don't supply any URL segments, it defaults to the "Home" controller and the "Index" method specified in the template line highlighted above. In the preceding URL segments:
80+
81+
* The first URL segment determines the controller class to run. So `localhost:5001/HelloWorld` maps to the **HelloWorld** Controller class.
82+
* The second part of the URL segment determines the action method on the class. So `localhost:5001/HelloWorld/Index` causes the `Index` method of the `HelloWorldController` class to run. Notice that you only had to browse to `localhost:5001/HelloWorld` and the `Index` method was called by default. `Index` is the default method that will be called on a controller if a method name isn't explicitly specified.
83+
* The third part of the URL segment ( `id`) is for route data. Route data is explained later in the tutorial.
84+
85+
Browse to: `https://localhost:{PORT}/HelloWorld/Welcome`. Replace `{PORT}` with your port number.
86+
87+
The `Welcome` method runs and returns the string `This is the Welcome action method...`. For this URL, the controller is `HelloWorld` and `Welcome` is the action method. You haven't used the `[Parameters]` part of the URL yet.
88+
89+
![Browser window showing an application response of This is the Welcome action method](~/tutorials/first-mvc-app/adding-controller/_static/9/welcome.png)
90+
91+
Modify the code to pass some parameter information from the URL to the controller. For example, `/HelloWorld/Welcome?name=Rick&numtimes=4`.
92+
93+
Change the `Welcome` method to include two parameters as shown in the following code.
94+
95+
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/mvcmovie90/Controllers/HelloWorldController.cs?name=snippet_Second)]
96+
97+
The preceding code:
98+
99+
* Uses the C# optional-parameter feature to indicate that the `numTimes` parameter defaults to 1 if no value is passed for that parameter.
100+
* Uses `HtmlEncoder.Default.Encode` to protect the app from malicious input, such as through JavaScript.
101+
* Uses [Interpolated Strings](/dotnet/articles/csharp/language-reference/keywords/interpolated-strings) in `$"Hello {name}, NumTimes is: {numTimes}"`.
102+
103+
Run the app and browse to: `https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4`. Replace `{PORT}` with your port number.
104+
105+
Try different values for `name` and `numtimes` in the URL. The MVC [model binding](xref:mvc/models/model-binding) system automatically maps the named parameters from the query string to parameters in the method. See [Model Binding](xref:mvc/models/model-binding) for more information.
106+
107+
![Browser window showing an application response of Hello Rick, NumTimes is\: 4](~/tutorials/first-mvc-app/adding-controller/_static/9/rick4.png)
108+
109+
In the previous image:
110+
111+
* The URL segment `Parameters` isn't used.
112+
* The `name` and `numTimes` parameters are passed in the [query string](https://wikipedia.org/wiki/Query_string).
113+
* The `?` (question mark) in the above URL is a separator, and the query string follows.
114+
* The `&` character separates field-value pairs.
115+
116+
Replace the `Welcome` method with the following code:
117+
118+
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie90/Controllers/HelloWorldController.cs?name=snippet_Third)]
119+
120+
Run the app and enter the following URL: `https://localhost:{PORT}/HelloWorld/Welcome/3?name=Rick`
121+
122+
In the preceding URL:
123+
124+
* The third URL segment matched the route parameter `id`.
125+
* The `Welcome` method contains a parameter `id` that matched the URL template in the `MapControllerRoute` method.
126+
* The trailing `?` starts the [query string](https://wikipedia.org/wiki/Query_string).
127+
128+
[!code-csharp[](~/tutorials/first-mvc-app/start-mvc/sample/MvcMovie90/Program.cs?name=snippet_MapControllerRoute&highlight=3)]
129+
130+
In the preceding example:
131+
132+
* The third URL segment matched the route parameter `id` as defined in the routing template in the `Program.cs` file.
133+
* The `Welcome` method contains a parameter `id` that matched the URL template in the `MapControllerRoute` method.
134+
* The trailing `?` (in `id?`) indicates the `id` parameter is optional.
135+
136+
> [!div class="step-by-step"]
137+
> [Previous: Get Started](~/tutorials/first-mvc-app/start-mvc.md)
138+
> [Next: Add a View](~/tutorials/first-mvc-app/adding-view.md)
139+
140+
:::moniker-end
56 KB
Loading
22.2 KB
Loading

0 commit comments

Comments
 (0)