views:

43

answers:

2

Update:

As someone pointed out I was missing an s in my Route registration. Now I have a secondary problem.

This is how I want it to work:

http://localhost/products/ --> ProductsController.Index()

http://localhost/products/3/apples --> ProductsController.Details(int? id, string productName)

This is what currently happens:

http://localhost/products goes to my Details action.

How do I set up the routes for this?

I set up the following routes in my Global.asx file:

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

    routes.MapRoute(
        "ViewProduct",
        "products/{id}/{productName}",
        new { controller = "Products", action = "Details", id = 0, productName = "" } // Parameter defaults
    );

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

I have the following controller:

public class ProductsController : Controller
{
    //
    // GET: /Products/

    public ActionResult Index()
    {
        IList<Product> products = new List<Product>
        {
            new Product { Id = 57349, ProductName = "Apple" },
            new Product { Id = 57350, ProductName = "Banana" }
        };

        return View(products);
    }

    public ActionResult Details(int? id, string productName)
    {
        Product p = new Product { Id = id.Value, ProductName = productName };

        return View(p);
    }
}
+3  A: 

You're missing a "s" in your route declaration

action = "Detail*s*"

Or have one exceeding "s" in your action name :

public ActionResult Detail*s*(int? id, string productName)

It's up to you to decide which one to correct ;)

Update : for the route update just use :

routes.MapRoute(
    "ViewProduct",
    "products/{id}/{productName}",
    new { 
        controller = "Products", 
        action = "Details" }
);

So when you type /products the "Default" route gets used.

mathieu
Oh nice catch. Now when I hit /products it's taking me to the Details action when I want it to hit the Index action. Do I need to set up another route?
Dismissile
No... you just say what is default action (Details), but you can hit the action you want just by passing its name in an address like `http://localhost/products/Index/`
ŁukaszW.pl
Yeah but I want /products/ to default to /products/index basically.
Dismissile
+2  A: 

Because you have defined default values for id and productName the routing engine just fills those in for you when they are missing, so your request to /products is getting those defaults inserted and going to the details action.

Take out: id = 0, productName = "" and you'll get the expected behavior.

edit

Consider having an {action} parameter in there. Since you have a default action and no way to override it you may have everything routed to details anyway.

jwsample
Should I also change the controller action so it is int instead of int? (nullable)? That didn't really make sense to me.
Dismissile
If the int always needs to be there (which appears to be the case) then I'd just make it a non-nullable int. Could help you catch bugs later.
jwsample
Yeah it should always be there. Was just following someone else's example. Thanks a ton.
Dismissile