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.UseVerboseError开发者_如何学运维s = 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
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();
(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]
)
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.
精彩评论