无法调试通过自定义 VirtualPathProvider 加载的 EmbeddedResource 视图

问题描述 投票:0回答:2

我编写了一个自定义 VirtualPathProvider(来源here),它将返回来自 EmbeddedResources 的内容,或者从原始文件(如果已被告知在哪里找到它)返回内容(这允许您编辑和更新文件而无需重建)。到目前为止,这工作正常。

不起作用的是调试。如果我向视图添加断点,它不会加载符号。我明白为什么这很困难(ASP 编译器如何知道源文件在哪里,以便找到断点?),但我正在寻找一种方法来提示编译器可以在哪里找到源文件。

此处的示例项目:http://dl.dropbox.com/u/2808109/VppDebugTest.zip

编辑:

我一直在尝试通过 VPP 加载 ASPX 页面,并查看编译源(使用 David Ebbo 的技术),并且行编译指示是这样生成的:

Line 275:              #line 1 "http://server/EmbeddedPage.aspx"
Line 276:              this.InitializeCulture();

通常,这些是沿着

的思路生成的
Line 275:              #line 1 "d:/somesln/someproj/EmbeddedPage.aspx"

不知道这是否对任何人有帮助...

编辑2:

大卫把他的代码发给我后,我做了一些进一步的调查,以下事情似乎是真的:

  1. 除非引用了 system.web(在 VS 2010 中),否则无法在 .aspx 中设置断点
  2. 如果您使用指令

    <%@ Page Language="C#" %>
    创建一个最小的.aspx页面并设置断点,VS将在源文件中的断点处停止

  3. 如果您使用指令

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="VppDebugTest.WebForm1" %>
    创建一个非最小.aspx并设置断点,则在查看时VS将带您进入反汇编调试视图

--- http://server/WebForm1.aspx ------------------------------------------------
0000003a  mov         ecx,dword ptr [ebp-3Ch] 
0000003d  call        63EC54F0 
00000042  mov         dword ptr [ebp-44h],eax 
00000045  mov         edx,dword ptr ds:[03E62200h] 
0000004b  mov         ecx,dword ptr [ebp-44h]

它仍然不会在 Razor 视图中的任何断点处停止,不幸的是,这正是我真正需要做的!这个 .aspx 的东西可能是转移注意力的东西。

编辑:

5:如果我在 Index.cshtml 中调用 Debugger.Break(),调试器会在反汇编视图中停止,并且根本没有编译指示,无论是不正确还是其他情况

  1. 如果我在我看来手动写入
    @{ #line 1 "C:\Users\Harry\Desktop\VppDebugTest\VppDebugTest.Views\Views\Home\Index.cshtml" }
    ,则调试将停止在文件中。所以也许解决方案是我的 VPP 将 #line pragmas 插入 cshtml 文件本身?
asp.net debugging embedded-resource virtualpathprovider
2个回答
2
投票

我遇到了同样的问题,最终通过使用自定义 RazorHost 使其正常工作。似乎物理文件位置是使用

HostingEnvironment.MapPath()
方法解析的,该方法不会返回嵌入文件的正确结果。

我做了什么:

public class MyCustomRazorHostFactory : WebRazorHostFactory
{
    public override System.Web.WebPages.Razor.WebPageRazorHost CreateHost( string virtualPath, string physicalPath )
    {
        // Implementation stolen from MvcRazorHostFactory :)
        var host = base.CreateHost( virtualPath, physicalPath );

        if( !host.IsSpecialPage )
        {
            return new MyCustomRazorHost( virtualPath, physicalPath );
        }

        return host;
    }
}

public class MyCustomRazorHost : MvcWebPageRazorHost
{
    public MyCustomRazorHost( string virtualPath, string physicalPath )
        : base( virtualPath, physicalPath )
    {
        if( MyMagicHelper.IsEmbeddedFile( virtualPath ) )
        {
            PhysicalPath = MyMagicHelper.GetPhysicalFilePath(virtualPath);
        }
    }
}

// Simplified for demonstration purpose
public static class MyMagicHelper
{
    public static bool IsEmbeddedFile(string virtualPath)
    {
        // ... check if the path is an embedded file path
    }

    public static string GetPhysicalFilePath(string virtualPath)
    {
        // ... resolve the virtual file and return the correct physical file path
    }
}

最后一步,您需要告诉 ASP.NET 它应该使用哪个主机工厂。这是在 web.config 中完成的:

<system.web.webPages.razor>
    <host factoryType="My.Custom.Namespace.MyCustomRazorHostFactory" />
</system.web.webPages.razor>

我知道我的答案有点晚了,但希望其他人可以像我一样在偶然发现这个问题时利用它。 :)


1
投票

我尝试了一下你的代码,当我在资源中添加测试 aspx 时,调试似乎工作正常。我能够在 Page_Load 中设置 BP,然后将其 git 到那里。

您可以在https://github.com/davidebbo/EmbeddedResourceVirtualPathProvider

中看到我的更改

请注意,我禁用了后备逻辑,因为我想专注于嵌入式案例,尽管我认为这没有什么区别。

请注意,我使用的是 VS2012,因此我还必须升级项目/sln(但它们在 2010 年仍然可以工作)。

ASP.NET 生成 http 行编译指示的原因是它无法在标准位置找到物理 aspx 文件(即 MapPath 将返回的内容)。实际上有一种鲜为人知的方法可以始终打开此行为:在部分中设置 urlLinePragmas=true (http://msdn.microsoft.com/en-us/library/system.web.configuration.compilationsection.urllinepragmas.aspx) .

© www.soinside.com 2019 - 2024. All rights reserved.