2011-12-14 7 views
3

Sharepoint Foundation 2010サイトのカスタムWebパーツからロードされたjavascriptからAJAXによって呼び出すことができるWCFを設定します。 Javascript側の処理を簡略化するため、Jsonに呼び出し元に戻すRestfulサービスを提示したいと思います。AJAXを使用してSharepoint WCFにアクセスするときのSPContext.Current null

問題は、AJAX呼び出しでサーバーを呼び出すと、SPContext.Currentがnullであるという問題です。

私はWebサービスを作成するには、SVCファイルに

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$"%> 
<%@ServiceHost Language="C#" Debug="true" 
Service="Driftportalen.LvService.SuggestService" 
Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory, Microsoft.SharePoint.Client.ServerRuntime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" 
    %> 

をMultipleBaseAddressWebServiceHostFactoryを使用していますWebサービスのための契約は、次のようにWebサービスの

[ServiceContract(Namespace = "", ProtectionLevel= ProtectionLevel.None)] 
public interface ISuggestServiceTest 
{ 
    [WebGet(UriTemplate = "/SuggestAddress/{streetprefix}/", ResponseFormat = WebMessageFormat.Json)] 
    [OperationContract] 
    Dictionary<string, GenericAddress> SuggestAddress(string streetprefix); 
} 

実装は基本的です。

[Guid("BA6733B3-F98D-4AD8-837D-7673F8BC527F")] 
[BasicHttpBindingServiceMetadataExchangeEndpoint] 
[ServiceBehavior(IncludeExceptionDetailInFaults = true, AddressFilterMode = AddressFilterMode.Any)] 
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] 
public class SuggestService : ISuggestServiceTest 
{ 
    private SPWeb currentWeb; 

    public SPWeb CurrentWeb 
    { 
     get 
     { 
      if (currentWeb == null) 
      { 
       var siteUrl = SPContext.Current.Web.Url; 
       SPSecurity.RunWithElevatedPrivileges(delegate 
       { 
        using (var site = new SPSite(siteUrl)) 
        using (var web = site.OpenWeb()) 
        { 
         currentWeb = web; 
        } 
       }); 
      } 
      return currentWeb; 
     } 
    } 


    public Dictionary<string, GenericAddress> SuggestAddress(string streetprefix) 
    { 
     LvService lvService = new LvService(CurrentWeb); 

     Dictionary<string, GenericAddress> suggestions = new Dictionary<string, GenericAddress>(); 

     //SNIP 
     //Code that uses lvService to populate suggestions 

     return suggestions; 
    } 
} 

私は、ウェブブラウザからWebサービスを呼び出す場合、すべてが期待どおりに動作し、私は右のデータを取り戻すことをことを確認しました。私はFirebugのを使用して、次のAjax呼び出し

$.ajax({ 
    url: addressUrl + "/"+request.term, 
    dataType: 'json', 
    success: function (data) { 
     responseCallback(data); 
    $(this).removeClass("fetching"); 
    } 
}); 

を使用

私は正しいURLはJavaScriptから呼び出されたことを確認したと私は、右のコードが実際に到達したことをサーバー側で確認しましたが、SPContext。現在はnullです。

Sharepointサーバーは、Windowsとクレームを使用してログインします。つまり、実際のWCFはSharepointソリューションとは別のアカウントを使用して実行されますが、vti_bin以下のフォルダに展開するので、SharepointはそのコンテキストをWCFに提供する必要があります。私は、AJAXコールがSharepointにそのコンテキストを提供するようには誘発されないと思われますが、ある意味ではそれは匿名です。

は、最初に私は、Webサービス自体はブラウザ専用から呼び出されたときに、それがランダムに失敗するので、非難したと仮定が、私は私が作ることができますどのようにのSharePoint Foundationへのアップグレードをインストールすることで、2010年

をその問題を整理だと思いますSharepointサイトにサインインしたユーザーのコンテキストにWebサービスがアクセスできるようにするJavascriptからのAJAX呼び出しを受け入れるjavascript/WebサービスからのAJAX呼び出し?

答えて

5

私はこの問題の解決策を見つけ出しました。誰かがこの種の問題に遭遇した場合に私の所見を共有したいと思います。

基本的な問題は、Microsoft svcファクトリがajax呼び出しのために適切なアクセスバインディングを追加できないという事実によって引き起こされます。これは、vti_binフォルダの認証マジックが発生しないことを意味します。実行中のsvcを取得しますが、通常のアクセスはうまく動作しますが、javascriptからのajax呼び出しでSharepointコンテキストにアクセスするとSharepointコンテキストがありません。

