wcf - 将WCF服务部署到SharePoint 2010网站时出现“找不到端点”错误

标签 wcf sharepoint web-config ajaxcontroltoolkit endpoint

我试图在我的解决方案之一中使用中的(这需要库的较旧版本,因为最近的所有库都需要.NET Framework 4.0),但不幸的是I can't use a page method in a UserControl, only in an actual page。因此,我只剩下一个选择,那就是使用实际Web服务中的方法。问题是我似乎无法弄清楚如何正确部署服务和配置web.config。当我尝试在浏览器中查看元数据信息时,收到一条错误消息,提示“找不到端点”。但是,当我尝试输入在URL后面附加方法名称的URL时,它实际上找到并执行了返回JSON数据的方法-这显然意味着它可以找到我的服务。另外,我可以使用jQuery调用我的服务并返回JSON数据-但我不想在该项目中使用jQuery,而是只保留所有纯C#代码。

我想知道的是,为什么我不能在浏览器中显示“漂亮的元数据信息”,所以却变得“温暖模糊”,并允许其他应用程序以应有的方式正确发现服务?

我对web.config进行了三重检查,并且既有metadataExchange端点,也有引用我的服务的端点,并且我将httpGetEnabled设置为“ true”。我尝试运行svcutil / t:metadata并将其指向我的服务,但是遇到了几个错误,第一个告诉我它无法获取元数据,第二个告诉我Metadata包含无法解析的引用,第三个是HTTP GET错误,指出HTML文档不包含Web服务发现信息。即使我的svc文件与OOTB SharePoint服务位于相同的ISAPI目录中,并且可以为这些服务生成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中托管的,因此它实际上不计数。
当我不在调试模式下运行服务时,出现一条错误消息,提示“异常消息是'值不能为空。参数名称:source'”。


在调试器中单步执行代码后,我看到了真正的错误:


请求类型为'IBM.Data.DB2.DB2Permission,IBM.Data.DB2,Version = 9.0.0.2,Culture = neutral,PublicKeyToken = 7c307b91aa13d208'的许可失败。


用简单的英语来说,这意味着我试图在我的SharePoint网站中加载IBM.Data.DB2 DLL的32位版本,不幸的是,它仅允许64位程序集。

所以我的第一个反应是“啊哈!”这应该很简单吧?我的意思是我要么需要找到DLL的64位版本,要么仅配置我的SharePoint网站在IIS中用于允许加载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(对this站点的家伙们表示敬意,因为它不仅具有相同的问题,而且还发布了解决方案)。现在,虽然我不记得要为每个与SharePoint相关的应用程序池专门将值设置为true,但我还是愿意尝试说,也许是在绝望的情况下,我可能只是对它说了些鬼话,然后开始不顾一切地更改配置设置。您知道,因为这正是经验丰富的开发人员所做的。

无论如何...

现在,我的管理中心网站已备份并正在运行,但是UserProfileApplication服务仍然不稳定,而且我仍然倾向于认为我的SecurityTokenServiceApplication服务仍然处于混乱状态,因为出现错误(由于配置了web.config,因此详细信息当然被隐藏了)这样做)告诉我“服务器由于内部错误而无法处理请求”。

详细信息...

更新#3:好的,我已将所有内容恢复为原始工作形式。我确认,仅为SharePoint资源使用的一个应用程序池启用32位应用程序就可以有效地更新所有其他应用程序,以跟风。我之所以知道这一点,是因为我自己并没有为每个与SharePoint相关的应用程序池更改该值。我会记得经历过类似的事情。事实证明,所有这些具有SharePoint Web Services使用的“ GUID式”外观的时髦应用程序池也都进行了更新,以允许运行32位应用程序,这正是导致我的环境陷入困境的原因。

另外,通过遵循here提供的建议,我得到了SecurityTokenService来在浏览器中正确显示它的元数据。尽管它们看起来有点像“ hack”,但它们是小型且可逆的hack,所以我是游戏。

简而言之,您可以像这样编辑每个服务的配置文件:


在spStsActAsBinding绑定中,将httpTransport重命名为httpsTransport。
向绑定安全性添加allowInsecureTransport =” true”并启用enableUnsecuredResponse =” true”。
确保仅定义1个绑定配置(例如,在Profile Service中,您将为http和https协议的同一服务找到2个绑定配置)。


完成所有这些操作后,您应该能够为正在使用的自定义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错误。

更新#5:我发现另一篇文章中某个人似乎遇到了与我现在完全相同的问题,唯一的区别是即使我在同一项目中拥有Web服务,我也无法自动完成工作。我还尝试了他的帖子中提出的建议,但这些建议也不起作用。对于感兴趣的人,这是该帖子的link

最佳答案

对于Webpart项目(使用ASCX),您可以:

1)在IIS中为SP SIte启用匿名身份验证

2)添加SP Mapped文件夹ISAPI

3)在ISAPI中创建YourService.asmx

<%@ WebService Language="C#" Class="YourNamespace.YourService, YourAsm, Version=1.0.0.0, Culture=neutral, PublicKeyToken=YourPublicKeyToken"%>


4)编辑用户控制代码:

