How to change a URL Link in ASP.NET MVC Breadcrumb
Problem Description:
I found a nice answer on creating breadcrumbs for this project here:
How can dynamic breadcrumbs be achieved with ASP.net MVC?
The modified code that I am using is here:
public static string BuildBreadcrumbNavigation(this HtmlHelper helper)
{
var result = string.Empty;
var controllerName = helper.ViewContext.RouteData.Values["controller"].ToString();
if ((controllerName != "Home") && (controllerName != "Account"))
{
var htmlLink = helper.ActionLink(
linkText: "Home",
actionName: "/",
controllerName: "Home").ToHtmlString();
var sb = new StringBuilder($"<ol class='breadcrumb'><li>{htmlLink}</li>");
var controllerLink = helper.ActionLink(
linkText: controllerName,
actionName: "/",
controllerName: controllerName);
sb.Append($"<li>{controllerLink}</li>");
var actionName = helper.ViewContext.RouteData.Values["action"].ToString();
var actionLink = helper.ActionLink(
linkText: actionName,
actionName: actionName,
controllerName: controllerName);
sb.Append($"<li>{actionLink}</li>");
result = sb.Append("</ol>").ToString();
}
return result;
}
The webpage I want to implement it on has a navigation menu:
- Services
- Parts
- Bulletins
- Publications
- Warranty
- Sales
- Buyers
- Image Resources
- Videos
For something like Home > Services > Parts
, there is a controller called ServiceController.cs and a model called PartsInformation.cs.
The links for Home
and Parts
work fine, but there is nothing to display for the intermediate Services
because it is a menu item only. Clicking Services
attempts to redirect here:
https://localhost:44383/Services/
What should be done here?
Should I remove the link for Services
and leave the text, or should I have Services
route to Home
?
I would like to route the root navigation menu items back to Home
, but I don’t understand enough about this ActionLink.
Solution – 1
Here is what I have done until someone posts a better solution:
In the file Global.asax.cs
, I added the Application_Error method to redirect when a controller is not found:
protected void Application_Error()
{
var err = Server.GetLastError();
if (err.GetType() == typeof(InvalidOperationException))
{
if (err.Message.IndexOf("The view 'Index' or its master was not found") == 0)
{
if (-1 < err.StackTrace.IndexOf("System.Web.Mvc.ViewResult.FindView(ControllerContext context)"))
{
// this controller does not have a view
var request = HttpContext.Current.Request;
var homeLink = $"{request.Url.Scheme}://{request.Url.Authority}{request.ApplicationPath.TrimEnd('/')}/";
Response.Redirect(homeLink);
}
}
}
}
It works, but it just doesn’t seem like the way ASP.NET MVC should handle the case of links going to controllers that do not exist.
Solution – 2
https://localhost:44383/Services/
It is trying to redirect to default action of ServiceController
, which is typically named Index
.
I think you have a few options (depending on what you want):
Redirect to
/Home
:public class ServiceController : Controller { // assuming you want to redirect to HomeController's default action: public IActionResult Index() => Redirect("/Home"); // or if you know HomeController's default action name, // you can use more idiomatic syntax: // // public IActionResult Index() => RedirectToAction("Index", "Home"); }
Utilize this space by adding an action Index page under Services (with list of services).
Render
Services
in breadcrumb as text (instead of link):if (controllerName == "Services") { sb.Append($"<li>{controllerName}</li>"); } else { var controllerLink = helper.ActionLink( linkText: controllerName, actionName: "/", controllerName: controllerName); sb.Append($"<li>{controllerLink}</li>"); }
(I’d personally choose option #2 if it’s my decision)