为啥 Web 部件在第一次添加到页面时会在构造函数上失败?

Posted

技术标签:

【中文标题】为啥 Web 部件在第一次添加到页面时会在构造函数上失败?【英文标题】:Why would a web part fail on constructor the first time it's being added to a page?为什么 Web 部件在第一次添加到页面时会在构造函数上失败? 【发布时间】:2010-10-13 23:04:44 【问题描述】:

这个问题有点具体(MOSS2007),我不希望得到答案,但也许运气会对我微笑。

除了第一次将它添加到页面之外,我有一个可以正常工作的 Web 部件。当我尝试打开与 SQL 服务器的连接时,它会在 constructor 内引发异常。 SqlClientPermission 权限请求失败。当我说它有效时,我的意思是它在任何方面都已正确注册,并且在所有其他情况下都有效,包括后续调用。

有人说没有出路。我想知道为什么。是设计的吗?

我什至完全信任我所能做的一切(更改了我在服务器上可以找到的每个 .config 文件),但这没有帮助。

SharePoint 在第一次添加 Web 部件时似乎正在执行某种远程处理,该 Web 部件似乎在第一次构建时以最低信任度运行(与 ASP.Net 的 web_minimaltrust.config 中定义的相同)。尝试为所有内容授予权限并没有产生任何成果。

我的解决方案是将数据访问代码移至 OnInit 方法,但这很烦人。有人有什么见解吗?

谢谢。

来自调试器的一些额外信息。

唯一允许的权限是:

<PermissionSet class="System.Security.PermissionSet" version="1">
    <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Execution"/>
    <IPermission class="System.Web.AspNetHostingPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Level="Minimal"/>
</PermissionSet>

内部异常堆栈:

