2009-05-05 20 views
2

Ich versuche, einen Webdienst zu erstellen, der für den Unterwebkontext empfindlich ist (d. H. Es stellt eine Webmethode bereit, die Listen in bestimmten Unterwebs berühren kann).Sharepoint-Webdienste in Unterwebs

Ich habe den Web-App mit den folgenden Dateien bereitgestellt:

ISAPI/MyService.asmx 
ISAPI/MyServiceWsdl.aspx 
ISAPI/MyServiceDisco.aspx 

Der Code-Behind:

[WebService] 
public class MyService : System.Web.Services.WebService 
{ 
    [WebMethod] 
    public ListSettings GetListSettings(string listName) 
    { 
     SPWeb site = SPControl.GetContextWeb(this.Context); 
     SPList list = site.Lists[listName]; 

     return new ListSettings(list); 
    } 

    [WebMethod] 
    public void UpdateListSettings(string listName, ListSettings settings) 
    { 
     SPWeb site = SPControl.GetContextWeb(this.Context); 
     SPList list = site.Lists[listName]; 

     list.EnableFolderCreation = settings.EnableFolders; 
     list.Update(); 
    } 
} 

public class ListSettings 
{ 
    public ListSettings() { } 

    internal ListSettings(SPList list) 
    { 
     EnableFolders = list.EnableFolderCreation; 
    } 

    public bool EnableFolders { get; set; } 
} 

Dieser ganz gut an der Wurzel Web meiner Website-Sammlung zu arbeiten scheint. Wenn ich jedoch Anfragen an http://moss/subweb/_vti_bin/MyService.asmx, und stoppen Sie die Web-Methode an einem Haltepunkt, um den HttpContext zu überprüfen, stelle ich fest, dass die Anfrage an gestellt wurde.

Ich habe eine Reihe von Ressourcen gelesen, die die Anpassungen beschreibt, die in den WSDL/disco-Dateien und in der spdisco.aspx-Datei in ISAPI benötigt werden, und die Anpassungen vorgenommen habe, die ich vornehmen sollte. Wie so:

In MyServiceDisco.aspx:

<%@ Page Inherits="System.Web.UI.Page" Language="C#" %> 
<%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
<%@ Import Namespace="Microsoft.SharePoint.Utilities" %> 
<%@ Import Namespace="Microsoft.SharePoint" %> 
<% Response.ContentType = "text/xml"; %> 

<discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/disco/"> 
    <contractRef ref=<% SPEncode.WriteHtmlEncodeWithQuote(Response, SPWeb.OriginalBaseUrl(Request) + "?wsdl", '"'); %> 
      docRef=<% SPEncode.WriteHtmlEncodeWithQuote(Response, SPWeb.OriginalBaseUrl(Request), '"'); %> 
      xmlns="http://schemas.xmlsoap.org/disco/scl/" /> 
    <soap address=<% SPEncode.WriteHtmlEncodeWithQuote(Response, SPWeb.OriginalBaseUrl(Request), '"'); %> 
     xmlns:q1="http://tempuri.org/" binding="q1:MyServiceSoap" xmlns="http://schemas.xmlsoap.org/disco/soap/" /> 
    <soap address=<% SPEncode.WriteHtmlEncodeWithQuote(Response, SPWeb.OriginalBaseUrl(Request), '"'); %> 
     xmlns:q2="http://tempuri.org/" binding="q2:MyServiceSoap12" xmlns="http://schemas.xmlsoap.org/disco/soap/" /> 
</discovery> 

An der Spitze der MyServiceWsdl.aspx:

<%@ Page Inherits="System.Web.UI.Page" Language="C#" %> 
<%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
<%@ Import Namespace="Microsoft.SharePoint.Utilities" %> 
<%@ Import Namespace="Microsoft.SharePoint" %> 
<% Response.ContentType = "text/xml"; %> 

und unten:

<wsdl:service name="MyService"> 
    <wsdl:port name="MyServiceSoap" binding="tns:MyServiceSoap"> 
     <soap:address location=<% SPEncode.WriteHtmlEncodeWithQuote(Response, SPWeb.OriginalBaseUrl(Request), '"'); %> /> 
    </wsdl:port> 
    <wsdl:port name="MyServiceSoap12" binding="tns:MyServiceSoap12"> 
     <soap12:address location=<% SPEncode.WriteHtmlEncodeWithQuote(Response, SPWeb.OriginalBaseUrl(Request), '"'); %> /> 
    </wsdl:port> 
    </wsdl:service> 

