无法加载类型“ASP.xxx”引用预编译母版页时
我正在尝试预编译一些母版页(不可更新)以在多个应用程序之间共享它们。我正在预编译的项目是一个网站。引用预编译程序集的项目是 Web 应用程序。但是,每次我尝试从客户端引用母版页时,都会收到无法加载类型“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>
我很困惑。不知道为什么类型没有解析。有人有建议吗?这两个项目(预编译的网站和客户端 Web 应用程序)都是为 ASP.NET 4.0 构建的。
编辑:这是预编译程序集的依赖项列表。没有第三方参考。
mscorlib, 系统, System.Web
UDPATE 1
那么,解决此问题的快速方法是指定母版页的完整路径。
<%@ Master Language="C#" Inherits="ASP.sitebase_master, App_Web_sitebase.master.cdcab7d2" %>
执行此操作后,我收到以下错误:
尝试加载字符串资源时发生错误(FindResource 失败,错误 -2147023083)。
经过一些研究后,这似乎与母版页中 HTML 标记的解析方式有关。还不完全确定。我还没有深入研究它。总的来说,我不敢相信这是共享控件的推荐方式,因为它绝对是令人难以置信的愚蠢。
更新2
我无法从中获得任何有价值的东西。它似乎讨厌头部部分的“脚本”标签,但我不知道为什么。母版页非常适合包含单个脚本。一旦我开始添加更多内容,我就会不断收到该错误。在浪费了一整天之后,我最终提交了 错误报告给 Microsoft。如果有人想撞它,请这样做。
更新3
在微软没有回应后,我又花了几天时间调试这个问题。这是我的发现。我最初认为 CodeDOM 提供程序生成的代码正在寻找 .NET 资源,该资源在发布时未以某种方式嵌入到程序集中。我错了。经过一番调查后发现,发生的情况是在母版页达到一定大小后,其中一部分存储在程序集的 PE 数据目录部分的资源表中。事实上,在查看 PE 资源查看器中生成的程序集后,我能够通过查找资源表中包含的所有脚本来确认这一点。现在,这是实际的问题。发生的情况是,CodeDOM 提供程序生成对 Win32 FindResource 的调用,以从资源表中提取该资源。但是,FindResource 不适用于内存中的程序集,仅适用于磁盘。所以它会因上述异常而失败。我已经很接近了,但仍然没有解决方法。
I'm attempting to precompile a few master pages (not update-able) to share them across multiple applications. The project I'm precompiling is a Web Site. The project that references precompiled assemblies is a Web Application. However, I'm getting a Could not load type 'ASP.xxx_master' every time i try to reference the master page from the client.
<%@ Master Language="C#" Inherits="ASP.sitebase_master" %>
My precompiled master page looks like this.
<%@ 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>
I'm stumped. No idea why the type isn't resolved. Anybody got suggestions? Both projects (precompiled web site and client web application) are built for ASP.NET 4.0.
EDIT: Here is the list of dependencies of the precompiled assembly. No 3rd party references.
mscorlib,
System,
System.Web
UDPATE 1
Well, the quick fix to this issue is to specify the full path to the master page.
<%@ Master Language="C#" Inherits="ASP.sitebase_master, App_Web_sitebase.master.cdcab7d2" %>
After doing that, I'm receiving the following error:
An error occurred while try to load the string resources (FindResource failed with error -2147023083).
After doing some research, this appears to be related to the way HTML markup is parsed within the master page. Not entirely sure yet. I haven't dug much deeper into it. Overall, I can't believe this is the recommended way to share controls as it is absolutely, mindbogglingly idiotic.
UPDATE 2
I couldn't make anything of value out of this. It appears to be hating "script" tags in the head section, but I don't know why. The Master Page works great with a single script include. As soon as i start adding more I keep getting that error. After wasting a full day on this I ended up submitting a bug report to Microsoft. If anyone wants to bump it, please do.
UPDATE 3
I spent a few more days debugging this after no response from MS. Here is my findings. I initially thought that the code generated by CodeDOM provider is looking for a .NET resource that somehow did not get embedded in the assembly when it was published. I was wrong. After some investigation it appears that what's happening is after the Master Page reaches a certain size, a chunk of it is stored in the Resource Table in PE Data Directories section of the assembly. In fact, after looking at the generated assembly in PE resource viewer, i was able to confirm this by finding all my script includes in the Resource Table. Now, here is the actual problem. What's happening is that the CodeDOM provider generates a call to Win32 FindResource to pull that resource from the Resource Table. However, FindResource doesn't work on assemblies in memory, only on disk. So it fails with the above exception. I'm getting close, but still no workaround.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我终于有一个解决方法了。这并不漂亮,但它解决了问题。显然,使用 LoadControl 预加载预编译的 MasterPages 会加载 FindResource 无法找到的所有资源。所以,这就是我为完成这项工作所做的一切。
在我的客户端应用程序中,我创建了一个虚拟母版页(即 Dummy.Master),它引用了我的预编译母版页,如下所示:
现在,任何引用 Dummy.Master 的 .aspx 页面都需要预加载预编译的 MasterPage 类型,如下所示:
我不这样做知道为什么会这样,但确实如此。此代码必须在 MasterPage 解析之前运行,因此 PreInit 效果很好。在 Reflector 中浏览了几秒钟的 .NET 代码后,发现 LoadControl 在尝试加载某种控件类型时实际上执行了一些程序集编译巫术。所以也许里面有东西加载 PE 资源数据部分。放置它的最佳位置是在我认为所有页面都可以继承的基类中。此外,每个加载的控件(在本例中为母版页)都应该被缓存。 这里有一篇很好的文章解释了这一点。
希望这对某人有帮助,就像对我有帮助一样。这对我来说是一个相当大的阻碍。
I finally have a workaround. It's not pretty, but it resolves the issue. Apparently using LoadControl to pre-load precompiled MasterPages loads all of the resources that FindResource cannot find otherwise. So, here is all i did to make this work.
In my client application I created a dummy master page (i.e. Dummy.Master) which references my precompiled master page like so:
Now, any .aspx page which references Dummy.Master needs to preload the precompiled MasterPage type like so:
I don't know why this works, but it does. This code must run before the MasterPage is resolved, so PreInit worked great. After glancing at the .NET code for a few seconds in Reflector, it appears that LoadControl actually does some assembly compiling voodoo when it attempts to load a certain control type. So perhaps something in there loads that PE resource data section. The best place to put it would be in the base class I suppose which all pages could inherit from. Also, each loaded control (master page in this case) ought to be cached. Here is a good article explaining just that.
Hopefully this helps someone as much as it helped me. It was a pretty big show stopper for me.