Reputation: 755
I will try to word this as best as I can. Lets assume I have one method in controller X:
Index(string someString)
Is this valid? : X/Index
or do I need: X/Index/someString
(All this using the default routing configuration).
Now, is it possible to have a second method, so that:
Index(stringSomestring)
{
..
}
Index()
{
}
And if so, how does MVC route choose the right method?
Finally...
What is the difference between : declaring a parameter default value in a routeConfiguration, or in the method Parameters itself?
e.g. :
rotes.Add("", "etcetc", new {someString = string.Empty);
vs
Index(string someString = string.Empty)
Thanks and sorry if it's too silly or verbose.
---- EDIT ----- Thanks for your response anaximander, you've helped me clear my head some (though still struggling). Consider this :
routes.MapRoute("",
"Student/Sort-By{sortType}",
new { controller="Student", action="Index", sortType= ""}
);
I have a method:
Index(string sortType)
{
...
}
If I provide a url : Student/Sort-ByDate it works fine. If I provide a url : Student/Sort-By it finds nothing, though my method has an option for empty sort...
I feel like I am overcomplicating/doing something stupid, but can't pinpoint what :(
Upvotes: 0
Views: 885
Reputation: 7140
It depends on your routing setup. The default route looks like this:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Note the UrlParameter.Optional
part. That means you can go to somehost.com/X/Index
and it will look for a method Index()
, or you can add another slash and a parameter, and it'll look for Index(foo id)
where foo
is any type you fancy.
Routes are applied in the order you add them. That means that if you start at the top of your RouteConfig
and read down, the first one that would match the URL is the one it'll use. This is why you should put more specific routes above more general ones - otherwise, the general routes will catch all the URLs and stop the more specific routes from being used.
The system looks for:
{controller}
portion of the URL (or the default controller if the URL doesn't specify one){action}
part of the URL (or the default action if the URL doesn't specify one)Index(int id)
, if the URL contains an {id}
portion, it'll use that method. If that portion is absent, but the route specifies a default value, then it'll use that method with the default value. If there is no value, no default, and the parameter is marked as UrlParameter.Optional
, it will look for another method that doesn't require id
. (If the parameter is required, then this route wouldn't have matched, because the URL hasn't provided one.)So, in your case, if you want to be able to use somehost.com/X/Index
to get to Index(string someString)
then you'll need a route like this:
routes.MapRoute(
name: "Index",
url: "{controller}/{action}/{someString}",
defaults: new { controller = "X", action = "Index", someString = String.Empty }
);
which will call Index(string someString)
with the empty string if the URL doesn't give one. If you want URLs without a someString
parameter to go to Index
, then instead you can set somestring = UrlParameter.Optional
and if the URL doesn't provide one, it'll look for a method that doesn't need it. If you leave someString
out of the defaults entirely, then any URL that doesn't provide one will be invalid for this route, and will have to match some other route instead. If you've still got the pre-provided default route at the bottom, then it will catch somehost.com/X/Index
because it fits that template, so it'll assume you've omitted the optional id
parameter and look for a method like Index()
.
Edit:
When combining URL fluff and parameters like this, it gets a little trickier. Without being able to run it myself to debug, I'd guess that as far as the system is concerned, when matching Sort-By{sortType}
, the string Sort-By
is not "Sort-By" + ""
, it's "Sort-By" + null
. That is, the URL doesn't give the value of {sortType}
as a blank string, because the blank string is still a string, whereas this URL contains no string at all in that position. If the URL doesn't provide a value for {sortType}
and it's not marked as optional, then the URL doesn't match this route. This might work better as:
routes.MapRoute("",
"Student/Sort/{sortType}",
new { controller="Student", action="Index", sortType= ""}
);
Alternatively, you could consider dropping the sort from the URL and using query parameters, so the route becomes
routes.MapRoute("",
"Student/",
new { controller="Student", action="Index", sortBy= ""}
);
and to sort you go to host.com/Student/?sortBy=Date
.
Upvotes: 2
Reputation: 439
You cannot have several Index() for your routing
If you want to use either X/Index or X/Index/someText
You will have to declare ActionResult Index(string someString)
The routing process will know that Index can accept a String and then it will redirect to the right action. You don't need to render the string nullable or to specify an empty string. the string will simply be null.
To "guess" the right action i think the mvc framework uses reflection and associate Types and Names of the parameters.
The routing process will always work but if you want to specify a route that will be different from the default way then you will have to :
rotes.Add("", "etcetc", new {someString = string.Empty);
Upvotes: 0