2011-12-14 2 views
3

Sharepoint Foundation 2010 사이트의 사용자 정의 webpart에서로드 된 javascript를 통해 AJAX에서 호출 할 수있는 WCF를 설정하려고합니다. Javascript 측에서 처리를 단순화하기 위해 Json에게 호출자에게 다시 제공하는 Restful 서비스를 제시하고자합니다.AJAX를 사용하여 Sharepoint WCF에 액세스 할 때 SPContext.Current null

문제는 내가 AJAX 호출로 서버를 호출 할 때 SPContext.Current가 null이라는 것입니다. 내가 MultipleBaseAddressWebServiceHostFactory을 사용하고

WebService에가의 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" 
    %> 

에게 계약을 만들려면 다음과 같이 웹 서비스의

[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; 
    } 
} 

나는 모든 것이 예상대로 작동하는 웹 브라우저에서하고있는 웹 서비스를 호출하면 내가 다시 올바른 데이터를 얻을 수 있음을 확인했습니다.

나는 다음과 같은 아약스는 내가 올바른 URL이 자바 스크립트에서 호출되는 것을 확인하고 난이 올바른 코드가 실제로 도달하는 서버 측에 확인하지만, SPContext 한 방화범을 사용하여

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

전화를 사용합니다. 현재 null입니다.

Sharepoint 서버는 Windows 및 클레임을 사용하여 로그인합니다. 즉, Sharepoint 솔루션과 다른 계정을 사용하여 실제 WCF가 실행되지만 vti_bin 아래 폴더에 배포 할 때 Sharepoint는 해당 컨텍스트를 WCF에 제공해야합니다. 나에게 AJAX 호출이 Sharepoint에서 컨텍스트를 제공하지 못하는 것처럼 보입니다. 어떤면에서는 익명입니다.

은 첫째 나는 자체가 browswer에서 호출 할 때 무작위로 실패 이후 비난했다 웹 서비스를 가정,하지만 난 내가 할 수있는 방법 재단 2010

셰어에 업그레이드를 설치하여이 문제를 정리 생각 셰어 포인트 사이트에 로그인 한 사용자의 컨텍스트에 웹 서비스가 액세스 할 수 있도록 자바 스크립트에서 AJAX 호출을 허용하는 자바 스크립트/웹 서비스의 AJAX 호출?

답변

5

나는이 문제의 해결책을 알아 냈으므로 다른 누구도 이런 종류의 문제를 발견하지 못했을 때 내 발견을 공유하고 싶다.

기본 문제는 Microsoft svc 팩토리가 ajax 호출에 적합한 액세스 바인딩을 추가하지 못하기 때문에 발생합니다. 이것은 vti_bin 폴더의 인증 마법이 발생하지 않음을 의미합니다. 실행중인 svc가 있지만 일반 액세스가 정상적으로 작동하더라도 javascript에서 ajax 호출을 사용하여 Sharepoint 컨텍스트에 액세스 할 필요가 없습니다.

교체

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

그리고 마지막으로 실제로 사용 코드를 다음과 같이 새로운 공장의

<%@ 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을 사용하여 동일한 문제에 직면했습니다. 권한을 높이기 전에 기본적으로 현재 사이트와 웹 ID를 얻은 다음 다른 것을 읽었 기 때문에 솔루션을 사용해 볼 기회가 없었습니다. . 이런 식으로 : https://sharepoint.stackexchange.com/questions/74205/spcontext-current-is-null-for-ihttphandler

그러나 우연히 나는 다음과 같은 것을 발견했다. 다음과 같이 현재 사이트의 ID를 얻은 후 : var currentSiteId = SPContext.Current.Site.ID;

SPContext.Current는 승격 된 권한 대리자 내부에서 더 이상 null이 아닙니다! 권한을 높이기 전에이 속성에 액세스하는 것만으로도 사용할 수 있습니다! 기묘한!!!!

실제로 내가 추가 한 유일한 코드 행은 나중에 볼 때 변수를 사용하지 않고 위에서 본 것입니다. 나는 어딘가에 잡기가 있다는 느낌을 가지고있다!

+0

이것은 내 하루를 저장했습니다! 너 락 : –

관련 문제