Question

I have got simple ASP.NET WebForms project with only few pages and I would like to use friendly URLs (not only for SEO but also localization of URLs). I use .NET 4.5 for this project and have tried to use Microsoft.AspNet.FriendlyUrls nuget package which looked like it might help. But there is one issue.

I've got in Global.asax this:

    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
    }

and RouteConfig class looks like this:

public static class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.MapPageRoute("HowItWorks", "ako-to-funguje", "~/HowItWorks.aspx");
        routes.MapPageRoute("AboutUs", "o-nas", "~/AboutUs.aspx");
        routes.MapPageRoute("Contact", "kontakt", "~/Contact.aspx");

        var settings = new FriendlyUrlSettings();
        settings.AutoRedirectMode = RedirectMode.Permanent;
        routes.EnableFriendlyUrls(settings);
    }
}

I want to show the same page if you access it through both /HowItWorks and /ako-to-funguje (which is Slovak locale).

And now I am getting close to actual issue. When I access site with one of localized routes (e.g. /ako-to-funguje) then Request.GetFriendlyUrlFileVirtualPath() returns empty string (but I want to get "~/HowItWorks.aspx" upon which I want to do some stuff in master page).

 string pageFileName = Request.GetFriendlyUrlFileVirtualPath();
 switch (pageFileName)
 {
      case "~/AboutUs.aspx":
           //do some stuff
           break;
      case "~/HowItWorks.aspx":
           //do some stuff
           break;
      case "~/Contact.aspx":
           //do some stuff
           break;
      default:
           break;
 }

If I access site with /HowItWorks URL then Request.GetFriendlyUrlFileVirtualPath() returns "~/HowItWorks.aspx" as expected.

Any idea how to get "~/HowItWorks.aspx" from Request.GetFriendlyUrlFileVirtualPath() when accessing site through both /HowItWorks and /ako-to-funguje?

Was it helpful?

Solution

At the end I've come up with own workaround of this issue. I've created own extension method for http request which returns virtual file path to currently executed page:

 using System.Web;
 using System.Web.Routing;
 using Microsoft.AspNet.FriendlyUrls;

 namespace Utils.Extensions
 {
      public static class HttpRequestExtensions
      {
          public static string GetFileVirtualPathFromFriendlyUrl(this HttpRequest request) 
          {
             string ret = string.Empty;

             ret = request.GetFriendlyUrlFileVirtualPath();

             if (ret == string.Empty)
             {
               foreach (RouteBase r in RouteTable.Routes)
               {
                   if (r.GetType() == typeof(Route))
                   {
                       Route route = (Route)r;
                       if ("/" + route.Url == request.Path)
                       {
                           if (route.RouteHandler.GetType() == typeof(PageRouteHandler))
                           {
                               PageRouteHandler handler = (PageRouteHandler)route.RouteHandler;

                               ret = handler.VirtualPath;
                           }
                           break;
                       }
                   }
               }
             }

             return ret;
          }
     }
 }

OTHER TIPS

Please check with

string requestUrl = this.Request.GetFriendlyUrlFileVirtualPath().ToLowerInvariant();
if (String.IsNullOrEmpty(requestUrl)) {
   requestUrl = this.Request.AppRelativeCurrentExecutionFilePath.ToLowerInvariant();
}

I updated Petriq's answer to handle parameters in the url

public static string GetFileVirtualPathFromFriendlyUrl(this HttpRequest request) {
        string ret = request.GetFriendlyUrlFileVirtualPath();

        if (ret == string.Empty) {
            for(int j = 0, a = RouteTable.Routes.Count; j<a;j++) {
                RouteBase r = RouteTable.Routes[j];
                if (r.GetType() == typeof(Route)) {
                    Route route = (Route)r;

                    StringBuilder newroute = new StringBuilder(route.Url);
                    if (route.Defaults != null && route.Defaults.Count > 1) {
                        string[] keys = route.Defaults.Select(x => x.Key).ToArray();
                        foreach (string k in keys) { 
                            newroute = newroute.Replace("{" + k + "}", k.CheckQueryString()); 
                        }
                    }

                    if (String.Compare(newroute.ToString(), request.Path.Replace(request.ApplicationPath, ""), true) == 0) {
                        if (route.RouteHandler.GetType() == typeof(PageRouteHandler)) {
                            PageRouteHandler handler = (PageRouteHandler)route.RouteHandler;
                            return handler.VirtualPath;
                        }
                    }
                }
            }
        }

        return ret;
    }

The Routes can now be

RouteValueDictionary contactDefault = new RouteValueDictionary { { "person", UrlParameter.Optional } };

routes.MapPageRoute("Contact", "kontakt/{person}", "~/Contact.aspx");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top