1

I've created a custom OData service in SharePoint 2010 to return a list of entities representing subsites, however I'd also like to be able to return the root.

To this end, I've created a function to do just that - however the service does not expose it (nor does it expose any service operation where I could pass a value over to get a specific sites subsites.) And with the data from SharePoint being hierarchical rather than relational, it's not a case of plucking a value from a selection...

Anyone any suggestions?

Testing code is:

 using System.Collections.Generic; using System.Data.Services; using
 System.Linq; using System.ServiceModel.Web; using
 Microsoft.SharePoint;

 namespace SpRestTest {
     public class MyContext {

         private List<SpSiteTest> Subwebs(SPWeb web)
         {
             return web.GetSubwebsForCurrentUser().Select(subweb => new SpSiteTest
             {
                 Id = subweb.ID,
                 Name = subweb.Name,
                 Title = subweb.Title,
                 Children = Subwebs(subweb)
             }).ToList();
         }

         public IQueryable<SpSiteTest> SubSites {
             get {
                 return (from item in SPContext.Current.Web.GetSubwebsForCurrentUser()
                         select new SpSiteTest {
                             Name = item.Name,
                             Title = item.Title,
                             Id = item.ID,
                             Children = Subwebs(item)
                         }).AsQueryable();
             }
         }

         public SpSiteTest Root {
             get {
                 var web = SPContext.Current.Site.RootWeb;
                 return new SpSiteTest
                 {
                     Name = web.Name,
                     Title = web.Title,
                     Id = web.ID,
                     Children = Subwebs(web)
                 };
             }
         }

         [WebGet]
         public IQueryable<SpSiteTest> Testing(string test)
         {
             return SubSites;
         }

       [WebGet]
        [SingleResult]
        public string GetResult(string value) {//Simple test
            return string.Format("Testing {0}", value);
        }
     } 
}

The curious thing is that SP2010 has kittens when exposing Service Operations. When I update the config in the class inheriting DataService to:

config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);

It doesn't work, but when I change it to :

config.SetServiceOperationAccessRule("GetResult", ServiceOperationRights.All);

It errors with:

<P class="intro">The server encountered an error processing the request. The exception message is 'Exception has been thrown by the target of an invocation.'. See server logs for more details. The exception stack trace is:</P>
<P class="intro">   at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Data.Services.DataServiceConfiguration.InvokeStaticInitialization(Type type)
   at System.Data.Services.DataServiceConfiguration.Initialize(Type type)
   at System.Data.Services.DataService`1.CreateConfiguration(Type dataServiceType, IDataServiceMetadataProvider provider)
   at System.Data.Services.DataService`1.CreateProvider()
   at System.Data.Services.DataService`1.EnsureProviderAndConfigForRequest()
   at System.Data.Services.DataService`1.HandleRequest()
   at System.Data.Services.DataService`1.ProcessRequestForMessage(Stream messageBody)
   at SyncInvokeProcessRequestForMessage(Object , Object[] , Object[] )
   at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</P>

The annoying thing is I can get this to work perfectly using a json/xml outputting system, but - wishing to make upgrading to SP2013 easier in the future - I'm wanting to stick with OData/Atom formatting and preferably only using one subset of WCF to make the life of anyone picking up my final code a bit easier.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.