Und schließlich die Ergänzungen zu spdisco.aspx:

<contractRef ref=<% SPEncode.WriteHtmlEncodeWithQuote(Response, spWeb.Url + "/_vti_bin/MyService.asmx?wsdl", '"'); %> 
      docRef=<% SPEncode.WriteHtmlEncodeWithQuote(Response, spWeb.Url + "/_vti_bin/MyService.asmx", '"'); %> 
      xmlns="http://schemas.xmlsoap.org/disco/scl/" /> 
    <discoveryRef ref=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(spWeb.Url + "/_vti_bin/MyService?disco"),Response.Output); %> 
       xmlns="http://schemas.xmlsoap.org/disco/" /> 

Endlich dachte ich, ich hätte alles Notwendige getan, damit der Dienst in jedem Web der Websitesammlung funktioniert, aber leider scheint es nicht richtig zu sein. Was habe ich vergessen zu tun?

Update: ein weiterer Leckerbissen von Informationen ist, dass der Versuch, die Entdeckung XML zu einem "Not Found" Sharepoint Fehler führt. Mit anderen Worten, der Zugriff auf http://moss/mysubsite/_vti_bin/MyService.asmx?disco führt zu einem Sharepoint-Fehler "Datei nicht gefunden".

Update: Es stellte sich heraus, dass ein kleiner Tippfehler in MyServiceDisco.aspx den Fehler "Datei nicht gefunden" verursachte. Allerdings habe ich das behoben und jetzt ist der Service komplett kaputt. Unter Verwendung des WCF-Testclients erhalte ich die Fehlermeldung "Server konnte die Anforderung nicht verarbeiten. ---> Objektverweis wurde nicht auf eine Objektinstanz festgelegt", gefolgt von einer Stack-Ablaufverfolgung. Von einer Anwendung, an der ich arbeite, wenn ich die generierte Proxy-Klasse "MyServiceSoapClient" aufruft, lautet die Antwort "Der Remote-Server hat einen Fehler zurückgegeben: NotFound".

Arrrgggh!

Update: In Ordnung, die "Objektreferenz nicht gesetzt ..." Nachricht war das Ergebnis eines boneheaded Fehler meinerseits. Dinge scheinen jetzt zu arbeiten, außer dass die SPContext.Current.HttpRequestContext.Request.Path-Eigenschaft immer die URL zu dem Dienst unter dem Stammweb anstelle des aktuellen Webs zeigt. Ich habe Wireshark verwendet, um sicherzustellen, dass der Client POST an die richtige URL (und es ist: http://moss/subweb/_vti_bin/MyService.asmx), ich habe die ASP.NET-Tracing-Funktion verwendet und nichts bemerkt schief (die Anfrage erscheint in der Ablaufverfolgung mit die richtige URL), und ich habe das IIS-Tracing-Dienstprogramm (logman.exe) verwendet, das nichts unerwartetes anzeigt.Das einzige, was nicht richtig erscheint, ist der HttpRequest-Kontext, sobald ich den Haltepunkt in meinem Dienst erreicht habe.

Antwort

2

Duuude ... Ich habe mit verschiedenen Stücken von Sharepoint wie dies genug Probleme hatte zu sein gründlich davon überzeugt, dass es wirklich noch ein Beta-Produkt ist.

Endlich habe ich entdeckt, dass die Verwendung von SPContext anstelle von SPControl, um das aktuelle Web zu bekommen, gibt mir, was ich brauche. All MSDN-Dokumentation sagt den Web wie folgt zu erhalten:

SPControl.GetContextWeb(this.Context); 

Und, wenn Sie den integrierten Web-Service zu zerlegen, werden Sie feststellen, dass dies auch ist, wie die integrierte Web-Service die aktuelle Web erhalten . Für meinen Service, hat es nicht funktioniert, und dies tut:

SPContext.Current.Site.OpenWeb(); 

Warum ???? Warum, Microsoft, warum ??? !!!!

+1

Sie müssen auf eine veraltete Dokumentation gestoßen sein. MS waren nicht großartig damit. Blogs sind die beste Quelle für SharePoint-Best Practices. –

1

Was Sie haben, sieht gut aus mir. Ich habe das schon mehrmals ohne Probleme benutzt.

Ein Unterschied, der mir auffiel, war mein Code die SPWeb für immer etwas anders (und einfacher):

 // Get the current site based on our context 
     // Note that this approach does _not_ require a Dispose of the SPWeb 
     SPWeb site = SPContext.Current.Web; 
+0

Und Sie können den richtigen Kontext in Unterwebs bekommen? –