2010-03-18 10 views
7

Ho un semplice servizio WCF Data Services e voglio esporre un'operazione di servizio come segue:Perché il mio metodo ServiceOperation non è presente nel mio codice proxy client di Servizi dati WCF?

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

Perché non è il metodo di GetProducts visibile quando aggiungo il riferimento al servizio sul client?

Sto eseguendo Visual Studio 2008 SP1 e .NET Framework 3.5 SP1. Ho anche scaricato e installato questo aggiornamento:

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

Le operazioni non sono visibili tramite il file .svc. Appaiono nel file di metadati che puoi vedere con questo url: http: // localhost: 3059/TestService.svc/$ metadata –

risposta

10

Finalmente risolto. Per chiamare un'operazione di servizio su una classe di servizio dati è necessario utilizzare i metodi CreateQuery o Execute dell'oggetto contesto di servizio dati. Per esempio:

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

Se sono stati richiesti i parametri, ad esempio una categoria di prodotto su un'operazione di servizio che ha avuto questa firma:

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

faremmo:

// 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

Grazie per aver postato la risposta dopo averla trovata! –

+0

Ancora un altro modo in cui i servizi dati WCF sono orribilmente danneggiati ... Grazie per questa soluzione. – Yuck

+1

Ecco un post sul blog di qualcuno in Microsoft in dettaglio sopra. http://blogs.msdn.com/b/writingdata_services/archive/2011/03/28/calling-service-operations-from-the-client.aspx. Fondamentalmente le stesse informazioni ma forse vale la pena per qualcuno. –

1

(questa risposta è errata (vedi commenti), ma viene volutamente lasciato qui per fermare altre risposte inciampo ciecamente nello stesso foro)


IIRC, ha anche bisogno di essere un [OperationContract]

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

(e, idealmente, il servizio stesso sarebbe un [ServiceContract])

+1

Morning Marc. Ho provato a decorare con l'attributo 'OperationContract', ma quando aggiungo il riferimento al servizio sul client ottengo un errore:" OperationContractAttributes è valido solo sui metodi dichiarati in un tipo con ServiceContractAttribute. ". – Kev

+0

Quindi ... Se aggiungo l'attributo '[ServiceContract]' alla classe come suggerito, allora ottengo un errore diverso: La classe di servizio di type .. both definisce un ServiceContract ed eredita un ServiceContract dal tipo System.Data.Services. IRequestHandler. L'ereditarietà del contratto può essere utilizzata solo tra i tipi di interfaccia. Se una classe è contrassegnata con ServiceContractAttribute, deve essere l'unico tipo nella gerarchia con ServiceContractAttribute. "Preferirei preferibilmente non finire con due servizi: – Kev

+0

@Kev - OK, ignoralo quindi. Lascerò questo qui solo nel caso in cui qualcun altro cada nello stesso errore. Accenderò astoria ... –

0

ho avuto un simile problema con il seguente esempio

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

    } 
} 

Quando ho passato in rassegna il servizio http://localhost:3059/TestService.svc, l'elenco non elencare il metodo con l'attributo WebGet, ma sono in grado di accedervi utilizzando http://localhost:3059/TestService.svc/GetStrings?index=1

Questo mi fa pensare che la definizione di servizio dati WCF non elenca il operazioni quando è navigato attraverso un browser web o c'è qualche modo non documentato per ottenere entrambi nella lista.

Problemi correlati