2. How to use the default route……
This chapter begins by showing how to configure and use
the default route for an ASP.NET Core MVC app. When you
begin developing an app, it’s common to start with this
route.
ASP.NET Core 2.2 introduced a new approach to routing
known as end point routing. It’s generally considered a
best practice to use endpoint routing for all new
development . Before you can use endpoint routing, you
need to add the necessary MVC services to the app. Then,
you need to mark where the routing decisions are made
and configure the end points for each route a Startup .
How to configure the default route…..
3. cs file that configures the default route for an ASP
.NET Core MVC
app To do that, it uses a routing system known as endpoint routing
that was introduced in ASP
.
NET Core 2.2 and is recommended for development with ASP
.
NET Core 3.0 and late development with ASP
.NET Core 3.0 and later.
Before you can use endpoint routing, you need to add the necessary MVC
services to the app .
To do that, you can add one or more statements to the Configure Services()
method.
With ASP
.NET Core 3.0 and later, you can call the Add Controllers With Views
Prior to ASP
.NET Core 2.2, you had to use the Add Mvc() method to add
these services.
However, this included some services such as Razor pages that aren’t
typically necessary for an MVC app.
As a result, unless you need these services in your MVC app, it’s better to
use the Add Controllers With Views() method to add MVC services.
4. After you add the necessary services, you need to configure the routing. To
do that:
First, you call the
Use Routing()
method to mark
where the routing
decisions are
made
Then, you call
the Use
Endpoints()
method to
configure the
endpoints for
each route
can add any
services that you
want to run after
routing decisions
have been made
but before they
have been
executed. This
typically includes
the services for
5. The method for adding the MVC service
Two methods for enabling and configuring routing
6. Two methods in the Startup.cs file that configure the
default route:
// Use this method to add services to the project.
public void ConfigureServices(IServiceCollection services) {
services.AddControllersWithViews(); // add MVC services
//add other services here
}
// Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
app.UseDeveloperExceptionPage();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting(); // mark where routing decisions are made
// configure middleware that runs after routing decisions have been made
app.UseEndpoints(endpoints => // map the endpoints
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
// configure other middleware here
}
services.AddCont
}
7. Another way to map a controller to the default route ::
endpoints.MapDefaultControllerRoute()
<Description>
ASP
.NET Core 2.2 introduced a new approach to routing known as
endpoint routing. It’s generally considered a best practice to use endpoint
routing for all new development.
Before you can use endpoint routing, you need to add the necessary MVC
services to the app. Then, you need to mark where the routing decisions
are made and configure the
endpoints for each route.
8. A URL that has three segments:
The pattern for the default route:
{controller=Home}/{action=Index}/{id?}
How the default route works
The first segment specifies the controller. Since the pattern sets the Home
controller as the default controller, this segment is optional.
The second segment specifies the action method within the controller.
controller. Since the pattern sets the Index() method as the default action,
this segment is optional.
The third segment specifies an argument for the id parameter of the
action method.
The pattern uses a question mark (?) to specify that this segment is
optional
9. Description
The default route maps a request to an action method within a
controller and can optionally pass an argument to that action method
10. later segment, you must also supply values for the
earlier segments:
The table of request URLs shows how this works. Here, the first URL doesn’t
specify any of the three segments. As a result, the app routes the request to
the Index() method of the Home controller and it doesn’t pass an argument
to the id parameter of this method.
Later in the table, the seventh URL specifies all three segments. As a result,
the app routes the request to the List() method of the Product controller
and passes an argument of “Guitars” to the id parameter of this method.
This table assumes that the List() method defines the id parameter as a
string and doesn’t provide a default value for this parameter. As a result, if
the URL.
11. doesn’t specify a third segment for the List() method, it sets the id
parameter to null. Similarly, this table assumes that the Detail() method
defines the id parameter as an int and doesn’t provide a default value for
this parameter.
As a result, if the URL doesn’t specify a third segment for the Detail()
method, it sets the id parameter to the default int value of 0.
How the default route works:
Home
specifies the controller.
Since the pattern sets the
Home controller
as the default controller,
this segment is optional
Index
specifies the action
method within the
controller. Since the
pattern sets the Index()
method as the default
action, this segment is
optional.
Joel
specifies an argument for
the id parameter of the
action method.
The pattern uses a
question mark (?) to
specify that this segment
is optional
12. The Home controller:
using Microsoft.AspNetCore.Mvc;
namespace GuitarShop.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return Content("Home controller, Index action");
}
public IActionResult About()
{
return Content("Home controller, About action");
}
}
}
13. A browser after requesting the default page:
A browser after requesting the Home/About
page:
14. Description:
The class for an MVC controller typically inherits the Controller class from
Microsoft’s AspNetCore.Mvc namespace.
The action methods for a controller typically return an object that
implements the IActionResult interface such as a ContentResult or ViewResult
object.
To create a simple controller, you can begin by coding action methods that
use the Content() method to return ContentResult objects that contain plain
text.
To test a controller, you can run the app and enter a URL in the browser’s
address bar
15. How to code a controller named Product Controller that uses
the id segment of the default route. Here, the Product
controller begins much like the Home controller from the
previous figure.
However, both of its action methods provide a parameter
named id that maps to the id segment of the default route.
The List() method uses the string type for the id parameter
and provides a default value of “All”. • The Detail() method
uses the int type for the id parameter and does not provide a
default value.
16. The Product controller:
using Microsoft.AspNetCore.Mvc;
namespace GuitarShop.Controllers
{
public class Product Controller : Controller
{
public IActionResult List(string id = "All")
{
return Content("Product controller, List action, id: " + id);
}
public IActionResult Detail(int id)
{
return Content("Product controller, Detail action, id: " + id);
}
}
}
17. A browser after requesting the Product/List action with no id
segment
A browser after requesting the Product/Detail action with an id
segment
A browser after requesting the Product/Detail action with no id
segment
18. Description:
The List() method uses the string type for the id parameter and provides
a default value of “All”.
The Detail() method uses the int type for the id parameter and does not
provide a default value.
Now that you understand how the default route works, you’re ready to learn
how to create custom routes. One way to do that is to add static content to
a route.
How to create custom routes:
19. A pattern that mixes static and dynamic data for a segment:::
{controller}/{action}/{cat}/Page{num} // 4 segments
Example URLs:::
The List() method of the Product controller
public IActionResult List(string cat, int num)
{
return Content("Product controller, List action, " +
"Category " + cat + ", Page " + num);
}
20. A URL that requests Product/List action for page 1 of all
categories:::
A pattern that supplies one segment that’s completely static
{controller}/{action}/ {cat}/Page/{num} // 5 segment
Example URLs
A URL that requests Product/List action for page 1 of all
categories
21. Description::
To include static content as part of a segment, you
can use a string literal to provide the static part of
the segment and use braces to identify the dynamic
part of the segment.
To include a static segment, you can code a string
literal for the entire segment.
22. Code that maps three routing patterns to controllers
app.UseEndpoints(endpoints =>
{
// most specific route – 5 required segments
endpoints.MapControllerRoute(
name: "paging_and_sorting",
pattern: "{controller}/{action}/{id}/page{page}/sort-by-{sortby}");
// specific route – 4 required segments
endpoints.MapControllerRoute(
name: "paging",
pattern: "{controller}/{action}/{id}/page{page}");
// least specific route – 0 required segments
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
23. The List() method of the Product controller
public IActionResult List(string id = "All", int page = 1,
string sortby = "Price")
{
return Content("id=" + id + ", page=" + page + ", sortby=" + sortby);
}
Examples that use the default route:
24. Examples that uses the paging route::
Example URLs that use the paging_and_sorting
Route::
Description
When you map multiple routing patterns, you must code the most specific ones first and the
most general one last. If you code the most general pattern first, it will process all URLs
25. How to use attribute routing
So far, this chapter has shown how to use the Startup.cs file to specify
the routing patterns for an app. However, you can override this routing
by adding Route attributes to the action methods of a controller or to
the class for the controller. This is known as attribute routing.
Figure 6-7 starts by showing the class for the Home controller after attribute
routing has been applied to its Index() and About() actions. To change the
routing for the Index() action, this code places a Route attribute directly above
the Index() method and specifies a route of “/”. This maps the Index() action to a
URL that requests the root folder of the app. Similarly, this code places a Route
attribute directly above the About() method that maps the About() action to a
request URL of “About”.
How to change the routing for an action
26. The Home controller with attribute routing for
both actions:
public class HomeController : Controller
{
[Route("/")]
public IActionResult Index()
{
return Content("Home controller, Index action");
}
[Route("About")]
public IActionResult About()
{
return Content("Home controller, About action");
}
}
27. How request URLs map to controller classes and their action
methods:
Two default routes that are overridden by the
attribute routing::: /Home/Index
/Home/About
Two tokens you can use to insert variable data
into a route:
Description
To change the routing for an
action, you can code a Route
attribute directly above the
action method. Then, the
route specified by the
attribute overrides the route
that’s specified in the
Startup.cs file. This is known
as attribute routing.
To specify a static route, you
can code a string literal
within the Route attribute.
To insert the name of the
current controller or action
into a route, you can use the
[controller] or [action]
tokens.
28. The Product controller with attribute routing that
specifies segments:
public class ProductController : Controller
{
[Route("Products/{cat?}")]
public IActionResult List(string cat = "All")
{
return Content("Product controller, List action, Category: " + cat);
}
[Route("Product/{id}")]
public IActionResult Detail(int id)
{
return Content("Product controller, Detail action, ID: " + id);
}
[NonAction]
public string GetSlug(string name)
{
return name.Replace(' ', '-').ToLower();
}
}
29. How request URLs map to controller classes and
their action methods:
Two default routes that are overridden by the attribute routing
/Product/List
/Product/Detail
A more flexible way to code the attribute for the Product/List action
[Route("[controller]s/{cat?}")]
A more flexible way to code the attribute for the Product/Detail action
[Route("[controller]/{id}")
30. Description
To insert other segments into a route, you can use all of the skills for coding
coding segments such as the skills described earlier in this chapter.
If a controller contains methods that aren’t action methods, you can code the
NonAction attribute above it to prevent it from being mapped to a URL.
How to change the routing for a controller :::
In the last two figures, you learned how to use attribute routing to override the
routing for a single action in a controller. However, it’s also possible to use
attribute routing to override the routing for all actions within a controller. To do
that, you can code a Route attribute directly above the declaration for the
controller’s class as shown in figure 6-9.
31. The code for the Product controller::
[Route("Retail/[controller]/[action]/{id?}")]
public class Product Controller : Controller
{
public Iaction Result List(string id = "All")
{
return Content("Product controller, List action, Category: " + id);
}
public Iaction Result Detail(int id)
{
return Content("Product controller, Detail action, ID: " + id);
}
}
32. How request URLs map to controller classes and
their action methods
Two default routes that are overridden by the
attribute routing:
/Product/List /Product/Detail
Description
To change the
routing for all
actions in a
controller, you can
code a Route
attribute directly
above the
declaration for the
controller’s class.
33. Best practices for URLs :::
o Keep the URL as short as possible while still being descriptive and user-
friendly.
o Use keywords to describe the content of a page, not implementation
details.
o Make your URLs easy for humans to understand and type.
o Use hyphens to separate words, not other characters, especially spaces.
o Prefer names as identifiers over numbers.
o Create an intuitive hierarchy.
o Be consistent.
o Avoid the use of query string parameters if possibl.
34. A URL that identifies a product…
With a number
https://www.domain.com/product/1307
With a name
https://www.domain.com/product/fender-special-edition-standard-
stratocaster
With a number and name (to keep it descriptive but short)
https://www.domain.com/product/1307/fender-specia
35. Four URLs that use query strings to pass data (not
recommended)
https://www.murach.com/p/List?
/p/List?catId=1
/p/List?catId=1&pg=1
/p/Detail?id=1307
Four URLs that follow best practices
https://www.murach.com/product/list
/product/list/guitars
/product/list/guitars/page-1
/product/detail/1307/fender-stratocaster
Four URLs that follow best practices, but are even shorter
https://www.murach.com/products
/products/guitars
/products/guitars/page-1
/product/1307/fender-stratocaste
36. Description
Well-designed URLs can improve the usability of your app
for both developers and end users.
Well-designed URLs can improve the search engine
optimization (SEO) for your app.
A slug is a string that describes the content of a page. Using
a slug can make your URLs more user-friendly.
Using hyphens to separate words is known as kebab case.
37. How to work with areas:
An ASP
.NET Core MVC app can have multiple areas.
Each area can have its own controllers, models, and
views. This can help you organize the folders and files of
an app.
For example, you may want to create one area that
allows administrators to perform tasks such as adding
and updating the products that are stored in a database.
Then, you can use another area to allow customers to
browse through the products and add them to a cart.
38. How to set up areas ??
Figure 6-11 shows how to set up areas. By convention, you
can create an area by adding a folder named Areas to the root
folder for the app.
Then, within the Areas folder, you can add a folder for the area.
In this figure, for example, the folders and files for the Guitar
Shop appinclude an area named Admin.
Within the folder for the area, you can add the necessary
subfolders such as the Controllers, Models, Views, and so on.
39. The starting folders for a Guitar Shop app that
includes an Admin area…
GuritarShop
/Areas
/Admin
/Controllers
/HomeController.cs
/ProductController.cs
/Views
/Home
/Index.cshthml
/Product
/List.cshthml
/AddUpdate.cshthml
/Delete.cshthml
/Shared
/_AdminLayout.cshtml
_ViewImports.cshtml
_ViewStart.cshtml
41. Aroute in the Startup.cs file that works with an
area
app.UseEndpoints(endpoints =>
{
endpoints.MapAreaControllerRoute(
name: "admin",
areaName: "Admin",
pattern: "Admin/{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Description::
An ASP
.NET Core MVC app can have multiple areas. Each area can have its own
controllers, models, and views. This can help you organize the folders and files of an app.
To configure the route for an area, you can use the MapAreaControllerRoute()
method to add a route that specifies the name of the area and its routing pattern
42. The Home controller for the Admin area ::
namespace Guitar Shop .Areas .Admin .Controllers
{
[Area("Admin")]
public class Home Controller : Controller
{
public IactionResult Index()
{
return View(); //map to/Areas/Admin/Views/Home/Index.cshtml
}
}
}
43. A token you can use to insert the area into a route ::
The Product conareatroller for the Admin ::
namespace Guitarshop .Areas . Admin . Controllers
{
[Area("Admin")]
public class Productcontroller : Controller
{
[Route("[area]/[controller]s/{id?}")]
public Iactionresult List(string id = "All") {...};
public IactionResult Add() {...};
public IactionResult Update(int id) {...};
public IactionResult Delete(int id) {...};
}
}
44. How reauest URLs map to controller classes and their action methods ::
Description
Before you can use a controller with an area, you must use the Area
attribute to associate it with an area.
After you add the Area attribute to the controller, you can use the [area]
token to specify attribute routing for the controller.
45. endpoint routing
URL path segment
default route
attribute routing
slug
kebab case
areas of an app
Terms:
46. Summary:
ASP
.NET Core 2.2 introduced a new approach to routing known as
endpoint routing. With ASP
.NET Core 3.0 and later, it’s generally
considered a best practice to use endpoint routing.
The path for a URL consists of zero or more segments where each
segment is separated by a slash (/).
The default route maps a request to an action method within a controller
and can optionally pass an argument to that action method.
Using the Route attribute to specify the routing for a controller or its
actions is known as attribute routing. Attribute routing overrides any
routing patterns specified in the Startup .cs file.
A slug is a string that describes the content of a page.
Using hyphens to separate words is known as kebab case.
An ASP
.NET Core MVC app can have multiple areas. Each area can
have its own controllers, models, and views
47. Exercise 6-1 Practice routing
View and test the default route for the app :
1- Open the Ch06Ex1RoutingPractice web app in the ex_ starts
directory.
2- Open the Startup .cs file and view its code. Note that it includes the
default route: {controller=Home}/{action=Index}/{id?} .
3- Open the Home Controller class in the Controllers folder and view its
code. Note that the Index() action method displays text that says “Home”
and the Privacy() action method displays text that says “Privacy”
48. 4- Run the app. This should start your browser and automatically call this
URL: https://localhost:5001 This should display text that says, “Home”.
5- Enter URLs in the browser to display the text returned by the Index() and
Privacy() methods. For example, try these URLs: https://localhost:5001/home
https://localhost:5001/home/privacy.
6- In the Home Controller class, view the code for the Display() action
method. Note that this method accepts a string parameter named id.
Review the code that works with this parameter.
49. 7- Run the app and test the Display() method by entering these URLs:
<https://localhost:5001/home/display>
<https://localhost:5001/home/display/123abc>
The first URL should display a message that indicates that the id hasn’t been supplied, and the
second URL should display a message that says, “ID: 123abc”
* Add an action method that uses the default route
8- In the Home Controller class, add the following action method. When you do, make sure to
declare a parameter of the int type with a name of id and a default value of 0 like this:
public Iaction Result Countdown(int id = 0)
{
string content String = "Counting down:n";
for(int i = id; i >= 0; i --)
{
content String += i+ "n";
}
return Content(content String);
}
50. 9- Run the app and enter a URL that calls the Countdown() method like this:
<https://ocalhost:5001/home/countdown >
This should display “Counting down:” followed by a 0 on the next line. That’s
because the URL omits the optional third segment of the default route. As a
result, the method uses the default value of 0 for the id parameter.
10- Run the app and enter a URL that calls the Countdown() method like this:
<https://localhost:5001/home/countdown/10 >
This should display a countdown that starts at 10 and counts down to 0 with
each integer on its own line. That’s because the URL included a value of 10
for the third segment.
51. Use attribute routing to customize the route for an action
method:
11- Add a Route attribute immediately above the Countdown() method like
this:
[Route("[action]/{id?}")]
public Iaction Result Countdown( int id = 0) {...}
12- Run the app and enter a URL that calls the Countdown() method like
this:
<https://localhost:5001/countdown/10>
Note that you only have to type the name of the action (countdown) and
the value of the id segment (10) in this URL, not the name of the controller
(home).
52. 13- In the Countdown() method, change the name of the parameter from id
to num. However, in the Route attribute, continue to use id as the name of
the second segment.
14- Run the app and test the Countdown() method without an id segment. It
should work correctly.
15- Test the Countdown() method with an id segment of 10 as before. This
should only display the default value of 0. That’s because the segment name
in the Route attribute must match the parameter name in the method.
16- In the Route attribute, change the second segment from {id?} to {num?}
17- Run the app and test the Count Down() method with a second segment
of 10. This should display a countdown from 10 to 0.
53. Add more segments to a route:
18- Edit the Route attribute for the Countdown() method like this:
[Route("[action]/{start}/{end?}/{message?}")]
public Iaction Result Countdown(int start, int end = 0,
string message = "")
Note that the segment names in the Route attribute match the parameter
parameter names in the action method and that the first two segments are
required but the third and fourth are optional.
54. 19- Modify the code for the Countdown() method so it starts counting down
at the start parameter, ends at the end parameter, and displays the message
param eter when the countdown is done.
20- Run the app and enter a URL that calls the Countdown() method like
this:
<https://localhost:5001/countdown/3/1/Liftoff!>
This should display a countdown like this:
Counting down:
3
2
1
Liftoff!
55. 21- Enter a URL that calls the Countdown() method like this:
<https://localhost:5001/countdown>
The browser should not be able to find the web page. That’s because the second
segment is now required. As a result, you must specify the start segment when you
enter this URL.
22- Enter a URL that calls the Countdown() method like this:
<https://localhost:5001/countdown/5 >
This should use the default parameters of the Countdown method to display a
countdown from 5 to 0 with no message