2013-03-01 89 views
3

我試圖在我的解決方案之一中使用來自(由於所有最新版本都需要較舊版本的庫.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#。在部署到SharePoint 2010站點的WCF服務中出現「EndPoint Not Found」錯誤

我想知道的是,爲什麼我不能得到「漂亮的元數據信息」,在瀏覽器中顯示,所以我得到了「溫暖模糊的」,並允許其他應用程序的方式,它的服務的正確發現應該工作?

我三重檢查了web.config,我有metadataExchange端點以及引用我的服務的端點都進入了,並且我將httpGetEnabled設置爲「true」。我嘗試運行svcutil/t: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> 

我在這裏真正的損失。有什麼想法嗎?

在此先感謝!

UPDATE#1: OK,我差不多讓它工作。我的意思是我「技術上」做到了,但只有在瀏覽器中並有一些注意事項。

我做的第一件事就是將以下代碼添加到我的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

現在的告誡...

  1. 我可以得到它充分發揮作用,如果我在調試模式下運行服務,這意味着它的迴歸在瀏覽器的XML響應,但ONLY在Visual Studio中託管,而不是IIS,因此它不會真正計數。

  2. 當我沒有在調試模式下運行服務時,出現一個錯誤提示「異常消息是'值不能爲null。參數名稱:source'」。

通過我的代碼在調試器步進後,我看到了真正的錯誤是:

請求類型的權限「IBM.Data.DB2.DB2Permission,的IBM.Data.DB2,版本= 9.0.0.2,文化=中立,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將找到一種方法來懲罰我試圖完成任何工作。

UPDATE#2:好的,我修復了整個「SharePoint網站不工作的事情」。基本上使用的應用程序池爲所有的SharePoint相關網站似乎已經改變,以使32位應用程序,包括SecurityTokenServiceApplication(榮譽的傢伙了,在this網站不僅有相同的問題,但也發佈瞭解決方案)。現在,雖然我不記得具體的值設置爲true每個SharePoint相關應用程序池,我願意一同演奏,並說,也許在絕望的舉動我可能只是他媽的說,開始不顧一切地更改配置設置。你知道,因爲這就是開發人員所做的經驗。

總之...

現在我的管理中心網站恢復運行,但UserProfileApplication服務仍然是靠不住的,我仍然傾向於認爲,我的SecurityTokenServiceApplication服務仍然是弗裏茨,因爲我得到一個錯誤(當然,因爲web.config被配置爲這樣做,因此隱藏了細節)告訴我「由於內部錯誤,服務器無法處理請求」。

詳情後...

UPDATE#3:好吧,我把所有的東西都還原到原來的工作形式。我確認只爲SharePoint資源使用的一個應用程序池啓用32位應用程序會有效更新所有其他應用程序以適應此類應用程序。我知道這是事實,因爲我肯定沒有爲自己的每個SharePoint相關應用程序池更改該值。我會記得經歷過這樣的事情。事實證明所有的時髦尋找「GUID樣」在SharePoint Web服務使用也全部更新,允許32位應用程序運行這是什麼原因造成我的環境全力以赴扭曲名的應用程序池。

此外,我得到了我的SecurityTokenService顯示它在瀏覽器中的元數據正確地按照所提供here的建議。雖然他們看起來有點「黑客」,但他們是小而可逆的黑客,所以我是遊戲。

總之,您可以編輯配置文件爲每個服務,像這樣:

  1. 在spStsActAsBinding結合重命名httpTransport到httpsTransport。
  2. 添加allowInsecureTransport =」 true」和enableUnsecuredResponse =」 true」添加到約束力的安全。
  3. 確保只定義1結合構造(配置文件服務例如,你會發現對於每個相同的服務爲http和https協議2結合配置)。

做這一切後,你應該能夠得到「溫暖元模糊」,我試圖以獲取我的工作自定義WCF服務。

所以現在我只需要回到修復我最初的問題,即獲得32位版本的IBM.Data.DB2 DLL與SharePoint 2010一起工作。我還沒有嘗試過的一件事是創建完全獨立於SharePoint運行的IIS託管服務。這樣做可以讓我創建一個單獨的應用程序池,實際上它可以運行32位應用程序,而不會導致SharePoint翻轉出來。

UPDATE#4:好吧,首先我要告訴你忽略我的建議,上面提到有關SecurityTokenService的問題。當然,隨着變化,你會得到「溫暖的元數據模糊」,但你可能會導致你的SharePoint網站中斷。

因此,無論如何...我現在創建了一個完全獨立於SharePoint的網站,該網站使用自己的應用程序池,該應用程序池配置爲允許32位應用程序,因此技術上應該照顧我所有的問題。那麼,當我嘗試在我的文本框中輸入文本時,它不會「自動完成」,但有網絡活動發生,因爲我在Fiddler中看到它。奇怪的部分是它只發生一次。意思是,如果我點擊backspace並重新輸入其他內容,則不會對Web服務進行額外的調用。我必須重新加載頁面才能再次進行測試。它調用方法時得到的錯誤消息是「405方法不允許」。現在我的方法接口簽名使用WebInvoke與method屬性設置爲「GET」我已經被告知應該可以正常工作,並已在過去做REST調用的返回JSON數據時,只是現在這是行不通的。哦,在網絡瀏覽器中它可以工作,並且我看到了從該方法返回的美妙的XML結果。但是,當我嘗試使用AutoCompleteExtender在我的SharePoint用戶控件調用方法(或使用任何其他客戶端爲此事)沒有。我嘗試過使用WebGet()屬性,但在Web瀏覽器中沒有返回任何內容。我想我得到了一個415錯誤。

更新#5:我發現另一篇文章,其中一些人似乎有我現在有完全相同的問題,唯一的區別是,我不能讓自動完成工作,即使我有web服務在同一個項目中。我也嘗試了他在帖子中提出的建議,他們也沒有工作。對於感興趣的人來說,這是一個link

+0

您能分享您從服務中獲得的確切異常詳情嗎?另外我注意到你的baseAddress沒有引用SVC文件的_vti_bin文件夾。你究竟在哪裏部署了ServiceContract DLL和.SVC文件? – Jomit 2013-03-01 18:45:28

+0

好點。我編輯了web.config很多次(試錯),爲了使這個工作無意中忽略了baseAddress和GetUrl中的「_vti_bin」。我已經把它們放回去,但仍然得到相同的錯誤。 – 2013-03-04 16:33:09

+0

只需重申一下,如果我在我的Web瀏覽器中輸入URL「http://myserver/sites/mysitecollection/_vti_bin/WebServices/MyService.svc/GetItems」,它實際上會查找並執行返回有效JSON數據的Web方法。 – 2013-03-04 16:49:47

回答

1

對於web部件項目(與ASCX),您可以:

1)啓用匿名身份驗證在IIS