public partial class YourControl : UserControl
{
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        FixFormAction();
        CheckScriptManager();           
        EnsureUpdatePanelFixups();
    }

    private void FixFormAction()
    {
        // Fix problem with postbacks and form actions (DevDiv 55525)
        Page.ClientScript.RegisterStartupScript(GetType(), ID, "_spOriginalFormAction = document.forms[0].action;", true);

        // By default, the onsubmit event for forms in SharePoint master pages call "return _spFormOnSubmitWrapper()" 
        // which blocks async postbacks after the first one.   Not calling "_spFormOnSubmitWrapper()" breaks all postbacks
        // and defeats the purpose of _spFormOnSubmitWrapper() which is to block repetitive postbacks.  
        // To call _spFormOnSubmitWrapper() and allow partial postbacks, remove "return" from the original call.  
        if (Page.Form != null)
        {
            string formOnSubmitAtt = Page.Form.Attributes["onsubmit"];
            if (formOnSubmitAtt == "return _spFormOnSubmitWrapper();")
            {
                Page.Form.Attributes["onsubmit"] = "_spFormOnSubmitWrapper();";
            }
        }
    }

    private void EnsureUpdatePanelFixups()
    {
        if (this.Page.Form != null)
        {
            var fixupScript = @"
            _spBodyOnLoadFunctionNames.push(""_initFormActionAjax"");
            function _initFormActionAjax()
            {
            if (_spEscapedFormAction == document.forms[0].action)
            {
            document.forms[0]._initialAction = document.forms[0].action;
            }
            }
            var RestoreToOriginalFormActionCore = RestoreToOriginalFormAction;
            RestoreToOriginalFormAction = function()
            {
            if (_spOriginalFormAction != null)
            {
            RestoreToOriginalFormActionCore();
            document.forms[0]._initialAction = document.forms[0].action;
            }
            }
            ";
            ScriptManager.RegisterStartupScript(this, this.GetType(), "EnsureUpdatePanelFixup", fixupScript, true);
        }
    }

    private ScriptManager CheckScriptManager()
    {
        ScriptManager sm = ScriptManager.GetCurrent(Page);
        if (sm == null)
        {
            if (Page.Form != null)
            {
                sm = new ScriptManager();
                sm.ID = Page.Form.ID + "_ScriptManager";
                Page.Form.Controls.Add(sm);
                //Page.Form.Controls.AddAt(0, sm);  
            }
        }
        sm.EnablePageMethods = true;

        var sharedPath = @"~/_layouts/Share/";
        var path = @"~/_layouts/YourWebPart/";

        sm.Scripts.Add(new ScriptReference { Path = @"/_vti_bin/YourService.asmx/JS" });

        //Registering ExtJS
        Page.ClientScript.RegisterClientScriptInclude(GetType(), "ext-all", sharedPath + "scripts/ext-all.js");

        ScriptManager.RegisterClientScriptBlock(this, GetType(), "ext-css",
                                    "<link href='" +
                                    sharedPath + "resources/css/ext-all.css' rel='stylesheet' type='text/css' />", false);

        Page.ClientScript.RegisterClientScriptInclude(GetType(), "YourScript", path + "scripts/Script.js");

        return sm;
    }

}


5)编辑您的服务代码:

[WebService(Namespace = "http://tempuri/ws")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class YourService : WebService
{
    //[WebMethod]
    [ScriptMethod]
    [WebMethod(EnableSession = true)]
    //[ScriptMethod(UseHttpGet = true)]
    public string YourWebMethod(string arg)
    {           
        return arg;
    }
}


6)在控制javascript中使用您的网络服务方法:

YourNamespace.YourService.YourWebMethod(arg, function (result) {
        if (result) {
            if (typeof result == 'string') {
                alert(result);
            }
        }
    }, function (error) { alert('YourWebMethod failed! ' + error.get_message()); });
}


没有webconfig

对于ISAPI子文件夹中的svc

<%@ ServiceHost Debug="true" Language="C#"
Service="Namespace.MyService, MyAsm, Version=1.0.0.0, Culture=neutral, PublicKeyToken=MyPublicKeyToken"
%>


web.config可以是:

<system.webServer>    
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="2097151"/>
      </requestFiltering>
    </security>
  </system.webServer>
  <system.web>
    <httpRuntime executionTimeout="60" maxRequestLength="2097151" />        
  </system.web>  
  <system.serviceModel>    
    <bindings>
      <basicHttpBinding>        
        <binding name="MyHttpBinding"
         maxBufferPoolSize="2147483647"
         maxBufferSize="2147483647"
         maxReceivedMessageSize="2147483647">          
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Ntlm" proxyCredentialType="None" realm=""/>
            <message clientCredentialType="UserName" algorithmSuite="Default"/>
          </security>          
          <readerQuotas maxArrayLength="2147483647" maxDepth="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" maxStringContentLength="2147483647"/>
        </binding>
      </basicHttpBinding>      
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="CustomServiceBehaviour">          
          <serviceMetadata httpGetEnabled="true"/>          
          <serviceDebug includeExceptionDetailInFaults="false"/>
          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>          
        </behavior>
      </serviceBehaviors>      
    </behaviors>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <services>
      <service behaviorConfiguration="CustomServiceBehaviour" name="Namespace.MyService">        
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="MyHttpBinding" contract="Namespace.IMyService" bindingNamespace="http://tempuri/ws" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>      
    </services>
    </system.serviceModel>

关于wcf - 将WCF服务部署到SharePoint 2010网站时出现“找不到端点”错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15163342/

相关文章:

wcf - 使用 IIS7 和 WCF 时出现问题 - 甚至无法加载 .SVC

c# - 使用 Web 服务时类型不兼容

c# - WCF HttpTransport : streamed vs buffered TransferMode

c# - 绑定(bind)一个下拉列表,然后添加一个新的列表项

r - 使用 Windows 身份验证访问 R 中的共享点

wcf - 具有字符串返回值(或参数)的 ASMX WebService 强制在 WCF 客户端中生成消息协定

.net - 如何从事件处理程序中的 SPItemEventProperties 获取当前添加的项目到 SPList?

.htaccess - 将域重定向到另一个域,包括文件夹结构(如果可能,使用 SSL)

url - IIS7中的urlCompression是什么?

asp.net - 在控制台应用程序和 asp.net Web 应用程序之间共享配置