Не удалось загрузить тип "ASP.xxx" при ссылке на предварительно скомпилированную главную страницу

Я пытаюсь предварительно скомпилировать несколько главных страниц (без возможности обновления), чтобы поделиться ими между несколькими приложениями. Проект, который я предварительно компилирую, - это веб-сайт. Проект, который ссылается на предварительно скомпилированные сборки, является веб-приложением. Тем не менее, я получаю Не удалось загрузить тип "ASP.xxx_master" каждый раз, когда я пытаюсь сослаться на главную страницу от клиента.

<%@ Master Language="C#" Inherits="ASP.sitebase_master" %>

Моя предварительно скомпилированная главная страница выглядит следующим образом.

<%@ Master Language="C#" ClientIDMode="Static" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org  /TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="AspNetHead" runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />   
    <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=7" /><![endif]-->
    <asp:ContentPlaceHolder ID="MetaContent" runat="server" />
    <title>Web Portal</title>   
    <link href="/media/css/style.css" rel="stylesheet" type="text/css" />
    <link href="/media/js/plugins/colorbox/colorbox.css" rel="stylesheet" type="text/css" />
    <asp:ContentPlaceHolder ID="StyleContent" runat="server" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js" type="text/javascript" language="javascript"></script>
    <script src="/media/js/plugins/colorbox/jquery.colorbox-min.js" type="text/javascript" language="javascript"></script>
    <script src="/media/js/plugins/filestyle/jquery.filestyle.min.js" type="text/javascript" language="javascript"></script>
    <script src="/media/js/portal.master.js" type="text/javascript" language="javascript"></script>
    <script language="javascript" type="text/javascript">
        PORTAL.debug.init();
        PORTAL.init();
    </script>
    <asp:ContentPlaceHolder ID="ScriptContent" runat="server" />
</head>
<body>
    <div id="hld">  
        <div class="wrapper">
            <form id="AspNetForm" runat="server">
                <asp:ContentPlaceHolder ID="BodyContent" runat="server" />  
            </form>
            <asp:ContentPlaceHolder ID="FooterContent" runat="server" />
        </div>
    </div>
</body>

Я в тупике. Не знаю, почему тип не разрешен. У кого-нибудь есть предложения? Оба проекта (предварительно скомпилированный веб-сайт и клиентское веб-приложение) созданы для ASP.NET 4.0.

РЕДАКТИРОВАТЬ: Вот список зависимостей скомпилированной сборки. Нет сторонних ссылок.

mscorlib, System, System.Web

UDPATE 1

Ну, быстрое решение этой проблемы - указать полный путь к главной странице.

<%@ Master Language="C#" Inherits="ASP.sitebase_master, App_Web_sitebase.master.cdcab7d2" %>

После этого я получаю следующую ошибку:

Произошла ошибка при попытке загрузить строковые ресурсы (FindResource не удалось с ошибкой -2147023083).

После некоторого исследования это, по-видимому, связано со способом анализа разметки HTML на главной странице. Еще не совсем уверен. Я не углубился в это глубже. В целом, я не могу поверить, что это рекомендуемый способ делиться средствами управления, поскольку это абсолютно, ошеломительно идиотски.

ОБНОВЛЕНИЕ 2

Я не мог сделать из этого ничего ценного. Кажется, он ненавидит теги "script" в разделе head, но я не знаю почему. Мастер-страница прекрасно работает с одним скриптом включения. Как только я начинаю добавлять больше, я продолжаю получать эту ошибку. Потратив на это целый день, я отправил отчет об ошибке в Microsoft. Если кто-то хочет столкнуться с этим, пожалуйста.

ОБНОВЛЕНИЕ 3

Я потратил еще несколько дней на отладку этого после отсутствия ответа от MS. Вот мои выводы. Сначала я думал, что код, сгенерированный провайдером CodeDOM, ищет ресурс.NET, который каким-то образом не внедряется в сборку при публикации. Я был неправ. После некоторого исследования выясняется, что происходит после того, как мастер-страница достигает определенного размера, ее часть сохраняется в таблице ресурсов в разделе "Каталоги данных PE" сборки. Фактически, просмотрев сгенерированную сборку в средстве просмотра ресурсов PE, я смог подтвердить это, найдя все мои скрипты, включенные в таблицу ресурсов. Теперь вот актуальная проблема. Происходит то, что поставщик CodeDOM генерирует вызов Win32 FindResource для извлечения этого ресурса из таблицы ресурсов. Однако FindResource не работает на сборках в памяти, только на диске. Так что это терпит неудачу с вышеупомянутым исключением. Я подхожу близко, но все еще нет обходного пути.

1 ответ

Решение

У меня наконец есть обходной путь. Это не красиво, но это решает проблему. Очевидно, использование LoadControl для предварительной загрузки предварительно скомпилированных MasterPages загружает все ресурсы, которые FindResource не может найти иначе. Итак, вот все, что я сделал, чтобы сделать эту работу.

В моем клиентском приложении я создал фиктивную главную страницу (т.е. Dummy.Master), которая ссылается на мою предварительно скомпилированную главную страницу следующим образом:

<%@ Master Language="C#" Inherits="ASP.sitebase_master, App_Web_sitebase.master.cdcab7d2" %>

Теперь любая страница.aspx, которая ссылается на Dummy.Master, должна предварительно загрузить предварительно скомпилированный тип MasterPage следующим образом:

        защищенное переопределение void OnPreInit(EventArgs e)
        {
            ASP.sitebase_master mp = (ASP.sitebase_master)Page.LoadControl(typeof(ASP.sitebase_master), null);

            base.OnPreInit(е);
        }

Я не знаю, почему это работает, но это работает. Этот код должен быть запущен до разрешения MasterPage, поэтому PreInit работал отлично. После нескольких секунд просмотра кода.NET в Reflector выясняется, что LoadControl фактически выполняет компиляцию сборок voodoo, когда пытается загрузить определенный тип элемента управления. Так что, возможно, что-то там загружает этот раздел данных о ресурсах PE. Лучшее место, чтобы поместить это было бы в базовом классе, я полагаю, что все страницы могли бы унаследовать. Кроме того, каждый загруженный элемент управления (в данном случае главная страница) должен быть кэширован. Вот хорошая статья, объясняющая только это.

Надеюсь, это поможет кому-то так же, как и мне. Это был довольно большой шоу-стоппер для меня.

Другие вопросы по тегам