hresult = -2146233078
mscorlib
在 System.Security.CodeAccessSecurityEngine.Check(对象需求,StackCrawlMark& stackMark,布尔 isPermSet)
在 System.Security.PermissionSet.Demand()
在 System.Data.Common.DbConnectionOptions.DemandPermission()
在 System.Data.SqlClient.SqlConnection.PermissionDemand()
在 System.Data.SqlClient.SqlConnectionFactory.PermissionDemand(DbConnection outerConnection)
在 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection,DbConnectionFactory connectionFactory)
在 System.Data.SqlClient.SqlConnection.Open()
在 System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionUser 用户)
在 System.Data.Linq.SqlClient.SqlProvider.get_IsSqlCe()
在 System.Data.Linq.SqlClient.SqlProvider.InitializeProviderMode()
在 System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(表达式查询)
在 System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute[S](表达式表达式)
在 System.Linq.Queryable.Count[TSource](IQueryable`1 源)
在 IManageDocumentsPart.ClientSideDocumentsWebPart.GetOfficeCode(Int32 employeeId)
在 IManageDocumentsPart.ClientSideDocumentsWebPart..ctor()

完整的堆栈:

IManageDocumentsPart.DLL!IManageDocumentsPart.ClientSideDocumentsWebPart.ClientSideDocumentsWebPart() 第 98 行 C#
[本机到托管转换]
[管理到本地转换]
mscorlib.dll!System.RuntimeType.CreateInstanceSlow(bool publicOnly, bool fillCache = true) + 0x68 字节
mscorlib.dll!System.Activator.CreateInstance(System.Type type, bool nonPublic) + 0x43 bytes
System.Web.dll!System.Web.HttpRuntime.FastCreatePublicInstance(System.Type 类型) + 0x56 字节
System.Web.dll!System.Web.UI.WebControls.WebParts.WebPartManagerInternals.CreateObjectFromType(System.Type 类型) + 0x7 字节
System.Web.dll!System.Web.UI.WebControls.WebParts.WebPartManager.ImportWebPart(System.Xml.XmlReader reader = EndElement, Name="metaData", out string errorMessage = null) + 0x35d bytes
Microsoft.SharePoint.dll!Microsoft.SharePoint.WebPartPages.SPWebPartManager.ImportWebPartBase(System.Xml.XmlReader reader = EndElement, Name="metaData", string importErrorMessage = "Cannot import this Web Part.", out string errorMessage = null ) + 0x25 字节
Microsoft.SharePoint.dll!Microsoft.SharePoint.WebPartPages.WebPartImporter.CreateWebPart(bool clearConnections = true) + 0x1b4 字节
Microsoft.SharePoint.dll!Microsoft.SharePoint.WebPartPages.WebPartImporter.Import(Microsoft.SharePoint.WebPartPages.SPWebPartManager manager = Microsoft.SharePoint.WebPartPages.SPWebPartManager, System.Xml.XmlReader reader = None, bool clearConnections = true , System.Uri webPartPageUri = http://v-sp2007/testsite/default.aspx?PageView=Shared, Microsoft.SharePoint.SPWeb spWeb = Microsoft.SharePoint.SPWeb) + 0x8e 字节
Microsoft.SharePoint.dll!Microsoft.SharePoint.WebPartPages.WebPartImporter.Import(Microsoft.SharePoint.WebPartPages.SPWebPartManager manager = Microsoft.SharePoint.WebPartPages.SPWebPartManager, System.Xml.XmlReader reader = None, bool clearConnections = true , Microsoft.SharePoint.SPWeb spWeb = Microsoft.SharePoint.SPWeb) + 0xa1 字节
Microsoft.SharePoint.dll!Microsoft.SharePoint.WebPartPages.WebPartQuickAdd.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(string eventArgument = "http%253A%252F%252Fv%252Dsp2007%252F%255Fcatalogs%252Fwp%252FClientSideDocumentsWebPart%252Ewebpart;ClientSideDocumentsWebPart" ) + 0x288 字节
System.Web.dll!System.Web.UI.Page.RaisePostBackEvent(System.Web.UI.IPostBackEventHandler sourceControl, string eventArgument) + 0xc 字节
System.Web.dll!System.Web.UI.Page.RaisePostBackEvent(System.Collections.Specialized.NameValueCollection postData) + 0xb2 字节

...堆栈的其余部分与正常打开页面时相同。

【问题讨论】:

【参考方案1】:

尝试设置解决方案包以部署代码访问安全设置。你肯定需要 SqlClientPermission。查看我在Code Access Security for web parts 上的帖子了解更多信息。

【讨论】:

谢谢。不过,我有。我试过有没有。这里的问题不在于 CAS 配置错误,因为如果它没有任何工作都不会起作用。这是 SharePoint 在首次添加 Web 部件时忽略任何配置并以最低信任运行。【参考方案2】:

作为下一篇文章的参考,here 有许多文章之一是 Web 部件构造函数中的代码被标记为 大 NO-NO

【讨论】:

是的,构造函数可能第一次被调用,而所有安全对象都没有正确设置。【参考方案3】:

这很奇怪。当页面处于编辑/设计模式时,也许您可​​以特殊情况下您的 Web 部件不执行数据库调用。这不能解决你的问题吗?

【讨论】:

我想我可以做到。正如我所提到的,我将代码移入 OnInit 并“修复”了它。我只是想知道为什么当我授予所有权限时它运行具有最小权限集的构造函数。【参考方案4】:

作为一个简单的测试,您可以将包含 Web 部件的程序集部署到 GAL 中。它将在完全信任的情况下运行。

就个人而言,我不建议在 Web 部件的构造函数中建立数据库连接,除非您有令人信服的理由。

[更新于 3009-03-27]

调试通常是为了排除原因。即使您认为 Web 部件在完全信任下运行,我还是建议您测试 GAC 的案例。请记住从 Bin 目录中删除 .dll 以进行测试。这只需要 5 到 10 分钟,您就会知道你站在哪里。

【讨论】:

我还没有尝试过 GAL,因为 Web 部件在 FullTrust 中运行,只是第一次添加时没有。我会尝试。我在构造函数中访问 DB,因为某些设计时属性取决于用户特定的数据。但是,任何特权方法都会失败,而不仅仅是 DB。【参考方案5】:

我的解决方案是将数据访问代码移至 OnInit 方法,但这很烦人。有人有什么见解吗?

当 SharePoint 处理并处理请求时,它将执行的第一件事是执行您的构造函数以创建对象的新实例。它调用的构造函数是无参数的,因此可以对它们进行序列化和反序列化以进行导入/导出。在构造函数内部,没有在新创建的对象中设置任何安全构造或关联对象。因此,您的对象可能没有任何关于它所在位置或正在做什么的上下文信息。

通过将代码移动到 OnInit 方法中,您已经将执行时间移回了一些相关对象以及此时尚未自动绑定的对象。在 ASP.net 生命周期中,OnInit 方法自上而下工作,而 OnLoad 方法自下而上工作。所以这也可能会影响你的父母或孩子是否已经执行了他们的相关代码。

【讨论】:

以上是关于为啥 Web 部件在第一次添加到页面时会在构造函数上失败?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 twitter 在调整大小时会在 Google Chrome 上启动“打嗝”?

为啥我的 iPhone 应用程序的发布版本在安装后第一次运行时会在设备上崩溃?

为啥 GCC 在匹配函数时会查看私有构造函数?

为啥 .NET 运行时会在我的字符串中添加下划线?

为啥受保护的构造函数会在此代码中引发错误?

为啥在尝试调用采用动态参数的基本构造函数/方法时会出现此编译错误?