2 SP網站)加入SP映射文件夾ISAPI

3)創建YourService.asmx在ISAPI

<%@ 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)使用你的Web服務方法在控制的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.confi G能夠是:

<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> 
+0

感謝您的建議,但我不明白爲什麼您建議我使用ASMX等過時/隱藏的架構?我多年前就使用過這種技術,雖然實施和部署起來可能比較簡單,但也不太安全和可配置。 至於其他的建議,web.config不應該要求所有的代碼,因爲各種默認綁定,如basicHttpBinding,wsHttpBinding,tcpBinding等默認情況下都是.NET已知的,沒有理由明確輸入它們你想指定某些自定義值,如maxBufferSize等 – 2013-03-04 16:38:34

+0

至於你在上面的「步驟#4」中的建議,我不太確定爲什麼我需要將所有這些添加到我的UserControl中。如果你已經閱讀AjaxControlToolKit的AutoCompleteExtender的文檔,這應該是非常簡單的。我計劃在後面添加UpdatePanel和進度條等效果,但我現在不想讓事情複雜化。此外,添加控制JavaScript只會使事情複雜化。我現在只想用一種語言。如前所述,我已經能夠從JavaScript/jQuery調用服務。 – 2013-03-04 16:45:28

+0

好吧,我**幾乎** _得到它的工作。我的意思是我「技術上」做到了,但只有在瀏覽器中並有一些注意事項。 The – 2013-03-06 16:48:27

0

所以我仍然不能得到與我的WCF服務工作,但我也沒搞清楚,如何解決EndPoint Not Found錯誤。

所以這裏有三件事情我沒有完全理解或忽略。

  1. Microsoft的WCF客戶端測試實用程序只測試SOAP請求。
  2. 所有不同的綁定是如何工作的以及它們的含義。
  3. 您需要確保正確的帳戶用於IIS中的匿名用戶身份。

隨着項目#1#2我需要添加另一個端點處理SOAP請求,要麼使用。我只有一個綁定指定爲,雖然這給了我在瀏覽器中的熱烈模糊,但實質上導致WCF客戶端實用程序不工作,因爲我基本上沒有定義任何SOAP端點。閱讀更多關於here的差異。

至於項目#3,我找到了我的答案here。它花了幾天時間編寫關於更改web.config,使用用戶名和密碼編寫代碼的文章以啓用和禁用IIS中人所知的每種形式的身份驗證類型。這是最終做到的,並允許我使用WCF客戶端測試實用程序,而不會出現令人討厭的EndPoint Not Found錯誤。

另外,對於那些有興趣的人,我已經開始了一個專門關注問題的新帖子,可以找到here

FYI:我設法去的地步,我可以從我的WCF服務,它看起來就像當代碼從ASPX的代碼隱藏頁面執行和得到返回的JSON數據返回相同JSON數據實際上工作...但由於某種原因,當使用WCF方法沒有得到自動完成。我注意到使用WCF服務方法時唯一不同的是,在獲取帶有JSON數據的甜美http 200消息之前,始終存在一個http 401認證錯誤。

+0

嗯......爲什麼我的問題投下來了?我的意思是它是如何不清楚,沒有用或沒有顯示任何研究工作?特別是關於不顯示任何研究工作的部分? – 2013-08-27 00:59:33

相關問題