I'm getting an unexpected exception when my url contains a quote character when my view contains a child action.
http://mysite.info/home/index/"
When the view for this action does not contain a child action everything works fine. When it does contain a child action (e.g. @Html.Action("Menu")) I get the exception "System.ArgumentException: Illegal characters in path" at the call to Html.Action.
Looking at this post the double quote character is not one of the default invalid characters. It seems to me that an action with or without a child action should behave the same. Either a double quote is valid or it is not.
In addition, I'm not sure how best to work around this seeming double standard. I'm hesitant to change the illegal characters list to contain " (the defaults are the defaults for a reason). Child actions are very useful so I don't want to not use them. Putting a try catch around every child action is hacky.
I'm not actively trying to use quotes in my routes, but if " is not in the illegal characters list then it shouldn't result in an exception, right?
Example
Controller:
public class HomeController : Controller
{
public ActionResult WithChildAction() // throws exception with quote in path
{
return View();
}
public ActionResult WithoutChildAction() // works with quote in path
{
return View();
}
public ActionResult ChildAction()
{
return View();
}
}
WithChildAction.cshtml:
<h2>With Child Action</h2>
@Html.Action("ChildAction")
WithoutChildAction.cshtml:
<h2>Without Child Action</h2>
ChildAction.cshtml:
<h2>Child Action</h2>
Stack Trace
[ArgumentException: Illegal characters in path.]
System.IO.Path.CheckInvalidPathChars(String path, Boolean checkAdditional) +11113918
System.Security.Permissions.FileIOPermission.CheckIllegalCharacters(String[] str) +30
System.Security.Permissions.FileIOPermission.AddPathList(FileIOPermissionAccess access, AccessControlActions control, String[] pathListOrig, Boolean checkForDuplicates, Boolean needFullPath, Boolean copyPathList) +97
System.Security.Permissions.FileIOPermission..ctor(FileIOPermissionAccess access, String path) +63
System.Web.InternalSecurityPermissions.PathDiscovery(String path) +29
System.Web.HttpRequest.MapPath(VirtualPath virtualPath, VirtualPath baseVirtualDir, Boolean allowCrossAppMapping) +149
System.Web.HttpRequest.MapPath(VirtualPath virtualPath) +33
System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage) +44
System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) +28
System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm) +19
System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter) +461
System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues) +83
System.Web.Mvc.Html.ChildActionExtensions.Action(HtmlHelper htmlHelper, String actionName, Object routeValues) +29
ASP._Page_Areas_Site_Views_Content_File_cshtml.Execute() in c:\inetpub\Websites\MyWebsite\Source\Areas\Site\Views\Content\File.cshtml:22
System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +199
System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +104
System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +78
System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) +235
System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +107
System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +291
System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +56
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +420
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +52
System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +173
System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +100
System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +39
System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +12
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +28
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +29
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +31
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9690164
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
Found one potential solution by setting the following in web.config:
<httpRuntime relaxedUrlToFileSystemMapping="true"/>
This seems dangerous so I'm just going to ignore the errors.
Html.Action has a check that processes the Current Route to see if it is in an Area. This process returns accesses the Virtual Path (File System). Quotes aren't allowed in the Filesystem and thus throw the error.
bool usingAreas;
VirtualPathData vpd = htmlHelper.RouteCollection
.GetVirtualPathForArea(htmlHelper.ViewContext.RequestContext, null /* name */, routeValues, out usingAreas);
With the RouteCollection Extensions code here:
http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/RouteCollectionExtensions.cs
you may be able to handle the RouteValues and set the area name to avoid the error, but not allowing the invalid file system characters in the first place would be ideal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With