Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC Routing Parameters with Special Characters and Child Action

I have the following route and it needs to be able to handle game titles with any character in them. I have things enabled appropriately in my web.config to allow special characters in the URL, and have confirmed that my URLS work when just using basic query strings rather than custom MVC Routes. However, as soon as I include a child action load via Html.Action I get the below stack trace.

routes.MapRoute("Game", "Game/Game/{id}", new { controller = "Game", action = "Game", id = ""}, new { id = @"[^\.]*" });

Here is my Controller method and view (I dumbed them down a lot, but the error still occurs), it gets called by the route, and even the razor inside of the view itself gets called but then I get the below error / stack trace.

Controller:

public ActionResult Game(string id)
  {
     {
        Game currentGame = _ugdb.Games.FirstOrDefault(g => g.GameName.Equals(id));
        return View(currentGame);

  }

View:

@model UltimateGameDB.Domain.Entities.Game
@Html.Action("SearchBar", "Search")
<span>@Model.GameName</span>

Child Action Controller Method (does not get called):

[ChildActionOnly]
  public ActionResult SearchBar()
  {
     ViewBag.TotalGames = _ugdb.Game_Platform.Count() + _ugdb.Games.Count(g => g.Game_Platform.Count == 0);
     return PartialView("_SearchBar");
  }

Here are some examples of a few routes that are not working:

http://localhost:58386/Game/Game/Sid%20Meier%27s%20Civilization%3a%20Beyond%20Earth

http://localhost:58386/Game/Game/Starcraft%20II%3a%20Heart%20of%20the%20Swarm

Although basically any game in my database that has a special character is giving the same error. The actual error message is as follows:

System.NotSupportedException: The given path's format is not supported.

at System.Security.Util.StringExpressionSet.CanonicalizePath(String path, Boolean needFullPath) at System.Security.Util.StringExpressionSet.CreateListFromExpressions(String[] str, Boolean needFullPath) at System.Security.Permissions.FileIOPermission.AddPathList(FileIOPermissionAccess access, AccessControlActions control, String[] pathListOrig, Boolean checkForDuplicates, Boolean needFullPath, Boolean copyPathList) at System.Security.Permissions.FileIOPermission..ctor(FileIOPermissionAccess access, String path) at System.Web.InternalSecurityPermissions.PathDiscovery(String path) at System.Web.HttpRequest.MapPath(VirtualPath virtualPath, VirtualPath baseVirtualDir, Boolean allowCrossAppMapping) at System.Web.HttpRequest.MapPath(VirtualPath virtualPath) at System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage) at System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) at System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) at System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter) at System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues) at System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, Object routeValues) at ASP._Page_Views_Game_Game_cshtml.Execute() in d:\TFS Workspace\UltimateGameDB\Dev\Source\ULTIMATEGAMEDB\UltimateGameDB.WebUI\Views\Game\Game.cshtml:line 257 at System.Web.WebPages.WebPageBase.ExecutePageHierarchy() at System.Web.Mvc.WebViewPage.ExecutePageHierarchy() at System.Web.WebPages.StartPage.RunPage() at System.Web.WebPages.StartPage.ExecutePageHierarchy() at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList1 filters, ActionResult actionResult) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<>c__DisplayClass2b.b__1c() at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.b__1e(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.CallEndDelegate(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase1.End() at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) at System.Web.Mvc.Controller.b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase1.End() at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) at System.Web.Mvc.Controller.b__15(IAsyncResult asyncResult, Controller controller) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase1.End() at System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) at System.Web.Mvc.MvcHandler.b__5(IAsyncResult asyncResult, ProcessRequestState innerState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase1.End() at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) at System.Web.HttpApplication.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar)

I have googled this a bunch and cannot seem to figure out why this route would not work.

Thanks in advance!

like image 994
Aaron Davis Avatar asked Sep 12 '15 23:09

Aaron Davis


1 Answers

Try setting relaxedUrlToFileSystemMapping="true" in your httpRuntime element. With the attributes you've already added, it will probably look something like this:

<httpRuntime targetFramework="4.5" 
  requestPathInvalidCharacters="" 
  requestValidationMode="2.0" 
  relaxedUrlToFileSystemMapping="true" /> 

From the docs for the HttpRuntimeSection.RelaxedUrlToFileSystemMapping property:

Gets or sets a value that indicates whether the URL in an HTTP request is required to be a valid Windows file path.

Somewhere in the depths of the ASP.NET runtime it tries to translate the requested url into a physical path before handling the request. This setting seems to keep it from blowing up if the physical path is not valid.

like image 104
Peter Avatar answered Oct 17 '22 14:10

Peter