为什么 Web 部件第一次添加到页面时会在构造函数上失败?
这个问题有点具体(MOSS2007),我对得到答案不抱太大希望,但也许幸运会向我微笑。
我有一个 Web 部件,除了第一次被添加到页面时之外,都可以正常工作。 当我尝试打开与 SQL 服务器的连接时,它在构造函数内引发异常。 对 SqlClientPermission 权限的请求失败。 当我说它有效时,我的意思是它在任何方面都正确注册并且在所有其他情况下都有效,包括后续调用。
有人说没有出路。 我想知道为什么。 是设计使然吗?
我什至完全信任我所能做的一切(更改了我在服务器上可以找到的每个 .config 文件),但这没有帮助。
SharePoint 似乎在第一次添加 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 at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet) at System.Security.PermissionSet.Demand() at System.Data.Common.DbConnectionOptions.DemandPermission() at System.Data.SqlClient.SqlConnection.PermissionDemand() at System.Data.SqlClient.SqlConnectionFactory.PermissionDemand(DbConnection outerConnection) at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) at System.Data.SqlClient.SqlConnection.Open() at System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionUser user) at System.Data.Linq.SqlClient.SqlProvider.get_IsSqlCe() at System.Data.Linq.SqlClient.SqlProvider.InitializeProviderMode() at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) at System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute[S](Expression expression) at System.Linq.Queryable.Count[TSource](IQueryable`1 source) at IManageDocumentsPart.ClientSideDocumentsWebPart.GetOfficeCode(Int32 employeeId) at IManageDocumentsPart.ClientSideDocumentsWebPart..ctor()
完整堆栈:
IManageDocumentsPart.DLL!IManageDocumentsPart.ClientSideDocumentsWebPart.ClientSideDocumentsWebPart() Line 98 C# [Native to Managed Transition] [Managed to Native Transition] mscorlib.dll!System.RuntimeType.CreateInstanceSlow(bool publicOnly, bool fillCache = true) + 0x68 bytes mscorlib.dll!System.Activator.CreateInstance(System.Type type, bool nonPublic) + 0x43 bytes System.Web.dll!System.Web.HttpRuntime.FastCreatePublicInstance(System.Type type) + 0x56 bytes System.Web.dll!System.Web.UI.WebControls.WebParts.WebPartManagerInternals.CreateObjectFromType(System.Type type) + 0x7 bytes 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 bytes Microsoft.SharePoint.dll!Microsoft.SharePoint.WebPartPages.WebPartImporter.CreateWebPart(bool clearConnections = true) + 0x1b4 bytes 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 bytes 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 bytes 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 bytes System.Web.dll!System.Web.UI.Page.RaisePostBackEvent(System.Web.UI.IPostBackEventHandler sourceControl, string eventArgument) + 0xc bytes System.Web.dll!System.Web.UI.Page.RaisePostBackEvent(System.Collections.Specialized.NameValueCollection postData) + 0xb2 bytes
...堆栈的其余部分与正常打开页面时相同。
This question is a bit specific (MOSS2007) and I don't high hopes for getting an answer, but maybe luck will smile upon me.
I have a web part that works except the very first time it's being added to a page. It throws an exception inside a constructor when I'm trying to open a connection to a SQL server. The demand for the SqlClientPermission permission fails. When I say it works, I mean it is properly registered in any regard and works in every other case, including subsequent calls.
Someone said there is no way out. I'd like to know why. Is it by design?
I went so far as to give a full trust to everything I could (changed every .config file I could find on my server), but it did not help.
It appears that SharePoint is doing some kind of remoting the first time it adds a web part, which appears to run with minimal trust the first time it's constructed (same as defined in web_minimaltrust.config for ASP.Net). Attempts to grant permissions for everything in everything did not yield any fruitful results.
My solution was to move the data access code to the OnInit method, but that is irritating. Does anyone have any insight?
Thank you.
Some extra info from the debugger.
The only permitted permissions were:
<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>
The inner exception stack:
hresult = -2146233078 mscorlib at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet) at System.Security.PermissionSet.Demand() at System.Data.Common.DbConnectionOptions.DemandPermission() at System.Data.SqlClient.SqlConnection.PermissionDemand() at System.Data.SqlClient.SqlConnectionFactory.PermissionDemand(DbConnection outerConnection) at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) at System.Data.SqlClient.SqlConnection.Open() at System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionUser user) at System.Data.Linq.SqlClient.SqlProvider.get_IsSqlCe() at System.Data.Linq.SqlClient.SqlProvider.InitializeProviderMode() at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) at System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute[S](Expression expression) at System.Linq.Queryable.Count[TSource](IQueryable`1 source) at IManageDocumentsPart.ClientSideDocumentsWebPart.GetOfficeCode(Int32 employeeId) at IManageDocumentsPart.ClientSideDocumentsWebPart..ctor()
The full stack:
IManageDocumentsPart.DLL!IManageDocumentsPart.ClientSideDocumentsWebPart.ClientSideDocumentsWebPart() Line 98 C# [Native to Managed Transition] [Managed to Native Transition] mscorlib.dll!System.RuntimeType.CreateInstanceSlow(bool publicOnly, bool fillCache = true) + 0x68 bytes mscorlib.dll!System.Activator.CreateInstance(System.Type type, bool nonPublic) + 0x43 bytes System.Web.dll!System.Web.HttpRuntime.FastCreatePublicInstance(System.Type type) + 0x56 bytes System.Web.dll!System.Web.UI.WebControls.WebParts.WebPartManagerInternals.CreateObjectFromType(System.Type type) + 0x7 bytes 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 bytes Microsoft.SharePoint.dll!Microsoft.SharePoint.WebPartPages.WebPartImporter.CreateWebPart(bool clearConnections = true) + 0x1b4 bytes 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 bytes 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 bytes 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 bytes System.Web.dll!System.Web.UI.Page.RaisePostBackEvent(System.Web.UI.IPostBackEventHandler sourceControl, string eventArgument) + 0xc bytes System.Web.dll!System.Web.UI.Page.RaisePostBackEvent(System.Collections.Specialized.NameValueCollection postData) + 0xb2 bytes
...the rest of the stack is the same as when opening a page normally.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
尝试设置解决方案包来部署代码访问安全设置。 您肯定需要 SqlClientPermission。 查看我的帖子 Web 部件的代码访问安全性 了解更多信息。
Try setting up a solution package to deploy code access security settings. You definitely need SqlClientPermission. Check out my post on Code Access Security for web parts for more information.
作为接下来的参考,此处 有许多文章中的一篇将 Web 部件构造函数中的代码标记为 big不,不。
Just as a reference for the next ones coming, here there's one of the many articles were code in web part constructor is marked as a big NO-NO.
这很奇怪。 也许您可以对您的 Web 部件进行特殊处理,以便在页面处于编辑/设计模式时不执行数据库调用。 这不就能解决你的问题吗?
That is odd. Maybe you could special case your web part to not do the database call when the page is in edit/design mode. Wouldn't that fix your problem?
作为一个简单的测试,您可以将包含 Web 部件的程序集部署到 GAL 中。 在那里它将以完全信任的方式运行。
就个人而言,我不建议在 Web 部件的构造函数中建立数据库连接,除非您有令人信服的理由这样做。
[更新时间:3009-03-27]
调试通常是为了排除原因。 即使您认为 Web 部件正在完全信任中运行,我还是建议测试 GAC 的案例。 请记住从 Bin 目录中删除 .dll 以进行测试。 只需 5-10 分钟,您就会知道自己的立场。
As a simple test, you could deploy the assemby containing the web part into the GAL. There it will run with Full Trust.
Personally, I would not recommend establishing a database connection in the constructor of a web part unless you had a compelling reason to do so.
[updated 3009-03-27]
Debugging is often about ruling out causes. Even though you believe the web part is running in Full Trust, I recommend testing the GAC'ed case. Remember to remove the .dll from the Bin directory for the test. This will only take 5-10 minutes and you'll know where you stand.
当 SharePoint 遍历并处理请求时,它要做的第一件事就是执行构造函数来创建对象的新实例。 它调用的构造函数是无参数的,因此可以对它们进行序列化和反序列化以进行导入/导出。 在构造函数内部,新创建的对象中没有设置任何安全构造或关联对象。 因此,您的对象可能没有任何有关其所在位置或正在做什么的上下文信息。
通过将代码移至 OnInit 方法中,您已将执行时间向后移动,因为此时某些相关对象和尚未自动绑定的对象。 在 ASP.net 生命周期中,OnInit 方法从上到下工作,OnLoad 方法从下到上工作。 因此,这也可能会影响您的父母或孩子是否已执行相关代码。
When SharePoint is going through and processing the request the first thing that it will be doing is executing your constructor to create a new instance of the object. The Constructors that it calls are parameterless so that they can be serialized and deserialized for import/exports. Inside of the constructor none of the security constructs or associated objects have been set in the newly created object. It may therefore be the case that your object does not have any context information about where it is living or what it is doing.
By moving your code into the OnInit method you have shifted the time of execution back as some of your related objects and what not have been bound automatically by this point. In the ASP.net lifecycle, OnInit methods work from the from the top down and OnLoad methods work from the bottom up. So that may also influence whether your parent or children have had their related code executed yet.