“路径中包含非法字符”仅在通过移动浏览器查看时

问题描述

我正在使用传统的WebAPI控制器:

- if: github.repository_owner == 'owner_name'

[Route("api/results/{query}")] [AcceptVerbs("GET")] public HttpResponseMessage GetQueryResults(string query) { var userAgent = Request.Headers.UserAgent; var result = _fooService.GetResults(GetUsername(),query); var response = Request.CreateResponse(HttpStatusCode.OK,result); return response; } 返回一个看起来像这样的元素数组:

GetResults

在大多数浏览器上,这都可以正常工作。我的用户代理标头如下所示:

[{
"resultId":2039016,"text":null,"dateCreated":"2020-09-10T02:24:36.003","targetPlatform":"FooBar"
}]

但是,当我使用设备工具栏从Chrome调试时,或者当我在iPhone上的Safari中访问网站时,用户代理会更改。在Chrome的设备工具栏(移动模拟器)中,看起来像这样:

{Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/84.0.4147.125 Safari/537.36}

在这种情况下,{Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/84.0.4147.125 Mobile Safari/537.36} 被调用并针对JSON失败:

“ type”:“ System.ArgumentException”, ↵“消息”:“路径中的非法字符。”, ↵“ stackTrace”:“在 System.IO.Path.GetIntension(字符串路径)\ r \ n上的System.IO.Path.CheckInvalidPathChars(字符串路径,布尔值checkAdditional)\ r \ n 在System.Web.WebPages.DefaultDisplayMode.TransformPath(String virtualPath,字符串后缀)\ r \ n位于 System.Web.WebPages.DefaultDisplayMode.GetDisplayInfo(HttpContextBase httpContext,字符串virtualPath,函数CheckInvalidPathChars 2 virtualPathExists, IDisplayMode currentDisplayMode,布尔值 requireConsistentDisplayMode)\ r \ n位于 System.Web.WebPages.WebPageRoute.GetRouteLevelMatch(字符串pathValue, String [] supportExtensions,Func 2 virtualPathExists)\r\n at System.Web.WebPages.DisplayModeProvider.GetDisplayInfoForVirtualPath(String virtualPath,HttpContextBase httpContext,Func 2个virtualPathExists, HttpContextBase上下文,DisplayModeProvider displayModes)\ r \ n位于 System.Web.WebPages.WebPageRoute.DoPostResolveRequestCache(HttpContextBase 上下文)\ r \ n System.Web.WebPages.WebPageHttpModule.OnApplicationPostResolveRequestCache(对象 发送者,EventArgs e)\ r \ n位于 System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()\ r \ n 在System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep步骤)\ r \ n 在System.Web.HttpApplication.ExecuteStep(IExecutionStep步骤, 布尔值和完成同步)“

我可以通过尝试将序列化的JSON解析为文件路径来手动重现此内容:

2 virtualPathExists,HttpContextBase context,DisplayModeProvider displayModeProvider)\r\n  at System.Web.WebPages.WebPageRoute.MatchRequest(String pathValue,String[] supportedExtensions,Func

但是,当然,尝试将序列化的JSON对象解析为文件会引发错误。为什么ASP.NET会根据用户代理标头修改解析行为?

我可以以某种方式覆盖 try { var isValid = System.IO.Path.GetExtension(jsonString); } catch (Exception e) { throw e; } 的入站标头来强制框架实现功能行为吗?

要明确-我可以从Chrome(标准)中调用控制器,而不会出现任何问题。当我从Chrome发出完全相同的请求来调用控制器时(打开devtools并激活了移动模拟器),将引发异常。同样,当我用来自iPhone上Safari的完全相同的请求调用它时,将引发异常。在这种情况下,用户代理标头是自变量-因此必须遵循该标头以某种方式导致被调用的不同执行路径。对吧?

在执行所有Controller逻辑后会引发异常-引发Request时,控制器将返回它。

解决方法

正如@Dipen Shah所指出的,解决方案在另一个post中。


为什么ASP.NET会基于用户代理标头修改解析行为?

ASP.NET应用程序(reference)中有一个WebPageHttpModule自动注册。在内部,WebPageHttpModule尝试根据显示模式路由请求。

// NOTE: Excluded unnecessary code
public sealed class DisplayModeProvider
{
    public static readonly string MobileDisplayModeId = "Mobile";

    private readonly List<IDisplayMode> _displayModes = new List<IDisplayMode>()
    {
        (IDisplayMode) new DefaultDisplayMode(DisplayModeProvider.MobileDisplayModeId)
        {
            ContextCondition = (Func<HttpContextBase,bool>) (context => context.GetOverriddenBrowser().IsMobileDevice)
        },(IDisplayMode) new DefaultDisplayMode()
    };

    public IList<IDisplayMode> Modes
    {
        get
        {
            return (IList<IDisplayMode>) this._displayModes;
        }
    }
}

您可以在此处看到字符串Mobile,并根据IsMobileDevicereference)检查条件。因此,上述post中的解决方案才有意义。一旦知道了它在内部的工作原理,就可以执行以下 hack

public static void RegisterDisplayModes()
{
    var displayModes = DisplayModeProvider.Instance.Modes;
    var mobileDisplayMode = displayModes.FirstOrDefault(d => d.DisplayModeId == DisplayModeProvider.MobileDisplayModeId);
    if (mobileDisplayMode != null)
    {
        displayModes.Remove(mobileDisplayMode);
    }
}

请注意,这是基于位于System.Web.WebPages.dll的反编译的C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v2.0\Assemblies\

,

假设我完全理解您的问题,我使用Asp.net Core可以找到下面的代码和屏幕截图。

sage: x = sqrt(2)
sage: x
sqrt(2)
sage: x.n()
1.41421356237310
  • 这是vscode的图像截图

enter image description here

  • 这是使用chrome移动响应的屏幕截图

enter image description here

  • 这是使用chrome web或桌面视图的屏幕截图

enter image description here

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...