交換する

public class AjaxCompatibleRestServiceHostFactory : Microsoft.SharePoint.Client.Services.MultipleBaseAddressBasicHttpBindingServiceHostFactory 
{ 
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
    { 
     return new AjaxCompatibleRestServiceHost(serviceType, baseAddresses); 
    } 
} 

そして最後にactuallコードを次のように新しい工場の

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$"%> 
<%@ServiceHost Language="C#" Debug="true" 
Service="Driftportalen.LvService.SuggestService, $SharePoint.Project.AssemblyFullName$" 
Factory="Driftportalen.LvService.AjaxCompatibleRestServiceHostFactory,Driftportalen.LvService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ab8de4d18e388c1f" 
     %> 

実装が正しいものとバインディングを置き換えるために工場を拡張することによって問題を解決することができますバインディング

public class AjaxCompatibleRestServiceHost : Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHost 
{ 

    public AjaxCompatibleRestServiceHost(Type serviceType, params Uri[] baseAddresses) 
     : base(serviceType, baseAddresses) 
    { 
    } 

    protected override void OnOpening() 
    { 
     base.OnOpening(); 

     foreach (ServiceEndpoint endpoint in base.Description.Endpoints) 
     { 
      if (((endpoint.Binding != null) && (endpoint.Binding.CreateBindingElements().Find<WebMessageEncodingBindingElement>() != null)) && (endpoint.Behaviors.Find<WebScriptEnablingBehavior>() == null)) 
      { 
       // try remove any previous behaviours 
       while (endpoint.Behaviors.Count > 0) 
       { 
        endpoint.Behaviors.RemoveAt(0); 
       } 
       endpoint.Behaviors.Add(new WebHttpBehavior()); 
      } 

     } 


     ServiceDebugBehavior debug = this.Description.Behaviors.Find<ServiceDebugBehavior>(); 
     // if not found - add behavior with setting turned on 
     if (debug == null) 
     { 
      this.Description.Behaviors.Add(
       new ServiceDebugBehavior() { IncludeExceptionDetailInFaults = true }); 
     } 
     else 
     { 
      // make sure setting is turned ON  
      if (!debug.IncludeExceptionDetailInFaults) 
      { 
       debug.IncludeExceptionDetailInFaults = true; 
      } 
     } 

     ServiceMetadataBehavior metadata =this.Description.Behaviors.Find<ServiceMetadataBehavior>(); 
     // if not found - add behavior with setting turned on 
     if (metadata == null) 
     { 
      this.Description.Behaviors.Add(
       new ServiceMetadataBehavior() { HttpGetEnabled = true }); 
     } 
     else 
     { 
      // make sure setting is turned ON  
      if (!metadata.HttpGetEnabled) 
      { 
       metadata.HttpGetEnabled = true; 
      } 
     } 

    } 
} 

おそらくあなたはWebSc WebHttpBehaviorの代わりにriptEnablingBehaviorを使用すると、結果が返されるときにラップされたものにすることができます。

考慮すべき点がいくつかあります。ネット上には、SP1が不足するとSharepointのコンテキストが不足する可能性があることが示されているので、問題が発生した場合は最新のサービスパックがあることを確認してください。

最後に、RESTサービスを構築している場合は、UriTemplateを使用して目的のURL構造を取得することが魅力的かもしれません。残念ながら、この記事の執筆時点では、このシナリオではUriTemplateはMicrosoftによってサポートされていませんので、UriTemplateの存在を基に設計する前にこの問題を調査してください。

4

私はSharePoint 2013を使用して同じ問題に直面しました。私は基本的に現在のサイトとWeb IDを取得する別のものについて読んでから、特権を昇格してから。このようなもの: https://sharepoint.stackexchange.com/questions/74205/spcontext-current-is-null-for-ihttphandler

しかし、偶然、私は以下を発見しました。次のように現在のサイトのIDを取得した後: var currentSiteId = SPContext.Current.Site.ID;

SPContext.Currentは、昇格された特権の代理人の中で、もはやnullではありません!特権を昇格する前にこのプロパティにアクセスするだけで利用可能になるようです。奇妙な!!!!

実際には、私が追加したコードは、後でその変数を使用しなくても、上記のものだけです。私はどこかにキャッチがあるという気持ちがあります!

+0

これは私の一日を保存しました!あなたはロック:) –

関連する問題