5

I am trying to set up custom routing with the following mapped route

edit: my full route config

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

        #region FixtureAdmin

        routes.MapRoute(
            name: "FixtureEdit",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "FixtureAdmin", action = "Edit", id = UrlParameter.Optional }
        );

        #endregion

        #region Results

        routes.MapRoute(
            name: "ResultAdd",
            url: "{controller}/{action}/{fixtureId}",
            defaults: new { controller = "Result", action = "Add", fixtureId = UrlParameter.Optional }
        );

        #endregion

And my controller code

public ActionResult Add(int fixtureId)
    {
       // return model to view etc..
    }

This is coming up with the exception, even though I have specified the parameter as optional.

The parameters dictionary contains a null entry for parameter 'fixtureId'

The strange thing is, if I change the parameter of the Add action to just 'Id' then the following URL will work Result/Add/1. I'm confused, is there some default routing that is overriding my custom one? Why would changing the parameter to just 'Id' work?

Edit

Just to test, I added another parameter to the action

public ActionResult Add(int? fixtureId, int? testId)

I then edited the route accordingly and now it works, so I reckon it is an issue with default routing.

nik0lai
  • 2,585
  • 23
  • 37
  • is their any other route also configured before or after this – rajansoft1 Jun 03 '13 at 10:06
  • 1
    If you want to be able to call `Add` without specifying the id, `fixtureId` should be nullable - `int? fixtureId`. "Optional" in the context of the route means it doesn't have to be in the URL, so that you can have actions like `public ActionResult Add() {/*no parameters*/}` – Alex Jun 03 '13 at 10:07
  • Only thing I can think of is that you are using an int which is non-nullable? Id is probably baked into the MVC framework so possibly works different. – David Jun 03 '13 at 10:07
  • Apologies, just to clear things up I want to pass in a parameter every time, I have changed it to a nullable param int? fixtureId but every time I call it the parameter is null, Result/Add/1 and Result/Add both work but pass in a null. – nik0lai Jun 03 '13 at 10:26

3 Answers3

6

Use a nullable int in your Controller Action.

public ActionResult Add(int? fixtureId)
{
   // return model to view etc..
}

But the question is, if that is indeed an ID, how would it react if a null/blank ID is requested by the user? Is that ID a key in your DB? You can make it nullable if you are able to handle or provide a default page if the ID is blank/null.

EDIT:

This is because ASP.NET will assume that an unidentified parameter in your request is the id, in your case, Results/Add/1, 1 is unidentified. If you want to make that code work with using fixtureId, you should use Results/Add?fixureId=1. So ultimately, it's not because of the routing, but instead, it's because of the parameter in the Action that you have.

EDIT2:

Also, what you are experiencing there is called a routing conflict. Your routes are conflicting with the Default. You can try to apply constraints.

Community
  • 1
  • 1
aiapatag
  • 3,355
  • 20
  • 24
  • I can make it nullable and handle it accordingly. The problem is when I actually pass a value in with Result/Add/1 for example the value passed in is always null. – nik0lai Jun 03 '13 at 10:21
  • 1
    Ok, looks like that will suffice, I wanted to go hide parameters from the user if possible but may have to do that with posting the form, thanks. – nik0lai Jun 03 '13 at 12:31
2

2, from your post i think your problem is putting your custom route after default, like this:

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

        routes.MapRoute(
        name: "ResultAdd",
        url: "{controller}/{action}/{fixtureId}",
        defaults: new { controller = "Home", action = "Add", fixtureId = UrlParameter.Optional }

so: 1/ exception "The parameters dictionary contains a null entry for parameter 'fixtureId'" will come if you dont give the specific route name for any action link or route form because MVC will use default route to routing. So you need to give specific route name to your custom route can be worked, like this:

@Html.ActionLink("Test custom Route", "Add", "Home", new { fixtureId = 1 }, "ResultAdd")

Cheer

user2412747
  • 111
  • 1
1

Look at this method of adding what the developer calls a 'NullableConstraint' clicky link So if the optional parameter is supplied you can do some checking on it's value.

And also look at the answer following the accepted answer for what seems a simpler, cleaner solution.

Community
  • 1
  • 1
Paul Zahra
  • 9,522
  • 8
  • 54
  • 76