Why is my ServiceOperation method missing from my WCF Data Services client proxy code?

6.1k Views Asked by At

I have a simple WCF Data Services service and I want to expose a Service Operation as follows:

[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class ProductDataService : DataService<ProductRepository>
{
    // This method is called only once to initialize service-wide policies.
    public static void InitializeService(IDataServiceConfiguration config)
    {
      config.SetEntitySetAccessRule("*", 
            EntitySetRights.ReadMultiple | EntitySetRights.ReadSingle);
      config.SetServiceOperationAccessRule("*", 
            ServiceOperationRights.All);
      config.UseVerboseErrors = true;
    }

// This operation isn't getting generated client side
[WebGet]
public IQueryable<Product> GetProducts()
{
    // Simple example for testing
    return (new ProductRepository()).Product;
}

Why isn't the GetProducts method visible when I add the service reference on the client?

I'm running Visual Studio 2008 SP1 and .NET Framework 3.5 SP1. I also downloaded and installed this update:

MS KB: 976127 - An update is available that provides additional features and improvements for ADO.NET Data Services in the .NET Framework 3.5 SP1 on a computer that is running Windows 7 or Windows Server 2008 R2

3

There are 3 best solutions below

3
Kev On BEST ANSWER

Finally solved this. To call a service operation on a data service class you need to use data service context object's CreateQuery or Execute methods. For example:

ProductDataService ctx = new ProductDataService(
    new Uri("http://localhost:1234/ProductDataService.svc/"));

// Method 1:
DataServiceQuery<Product> q = ctx.CreateQuery<Product>("GetProducts");
List<Product> products = q.Execute().ToList();

// Method 2:
Uri uri = new Uri(String.Format("{0}GetProducts", ctx.BaseUri), 
             UriKind.RelativeOrAbsolute);
List<Product> products = ctx.Execute<Product>(uri).ToList();

If parameters were required, say a product category on a service operation that had this signature:

[WebGet]
public IQueryable<Product> GetProducts(string category)

We would do:

// Method 1:
DataServiceQuery<Product> q = ctx.CreateQuery<Product>("GetProducts")
                                .AddQueryOption("category", "Boats") ;
List<Product> products = q.Execute().ToList();

// Method 2:
Uri uri = new Uri(String.Format("{0}GetProducts?category={1}", 
                    ctx.BaseUri, "Boats"), UriKind.RelativeOrAbsolute);
List<Product> products = ctx.Execute<Product>(uri).ToList();
5
Marc Gravell On

(this answer is incorrect (see comments), but is deliberately left here to stop other answers stumbling blindly into the same hole)


IIRC, it also needs to be an [OperationContract]

[OperationContract, WebGet]
public IQueryable<Product> GetProducts()
{
    // Simple example for testing
    return (new ProductRepository()).Product;
}

(and ideally the service itself would be a [ServiceContract])

0
Mahesh On

I had a similar issue with following sample

 [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
 public class TestService : DataService<MyService>
{
    // This method is called only once to initialize service-wide policies.
    public static void InitializeService(DataServiceConfiguration config)
    {

        config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
        config.SetServiceOperationAccessRule("*", ServiceOperationRights.AllRead);
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;

    }

    [WebGet]
    public IQueryable<string> GetStrings(int index)
    {
        string[] list = { "One", "two" };
        return list.AsQueryable(); 

    }
}

When I browsed the service http://localhost:3059/TestService.svc, the list didn't list the method with the WebGet attribute, but I am able to access it using http://localhost:3059/TestService.svc/GetStrings?index=1

This suggests to me that the WCF data service definition doesn’t list the operations when it's browsed through a web browser or there is some undocumented way to get both in the list.