我正在尝试在我的一个共享点解决方案中使用来自ajaxcontroltoolkit的自动完成扩展器(这需要旧版本的库,因为所有最近的库都需要 .NET Framework 4.0),不幸的是我不能在UserControl,仅在实际页面中. 因此,我只剩下一个选择,即使用来自实际 Web 服务的方法。问题是我似乎无法弄清楚如何正确部署服务和配置 web.config。当我尝试在浏览器中查看元数据信息时,我收到一条错误消息,提示“找不到端点”。但是,当我尝试输入附加到 URL 的方法名称的 URL 时,它实际找到并执行返回 JSON 数据的方法 - 这显然意味着它可以找到我的服务。此外,我可以使用 jQuery 来调用我的服务并返回 JSON 数据——但我不想在这个项目中使用 jQuery,而宁愿保持一切纯 C#。
我想知道的是,为什么我不能让“漂亮的元数据信息”显示在浏览器中,所以我得到了“温暖的模糊”,并允许其他应用程序以它应该工作的方式正确发现服务?
我对 web.config 进行了三次检查,我同时输入了 metadataExchange 端点以及引用我的服务的端点,并且我将 httpGetEnabled 设置为“true”。我尝试运行 svcutil /t:metadata 并将其指向我的服务,但出现了几个错误,第一个告诉我它无法获取元数据,第二个是元数据包含无法解析的引用,第三个是HTTP GET 错误,表示 HTML 文档不包含 Web 服务发现信息。即使我的 svc 文件与 OOTB SharePoint 服务位于同一个 ISAPI 目录中,并且可以为这些服务生成 XSD 文件,但不能为我的服务生成 XSD 文件。
这是我当前的 web.config 文件的样子......
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" />
<identity impersonate="true"/>
</system.web>
<system.serviceModel>
<!-- we need this to enable session -->
<client>
</client>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<behaviors>
<endpointBehaviors>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="metadataSupportBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://myserver/sites/mysitecollection/_vti_bin/WebServices/MyService.svc" policyVersion="Policy15"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization impersonateCallerForAllOperations="false"/>
<serviceCredentials>
<windowsAuthentication includeWindowsGroups="true" />
</serviceCredentials>
</behavior>
<behavior name="defaultBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
</bindings>
<services>
<service behaviorConfiguration="metadataSupportBehavior" name="Sample.WebServices.MyService">
<clear />
<endpoint address="" binding="basicHttpBinding" contract="Sample.WebServices.IMyService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange">
<identity>
<certificateReference storeName="My" storeLocation="LocalMachine"
x509FindType="FindBySubjectDistinguishedName" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://myserver/sites/mysitecollection/_vti_bin/WebServices/MyService.svc" />
</baseAddresses>
</host>
</service>
</services>
我在这里真是不知所措。有什么想法吗?
提前致谢!!!
更新#1:好的,我几乎让它工作了。我的意思是我“技术上”做了,但只是在浏览器中并有一些警告。
我做的第一件事是将以下代码添加到我的 web.config 文件中:
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
然后更新我的服务端点以包含对新配置的引用,如下所示:
<endpoint address="" binding="webHttpBinding" contract="Sample.WebServices.IMyService" behaviorConfiguration="webBehavior">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
我还将绑定从basicHttpBinding更改为webHttpBinding。
现在警告...
我可以让它完全发挥作用并在浏览器中返回 XML 响应,但前提是我在调试模式下运行该服务,这意味着它托管在 Visual Studio 而不是 IIS 中,因此它并不真正重要。
当我不在调试模式下运行服务时,我收到一条错误消息,说明“异常消息是‘值不能为空。参数名称:源’”。
在调试器中单步执行我的代码后,我看到了真正的错误:
请求“IBM.Data.DB2.DB2Permission, IBM.Data.DB2, Version=9.0.0.2, Culture=neutral, PublicKeyToken=7c307b91aa13d208”类型的权限失败。
简而言之,这意味着我正在尝试在我的 SharePoint 站点中加载 32 位版本的 IBM.Data.DB2 DLL,不幸的是,它只允许 64 位程序集。
所以我的第一反应是“啊哈!” 这应该很简单吧?我的意思是我要么需要找到 64 位版本的 DLL,要么只配置我在 IIS 中的 SharePoint 站点使用的应用程序池,以允许加载 32 位程序集,一切都应该是桃色的!我不聪明吗?但是没有说 SharePoint!我不仅不会让你做这些事情中的任何一个*,而且我会让你的整个 SharePoint 场完全无法使用,甚至无法尝试实施这种可笑的解决方案!!!
所以现在,当我尝试导航到我的 SharePoint 场中的任何资源时,我会受到欢迎。
[NullReferenceException: Object reference not set to an instance of an object.]
Microsoft.Office.Server.Administration.UserProfileApplicationProxy.get_ApplicationProperties() +134
Microsoft.Office.Server.Administration.UserProfileApplicationProxy.get_PartitionIDs() +44
Microsoft.Office.Server.Administration.UserProfileApplicationProxy.IsAvailable(SPServiceContext serviceContext) +329
Microsoft.Office.Server.WebControls.MyLinksRibbon.get_PortalAvailable() +44
Microsoft.Office.Server.WebControls.MyLinksRibbon.EnsureMySiteUrls() +60
Microsoft.Office.Server.WebControls.MyLinksRibbon.get_PortalMySiteUrlAvailable() +15
Microsoft.Office.Server.WebControls.MyLinksRibbon.OnLoad(EventArgs e) +91
System.Web.UI.Control.LoadRecursive() +65
System.Web.UI.Control.LoadRecursive() +190
System.Web.UI.Control.LoadRecursive() +190
System.Web.UI.Control.LoadRecursive() +190
System.Web.UI.Control.LoadRecursive() +190
System.Web.UI.Control.LoadRecursive() +190
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2427
即使我撤消对 IIS、应用程序池、DLL 的所有更改,重新启动 IIS,重新启动我的服务器等,也没有任何效果。我完全搞砸了。
美好时光。
*公平地说,SharePoint 与 64 位 IBM 驱动程序不可用无关,但我只是假设即使有一个我可以在技术上使用的,SharePoint 也会找到一种方法来惩罚我试图获取完成的任何工作。
更新#2:好的,我修复了整个“SharePoint 站点不工作”。基本上,所有与 SharePoint 相关的网站使用的应用程序池似乎都已更改为启用 32 位应用程序,包括 SecurityTokenServiceApplication(感谢该网站上的老兄不仅有同样的问题,而且还发布了解决方案)。现在,虽然我不记得为每个与 SharePoint 相关的应用程序池专门设置了该值,但我愿意一起玩,并说也许在绝望的情况下,我可能刚刚对它说地狱并开始鲁莽地更改配置设置. 你知道,因为这正是经验丰富的开发人员所做的。
无论如何...
现在我的中央管理网站已备份并运行,但 UserProfileApplication 服务仍然不稳定,我仍然倾向于认为我的 SecurityTokenServiceApplication 服务仍然处于崩溃状态,因为我收到错误(由于配置了 web.config,细节当然隐藏了这样做)告诉我“由于内部错误,服务器无法处理请求”。
详情请关注...
更新#3:好的,我把一切都恢复到原来的工作形式。我确认,仅为 SharePoint 资源使用的一个应用程序池启用 32 位应用程序会有效地更新所有其他应用程序以效仿。我知道这是一个事实,因为我自己确实没有为每个与 SharePoint 相关的应用程序池更改该值。我会记得经历过类似的事情。事实证明,SharePoint Web 服务使用的所有具有时髦外观的“类似 GUID”的名称的应用程序池也都已更新为允许运行 32 位应用程序,这导致我的环境变得一团糟。
此外,按照此处提供的建议,我让我的 SecurityTokenService 在浏览器中正确显示它的元数据。虽然它们看起来有点像“黑客”,但它们是小型且可逆的黑客,所以我很喜欢。
简而言之,您可以像这样编辑每个服务的配置文件:
- 在 spStsActAsBinding 绑定中,将 httpTransport 重命名为 httpsTransport。
- 将 allowInsecureTransport=”true” 和 enableUnsecuredResponse=”true” 添加到绑定安全性。
- 确保您只定义了 1 个绑定配置(例如,在 Profile Service 中,您会发现同一服务的 2 个绑定配置分别用于 http 和 https 协议)。
在完成所有这些之后,您应该能够获得我正在尝试为我正在处理的自定义 WCF 服务获取的“温暖元数据模糊”。
所以现在我只需要重新解决我最初的问题,即让 32 位版本的 IBM.Data.DB2 DLL 与 SharePoint 2010 一起使用。我还没有尝试过的一件事是创建一个托管的 IIS完全独立于 SharePoint 运行的服务。这样做可以让我创建一个单独的应用程序池,它实际上可以运行 32 位应用程序,而不会导致 SharePoint 崩溃——希望如此。
更新#4:好的,所以首先我要告诉你忽略我上面关于搞乱 SecurityTokenService 的建议。当然,您会通过更改获得“温暖的元数据模糊”,但您可能会导致您的 SharePoint 网站中断。
所以无论如何...我现在创建了一个完全独立于 SharePoint 的网站,它使用自己的应用程序池,该应用程序池配置为允许 32 位应用程序,因此从技术上讲应该可以解决我的所有问题。好吧,当我尝试在我的文本框中输入文本时,它不会“自动完成”,但是会发生网络活动,因为我在 Fiddler 中看到了它。奇怪的是它只发生一次。这意味着,如果我按退格键并重新输入其他内容,则不会对 Web 服务进行额外调用。我必须重新加载页面以再次测试它。我在调用该方法时收到的错误消息是“405 Method Not Allowed”。现在我的方法接口签名使用 WebInvoke 并将 Method 属性设置为“GET”,我' 已经被告知应该可以正常工作,并且过去在进行返回 JSON 数据的 REST 调用时,现在它不起作用。哦,在 Web 浏览器中它可以工作,我看到该方法返回了美妙的 XML 结果。但是,当我尝试在 SharePoint UserControl 中使用 AutoCompleteExtender 来调用该方法(或为此使用任何其他客户端)时,它不会。我曾尝试使用 WebGet() 属性,但 Web 浏览器中也没有返回任何内容。我想我收到了一个 415 错误。我曾尝试使用 WebGet() 属性,但 Web 浏览器中也没有返回任何内容。我想我收到了一个 415 错误。我曾尝试使用 WebGet() 属性,但 Web 浏览器中也没有返回任何内容。我想我收到了一个 415 错误。
更新#5:我发现了另一个帖子,其中有些人似乎遇到了与我现在遇到的完全相同的问题,唯一的区别是即使我在同一个项目中有网络服务,我也无法让自动完成工作。我也尝试了他帖子中提出的建议,但它们也没有奏效。这是帖子的链接,供感兴趣的人使用。