How to change a URL Link in ASP.NET MVC Breadcrumb

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/

404

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):

  1. 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");
    }
    
  2. Utilize this space by adding an action Index page under Services (with list of services).

  3. 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)

Rate this post
We use cookies in order to give you the best possible experience on our website. By continuing to use this site, you agree to our use of cookies.
Accept
Reject