简体   繁体   中英

How to fix a 404 with routes in ASP.NET MVC?

I'm having a problem trying to get routing to work with ASP.NET MVC 3.0. I have the following routes declared:

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

    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
    new { controller = "Home", action = "RsvpForm", id = UrlParameter.Optional } 
    );

    routes.MapRoute(
        "TestRoute",
        "{id}",
        new { controller = "Product", action = "Index3", id = UrlParameter.Optional }
    );

    routes.MapRoute(
        "TestRoute2",
        "{action}",
        new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

When I visit:

http://localhost

The site works correctly, and it appears to hit Default route.

When I visit:

http://localhost/1

I get a 404:

Server Error in '/' Application.

The resource cannot be found. Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.

Requested URL: /1

Here are the actions those routes correspond to:

public ActionResult Index3(int? id)
{
    Product myProduct = new Product
    {
        ProductID = 1,
        Name = "Product 1 - Index 3",
        Description = "A boat for one person",
        Category = "Watersports",
        Price = 275M
    };

    Product myProduct2 = new Product
    {
        ProductID = 2,
        Name = "Product 2 - Index 3",
        Description = "A boat for one person",
        Category = "Watersports",
        Price = 275M
    };

    ViewBag.ProcessingTime = DateTime.Now.ToShortTimeString();

    if (id == 1)
        return View("index", myProduct);
    else
        return View("index", myProduct2);
}

How do I structure my routes so that all three action methods are hit correctly?

ASP.NET MVC Routing evaluates routes from top to bottom. So if two routes match, the first one it hits (the one closer to the 'top' of the RegisterRoutes method) will take precedence over the subsequent one.

With that in mind, you need to do two things to fix your problem:

  1. Your default route should be at the bottom.
  2. Your routes need to have constraints on them if they contain the same number of segments:

What's the difference between:

example.com/1

and

example.com/index

To the parser, they contain the same number of segments, and there's no differentiator, so it's going to hit the first route in the list that matches.

To fix that, you should make sure the routes that use ProductIds take constraints:

routes.MapRoute(
    "TestRoute",
    "{id}",
    new { controller = "Product", action = "Index3", id = UrlParameter.Optional },
    new { id = @"\d+" } //one or more digits only, no alphabetical characters
);

There are other issues with your set up, but those are two things that come to mind right off the bat.

Your routes MapRoute Default should be the last.

routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
    new { controller = "Home", action = "RsvpForm", id = UrlParameter.Optional } 
    );

In my case, the answer for the same problem was a matter of needing to "include in project" the relevant controllers and views instead of incorrect routing rules.

When mine were created, they weren't automatically included for some reason. This problem was revealed after I closed and re-opened the solution.

{+1 hate} awarded to Visual Studio for its faulty hyper-automation sending me digging through Web.Config files, trying to tack on extensions, and even trying (and failing) to whip up a decent ErrorController.

Push the most generic route to the last of the MapRoute call chain.

Try this:

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


        routes.MapRoute(
                "TestRoute",
                "{id}",
                new { controller = "Product", action = "Index3", id = UrlParameter.Optional }
        );

        routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "RsvpForm", id = UrlParameter.Optional } // Parameter defaults
                //new { controller = "Product", action = "Index2", id = UrlParameter.Optional } // Parameter defaults
        );


        routes.MapRoute(
                "TestRoute2",
                "{action}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

}

将默认路由移动到结尾,默认路由应该是要定义的最后一条路由,因为它充当了捕获所有路由

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM