2010-03-18 20 views
7

que tienen un simple servicio de WCF Data Services y quiero exponer a una operación de servicio de la siguiente manera:¿Por qué falta mi método ServiceOperation en el código proxy de mi cliente WCF Data Services?

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

¿Por qué no es el método GetProducts visibles cuando agrego la referencia de servicio en el cliente?

Estoy ejecutando Visual Studio 2008 SP1 y .NET Framework 3.5 SP1. También he descargado e instalado esta actualización:

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

+0

Las operaciones no son visibles a través del archivo .svc. Aparecen en el archivo de metadatos que puede ver con esta url: http: // localhost: 3059/TestService.svc/$ metadata –

Respuesta

10

Finalmente se solucionó esto. Para llamar a una operación de servicio en una clase de servicio de datos, necesita usar los métodos CreateQuery o Execute del objeto de contexto de servicio de datos. Por ejemplo:

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(); 

Si se requieren parámetros, por ejemplo una categoría de producto en una operación de servicio que tenía esta firma:

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

Nos haría:

// 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(); 
+0

¡Gracias por publicar la respuesta después de haberla encontrado! –

+0

Otra forma en que los servicios de datos de WCF se rompen horriblemente ... Gracias por esta solución. – Yuck

+1

Aquí hay una publicación de blog de alguien en Microsoft que detalla lo anterior. http://blogs.msdn.com/b/writingdata_services/archive/2011/03/28/calling-service-operations-from-the-client.aspx. Básicamente la misma información, pero tal vez valga la pena para alguien. –

1

(esta respuesta es incorrecta (ver comentarios), pero está deliberadamente aquí para detener otras respuestas de tropiezo a ciegas en el mismo agujero)


IIRC, sino que también tiene que ser un [OperationContract]

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

(e idealmente el servicio en sí habría una [ServiceContract])

+1

Morning Marc. Intenté decorar con el atributo 'OperationContract', pero cuando agregué la referencia de servicio en el cliente, recibí un error:" OperationContractAttributes solo es válido en métodos que se declaran en un tipo que tiene ServiceContractAttribute ". – Kev

+0

Entonces ... Si agrego el atributo '[ServiceContract]' a la clase como sugiero, entonces obtengo un error diferente: La clase de servicio de tipo ... ambos define un ServiceContract y hereda un ServiceContract de tipo System.Data.Services. IRequestHandler. La herencia de contrato solo se puede usar entre los tipos de interfaz. Si una clase está marcada con ServiceContractAttribute, debe ser el único tipo en la jerarquía con ServiceContractAttribute. "Lo ideal sería que no terminara con dos servicios. – Kev

+0

@Kev - OK; ignora esto luego. Dejaré esto aquí solo en caso de que alguien más caiga en el mismo error. Arrancaré astoria ... –

0

que tenían un parecido problema con la siguiente muestra

[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(); 

    } 
} 

Cuando exploré el servicio http://localhost:3059/TestService.svc, la lista no incluyó el método con el atributo WebGet, pero soy capaz de acceder a él mediante http://localhost:3059/TestService.svc/GetStrings?index=1

Esto me sugiere que la definición de servicios de datos de WCF no muestra la operaciones cuando se navega a través de un navegador web o hay alguna forma no documentada de obtener ambas en la lista.

Cuestiones relacionadas