Не удается отладить просмотры EmbeddedResource, загруженные через пользовательский VirtualPathProvider

Я написал пользовательский VirtualPathProvider (источник здесь), который будет возвращать контент из EmbeddedResources или из исходного файла, если было сказано, где (это позволяет редактировать и обновлять файлы без необходимости их восстановления). Пока все работает нормально.

Что не работает, это отладка. Если я добавлю точку останова в представление, она не загрузит символы. Я могу понять, почему это сложно (как компилятор ASP знает, где находится исходный файл, чтобы определить точки останова?), Но я ищу способ подсказки компилятору, где можно найти исходный файл.

Пример здесь: http://dl.dropbox.com/u/2808109/VppDebugTest.zip

изменить:

Я экспериментировал с ASPX-страницей, загружаемой через VPP, и просмотрел Compiled Source (используя метод Дэвида Эббо) и линейные прагмы генерируются так:

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

Обычно они генерируются вдоль линий

Line 275:              #line 1 "d:/somesln/someproj/EmbeddedPage.aspx"

Не знаю, помогает ли это кому-либо, или нет...

edit 2:

После того, как Дэвид прислал мне свой код, я провел некоторое дальнейшее расследование, и следующие вещи выглядят правдоподобно:

  • вы не можете установить точку останова в .aspx, если не указана система system.web(в VS 2010)
  • если вы создаете минимальную страницу .aspx с директивами <%@ Page Language="C#" %> и задаете точку останова, VS остановится в точке останова в исходном файле

  • если вы создаете не минимальный .aspx с директивами <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="VppDebugTest.WebForm1" %> и устанавливаете точку останова, при просмотре 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: Если я поместил вызов Debugger.Break() в мой Index.cshtml, отладчик остановится на разборном представлении, и нет прагм вообще, некорректно или иначе

  • Если я вручную напишу @{ #line 1 "C:\Users\Harry\Desktop\VppDebugTest\VppDebugTest.Views\Views\Home\Index.cshtml" }, на мой взгляд, отладка остановится в файле. Так, может быть, решение для моего VPP вставить прайсы #line в сами файлы cshtml??

Ответ 1

У меня была такая же проблема и, наконец, она работала, используя пользовательский 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, на котором размещен factory он должен использовать. Это делается в файле web.config:

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

Я знаю, что мой ответ наступает немного поздно, но, надеюсь, кто-то другой сможет его использовать, когда споткнулся об этом вопросе, как и я.:)

Ответ 2

Я немного поиграл с вашим кодом, и когда я добавил тестовый aspx в ресурсы, отладка, похоже, работала нормально. Я смог установить BP в Page_Load, а там git.

Вы можете увидеть мое изменение https://github.com/davidebbo/EmbeddedResourceVirtualPathProvider

Обратите внимание, что я отключил логику возврата, поскольку я хотел сосредоточиться на встроенном случае, хотя я не думаю, что это имеет значение.

Обратите внимание, что я использую VS2012, поэтому мне также пришлось обновить проект /sln (но они все равно будут работать в 2010 году).

Причина, по которой ASP.NET генерирует прагму http-строки, заключается в том, что она не может найти физический файл aspx в стандартном местоположении (то есть, что вернет MapPath). На самом деле существует малоизвестный способ всегда включать это поведение: set urlLinePragmas = true в разделе (http://msdn.microsoft.com/en-us/library/system.web.configuration.compilationsection.urllinepragmas.aspx).