paddingtonMike
paddingtonMike

Reputation: 1603

Weird behaviour with routing in ASP MVC

I've been messing around a little with the RouteConfig class in MVC4 and I came across a weird behavior that I don't know why it's happening.

I have the following code in the class:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.Add("Favicon", new Route("favicon.ico", new FavIconFileHandler()));

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );


}

The idea is that when someone access the http://my.domain.com/favicon.ico a different file would be served depending of the subdomain that was used. For example, http://app1.domain.com would get a different one that http://app2.domain.com. I know this could be done with IISRewrite, but I'm trying to explore this route to solve the problem too.

The code here actually works, the problem is that now when I submit any form in MVC I get the following URL:

http://localhost:13424/favicon.ico?action=ShowResult&controller=Home

Instead of

http://localhost:13424/Home/ShowResult

Any reason why is this happening and why the favicon.ico is being appended to the URL?

Upvotes: 1

Views: 294

Answers (2)

Alexandr Mihalciuc
Alexandr Mihalciuc

Reputation: 2577

You would be better off adding a handler to web.config handlers section and then ignore it in route mappings. But if you want to go with your solution you need to create a custom route class and ovveride GetVirtualPath method here is sample code for registering a route:

 public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.Add("Favicon", new CustomRoute("favicon.ico", new FavIconFileHandler()));

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );


}

CustomRoute Class:

 public class CustomRoute : Route
    {
        public CustomRoute(string uri, IRouteHandler handler) : base(uri, handler)
        {
        }

        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            return null;
        }
    }

That works because ASP.NET MVC will call VirtualPathData for every registered route when generating action links, and if a route returns null, then this route will not be considered for URL generation.

Here is the code from MVC which checks the outcome of VirtualPathData:

public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
    requestContext = this.GetRequestContext(requestContext);
    using (this.GetReadLock())
    {
        foreach (RouteBase current in this)
        {
            VirtualPathData virtualPath = current.GetVirtualPath(requestContext, values);
            if (virtualPath != null)
            {
                virtualPath.VirtualPath = RouteCollection.GetUrlWithApplicationPath(requestContext, virtualPath.VirtualPath);
                return virtualPath;
            }
        }
    }
    return null;
}

Upvotes: 1

YD1m
YD1m

Reputation: 5895

You can debug this behavior with enabled RouteDebugging.

Modify web.config with:

<add key="RouteDebugger:Enabled" value="true" /> in <appSettings> block

Make sure, that your default route handler is in the bottom of route table.

Upvotes: 1

Related Questions