Notice the 2nd url, there is no action method. Here
- Shares is the action name
- 2 is the item id
- what-is-mind-industries - is the title of item
In normal scenarios, this is not possible however we will learn how to do above in ASP.NET Core.
Modify Startup.cs routes
Look at the 1st MapRoute, I have created a new MapRoute with "Shares" as explicit word in the URL. The 2nd MapRoute is default. When a URL that starts with /Shares/{with a digit}/{and with a title} is requested, the 1st MapRoute executes otherwise 2nd MapRoutes executes.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "Shares",
template: "Shares/{id}/{title}",
defaults: new { controller = "Shares", action = "Index" });
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"
);
Create a custom attribute
Now, create a custom attribute named RequiredParameter
that inherits ActionMethodSelectorAttribute
.
In below code snippet, we have a property named ValueName
. In the constructor, we its property that is set when this custom attribute is used.
We also need to override IsValidForRequest
method. Here we are checking if the requested url contains the route parameter we are passing. Based on this, it returns true or false.
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Routing;
public class RequiredParameterAttribute : ActionMethodSelectorAttribute
{
public RequiredParameterAttribute(string valueName)
{
ValueName = valueName;
}
public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
{
var isTrue = routeContext.RouteData.Values[ValueName] != null;
return isTrue;
}
public string ValueName { get; private set; }
}
If this method returns true, the action method that uses this attribute executes.
Using custom attribute in the action method
In below code snippet, notice that we two method with the same name but different parameters. Notice that both method are HttpGet method (default, if you do not specify method type, its HttpGet).
In the 2nd method, we are using RequiredParameter
custom attribute that we have created in the above code snippet. We are passing "id" as parameter to this attribute.
// GET: Forums
public async Task<IActionResult> Index()
{
return View(await _context.Forums.ToListAsync());
}
[RequiredParameter("id")]
public async Task<IActionResult> Index(int id, string title)
{
return View("IndexList", await _context.Forums.ToListAsync());
}
Now when we request
- http://localhost:44304/Shares - as the URL doesn't contains the id parameter so the 1st method executes. This intern return "Index" view.
- http://localhost:44304/Shares/2/what-is-minda-industries - as the URL contains id value as 2 and title is what-is-minda-industries so the custom attribute returns true and this method executes and returns "IndexList" view.
The use of Custom attributes are very vast and it can be used in many scenarios, this is one of the use of custom attribute that help us making the URL look nice, small and easily readable.