I have an MVC5 web application where some ID's can contain the period character.
For example
This works fine http://www.website.com/Employee/Details/123
This will fail http://www.website.com/Employee/Details/123.45
But this will work fine http://www.website.com/Employee/Details/?id=123.45
Similar problem here:
Currently all the solutions I have found are described in the links above.
<httpRuntime relaxedUrlToFileSystemMapping="true" />
<add name="UrlRoutingHandler" type="System.Web.Routing.UrlRoutingHandler, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" path="Remote.mvc/*" verb="GET"/>
As users will only browse to these url's via menus and link in the web page, I was hoping that the ActionLink html helper could be smart enough to render the ?id=123.45 when it recognizes the Id contains unsafe characters for the the Id route value.
Or is there a way to force the ActionLink html helper to always render the Id route value in the query string?
Update I could not find any parameters to force ActionLink to render the ?id= query string parameter so I found 2 possible solutions.
Solution 1
Create an html helper to generate the url. Any comments for improvement on this code would be appreciated.
public static MvcHtmlString ActionLinkSafeId(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
{
var routeValuesDictionary = new RouteValueDictionary(routeValues);
MvcHtmlString link = htmlHelper.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes);
if (routeValuesDictionary.ContainsKey("id") && routeValuesDictionary["id"].ToString().Contains('.'))
{
if (routeValuesDictionary.Count == 1)
{
var searchValue = string.Format("/{0}", routeValuesDictionary["id"]);
var replaceValue = string.Format("?id={0}", routeValuesDictionary["id"]);
link = new MvcHtmlString(link.ToString().Replace(searchValue, replaceValue));
}
else
{
var searchValue = string.Format("/{0}?", routeValuesDictionary["id"]);
var replaceValue = string.Format("?id={0}&", routeValuesDictionary["id"]);
link = new MvcHtmlString(link.ToString().Replace(searchValue, replaceValue));
}
}
return link;
}
Solution 2
Disable the use of id route value in your route configuration. This can either be done for the default route, a specific controller or a specific controller/action.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index"}
);