【问题标题】:MVC Child Action throws Illegal Characters in PathMVC 子动作在路径中抛出非法字符
【发布时间】:2014-04-07 18:14:18
【问题描述】:

当我的视图包含子操作时,我的 url 包含引号字符时出现意外异常。

http://mysite.info/home/index/"

当此操作的视图不包含子操作时,一切正常。当它确实包含子操作时(例如@Html.Action("Menu")),我在调用 Html.Action 时收到异常“System.ArgumentException: Illegal characters in path”。

查看this post 双引号字符不是默认的无效字符之一。在我看来,带有或不带有子动作的动作应该表现相同。双引号有效或无效。

此外,我不确定如何最好地解决这个看似双重标准的问题。我很犹豫是否将非法字符列表更改为包含 " (默认值是默认值是有原因的)。子动作非常有用,所以我不想不使用它们。在每个子动作周围放一个 try catch 是 hacky .

我并没有积极尝试在我的路由中使用引号,但如果 " 不在非法字符列表中,那么它不应该导致异常,对吧?

示例

控制器:

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>

堆栈跟踪

[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

【问题讨论】:

  • 堆栈跟踪是什么?
  • @ErikFunkenbusch 添加了堆栈跟踪。
  • 从堆栈跟踪中可以看出,错误来自 MapPath,实际上发生在 MVC 之外。这是基本 HttpHandler 中的代码,无论是常规操作还是子操作,都应该相同。
  • 我同意无论是常规动作还是子动作,它都应该是相同的。但观察到的行为是不一样的。
  • 你能发布你的控制器和动作吗?

标签: asp.net asp.net-mvc


【解决方案1】:

通过在 web.config 中设置以下内容找到了一种潜在的解决方案:

<httpRuntime relaxedUrlToFileSystemMapping="true"/>

这看起来很危险,所以我将忽略这些错误。

【讨论】:

    【解决方案2】:

    Html.Action 有一个检查当前路由是否在一个区域中。这个过程返回访问虚拟路径(文件系统)。文件系统中不允许使用引号,因此会引发错误。

    bool usingAreas;
    VirtualPathData vpd = htmlHelper.RouteCollection
        .GetVirtualPathForArea(htmlHelper.ViewContext.RequestContext, null /* name */, routeValues, out usingAreas);
    

    这里有 RouteCollection 扩展代码:

    http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/RouteCollectionExtensions.cs

    您可能能够处理 RouteValues 并设置区域名称以避免错误,但首先不允许无效的文件系统字符是理想的。

    【讨论】:

    • 进一步看,它正在通过区域检查。它实际上是在尝试执行,所以没有像最初那样清理一些东西。
    • 我唯一的想法是它是在浏览器请求上编码的,被解码,而不是在 Child Action 请求上编码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-05
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    • 2019-08-30
    • 1970-01-01
    相关资源
    最近更新 更多