I have created a new route with that looks like this in the RouteConfig.cs.
routes.MapRoute("Edit_Personal",
"Edit/Personal/{userID}/{refKey}/{houseID}",
new {controller = "Edit", action = "Personal",
userID = UrlParameter.Optional,
refKey = UrlParameter.Optional,
houseID = UrlParameter.Optional });
This route works fine if I pass in something like:
Edit/Personal/78887/abcd/
UserID = 78887
RefKey = abcd
HouseID = null
However, if the RefKey is never passed (it's optional), but a HouseID is passed, I get this as the result (the URL):
Edit/Personal/78887//88881 <--- Notice the two slashes between the numbers.
UserID = 78887
RefKey = 88881
HouseID = null
The results I expected are:
UserID = 78887
RefKey = null
HouseID = 88881
If you notice, the RefKey should be NULL, however, it's binding the HouseID into the RefKey parameter.
Is there a way to correct this? Am I missing something?
You need to define multiple routes like below:
routes.MapRoute(
"WithAll",
"{controller}/{action}/{UserID}/{RefKe}/{HouseID}",
new{ controller = "Edit",action = "Personal"});
routes.MapRoute(
"WithoutRefke",
"{controller}/{action}/{UserID}/{HouseID}",
new{controller = "Edit",action = "Personal"});
routes.MapRoute(
"WithoutRefkeAndHouseID",
"{controller}/{action}/{UserID}",
new{controller = "Edit",action = "Personal",UserID= UrlParameter.Optional});
Take a look at the following link for more details:
http://haacked.com/archive/2011/02/20/routing-regression-with-two-consecutive-optional-url-parameters.aspx/
Related
I have a route rule as:
routes.MapRoute("HotToursPage",
"HotTours/{countryTo}/{resort}/{param1}/{param2}/{param3}/{param4}/{param5}",
new
{
controller = "HotTours",
action = "Index",
countryTo = UrlParameter.Optional,
resort = UrlParameter.Optional,
param1 = UrlParameter.Optional,
param2 = UrlParameter.Optional,
param3 = UrlParameter.Optional,
param4 = UrlParameter.Optional,
param5 = UrlParameter.Optional
}
);
In the code I have:
var dictionary = new RouteValueDictionary();
aaa.Add("countryTo", countryToInfo.Translit);
aaa.Add("resort", resort);
aaa.Add("param1", param1);
string url = urlHelper.Action("Index", "HotTours", dictionary);
If there are param5, param6 and other, then
url =/hottours/?countryTo=tailand&resort=bangkok¶m1=price_from_50000,
but if i remove param5, param6 and other, then all ok:
url =/hottours/tailand/bangkok/price_from_50000
Why if segment count is less then 7, all ok? I need 9 segments, but urlHelper builds wrong url in this case.
When building URLs, you have to provide all of the route values that are in the URL pattern. There is one exception - when the last parameter is optional, you don't need to include it.
Therefore, to consistently deal with segments that could be optional in a long URL pattern, you need more than one route. Each route can only have one UrlParameter.Optional and it must be the right-most segment.
routes.MapRoute("HotToursPage3",
"HotTours/{countryTo}/{resort}/{param1}/{param2}/{param3}/{param4}/{param5}",
new
{
controller = "HotTours",
action = "Index",
param5 = UrlParameter.Optional
}
);
routes.MapRoute("HotToursPage2",
"HotTours/{countryTo}/{resort}/{param1}/{param2}/{param3}",
new
{
controller = "HotTours",
action = "Index",
param3 = UrlParameter.Optional
}
);
routes.MapRoute("HotToursPage1",
"HotTours/{countryTo}/{resort}/{param1}",
new
{
controller = "HotTours",
action = "Index",
param1 = UrlParameter.Optional
}
);
NOTE: I am assuming here that your {countryTo} and {resort} parameters are required. It doesn't seem that sensible to make them optional. However, if I am mistaken, you need another route to deal with those 2 segments being optional or alternatively you should provide sensible default values for them. Generally speaking, if there are no sensible defaults for a value it should be required in the URL.
Do note that you still can only make a segment optional if none of the segments to the right of it are provided. Therefore, this combination will work:
var dictionary = new RouteValueDictionary();
dictionary.Add("countryTo", "test1");
dictionary.Add("resort", "test2");
dictionary.Add("param1", "test3");
var url = Url.Action("Index", "HotTours", dictionary);
But this combination will still build a query string:
var dictionary = new RouteValueDictionary();
dictionary.Add("countryTo", "test1");
dictionary.Add("resort", "test2");
dictionary.Add("param1", "test3");
dictionary.Add("param2", "test4");
dictionary.Add("param5", "test5");
var url = Url.Action("Index", "HotTours", dictionary);
If you want all 5 of your params to be optional (and in any order), you should use query strings, rather than putting them into the path.
routes.MapRoute("HotToursPage",
"HotTours/{countryTo}/{resort}",
new
{
controller = "HotTours",
action = "Index"
}
);
An alternative (that I don't recommend) would be to build up a series of routes that have identifier segments, which allows you to place the values in any order. See ASP.Net MVC Handling Segments with Route.
Nothing like that as you are mentioning below is the main reason
Http.sys service is coded with default maximum of 260 characters per Url segment.
An "Url segment" in this context is the content between "/" characters in the Url. For example:
The max allowed Url segment length can be changed with registry settings:
Key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters
Value: UrlSegmentMaxLength
Type: REG_DWORD
Data: (Your desired new Url segment maximum allowed length, e.g. 4096)
The maximum allowed value is 32766. If a larger value is specified, it will be ignored.
Restarting the PC is required to make a change to this setting take effect.
Why isn't the value of default-only variable myVar added to outbound URL as part of a query string:
routes.MapRoute("MyRoute", "{controller}/{action}",
new { myVar = 1 });
Index.cshtml:
#Html.ActionLink("click me", "CustomVariable", "Home",
new { myVar = 1, newMyVar = 1000 }, null);
From the above routing system generates:
click me
Thank you
In your routing rule you are stating that if the default value is not provided, then use this value.
So there is really no need to provide the value when it is the same as the default value, because it will simply use the default value.
I'm creating a online log viewer application which reads logs generated by many applications into a single common database. Log types are error, fatal, debug and I use all to represent all the logs.
I've a controller named AppsController which should server Views for the following requests, where "bi-reports" is one of the many application names we have.
/apps/bi-reports/
/apps/bi-reports/all
/apps/bi-reports/error/
/apps/bi-reports/2011/04/
/apps/bi-reports/2011/04/all
/apps/bi-reports/2011/error
/apps/bi-reports/2011/04/error
/apps/bi-reports/all/last-hundred
/apps/bi-reports/all/most-hundred
/apps/bi-reports/2011/last-hundred
/apps/bi-reports/2011/04/all/last-hundred
How should I configure routes set parameters in Action methods of Controller to get this working?
This is rough idea of your routing definition. I can see that you basically have three types of routes:
routes.MapRoute(
"IrrelevantDates",
"{controller}/{application}/{type}/{range}",
// defaults
new {
controller = "Apps",
action = "UnboundReport",
type = "all",
range = "no-limit"
},
// constraints
new {
type = "apps|error"
}
);
routes.MapRoute(
"RelevantYearOnly",
"{controller}/{application}/{year}/{type}/{range}",
// defaults
new {
controller = "Apps",
action = "YearlyReport",
type = "all",
range = "no-limit"
},
// constraints
new {
year = "19\d{2}|2[01]\d{2}",
type = "apps|error"
}
);
routes.MapRoute(
"RelevantYearAndMonth",
"{controller}/{application}/{year}/{month}/{type}/{range}",
// defaults
new {
controller = "Apps",
action = "MonthlyReport",
type = "all",
range = "no-limit"
},
// constraints
new {
year = "19\d{2}|2[01]\d{2}",
month = "0[1-9]|1[0-2]",
type = "apps|error"
}
);
I've set year constraint to match years between 1900 and 2199, and months so they actually have to specify a valid month 01 to 12.
If you have any additional controllers you will have to define a default route as well and put controller constraint on this one or make controller name static (when just one applies).
I would do something along these lines
''# note, this is untested VB and might need some tweaking.
routes.MapRouteLowercase("Base", "",
New With {.controller = "Home",
.action = "Index",
.year = UrlParameter.Optional,
.paging = UrlParameter.Optional},
New With {.year = "[0-9]*"})
Then your controller would have something like
Function Index(ByVal paging As String, ByVal year As Integer?) As ActionResult
''# do your pre-processing for paging and year.
Return View()
End Function
I'd like to add a constraint to a route parameter that I have. The route pattern is:
{region}/{controller}/{action}
where {region} should only be UK or US.
How can I do this? Is there a regex I can apply here, or some other means of defining this?
This question has been asked before. See:
Constraint Question
In essence, use Regular Expressions:
routes.MapRoute(
"Search", // Route name
"Search/{affiliateId}", // URL with parameters
new { controller = "Syndication", action = "Search" }, // Parameter defaults
new { affiliateId = "SOME REGEX TO TEST GUID FORMAT" } // constraints
);
There seem to be a lot of issues on SO dealing with MapRoute problems. I've read through a bunch of them, but I can't see what I'm doing wrong in my implementation. I've got the following routes set up:
routes.MapRoute( _
"FilesDisplay", _
"{controller}/{action}/{year}/{month}", _
New With {.controller = "Files", .action = "Display", .year = "", .month = ""})
routes.MapRoute( _
"Default", _
"{controller}/{action}", _
New With {.controller = "Files", .action = "Index"})
and the following RouteLink:
<%=Html.RouteLink("Show", "FilesDisplay", New With {.year = 2008, .month = 5})%>
However, the resulting URL for "Show" is /Files/Index/2008/5. Why is it picking up the Index action instead of the Display action?
Edit: As a lark I changed the second route to .action = "Display" just to see if I could get the URL to change, and it still resolves to /Files/Index/2008/5.
Edit 2: I also tried:
<%=Html.ActionLink("Show", "Display", "Files", New With {.year = 2008, .month = 5}, Nothing)%>
but that also resolves to /Files/Index/2008/5. Why is it that no matter what I specify for an action it's defaulting to Index?
Upgrading to MVC RC 1.0 seemed to fix ActionLink but not RouteLink. Therefore I'm moving forward with ActionLink. I'd love to know why RouteLink doesn't want to work though.