2013-08-16 11 views
7

Ho un servizio WCF chiamiamolo UserService. UserService ha un riferimento a una libreria di classi. Chiamiamolo DoWork.dll. Lo DoWork.dll ha un riferimento al servizio WCF per un servizio diverso che chiameremo CompanyService.Errore di configurazione dell'endpoint WCF: l'attributo 'contratto' non è valido?

Ora, quando ho provato a chiamare lo UserService, avrei ricevuto un messaggio di errore non configurato. Dopo aver letto sul Web ho scoperto che ho bisogno di aggiungere le associazioni CompanyService e le informazioni sul client nello UserServiceweb.config sotto il nodo <system.serviceModel>.

Eccolo:

<system.serviceModel> 
    <bindings> 
     <basicHttpBinding> 
     <binding name="BasicHttpBinding_IComapnyService" /> 
     </basicHttpBinding> 
    </bindings> 
    <client> 
     <endpoint name="BasicHttpBinding_ICompanyService" 
      address="http://it-dev.company.local:81/Project/Copmpany/CompanyService.svc" 
      binding="basicHttpBinding" 
      bindingConfiguration="BasicHttpBinding_IComapnyService" 
      contract="CompanyService.ICompanyService" /> 
    </client> 

Il problema che ho è il contract="CompanyService.ICompanyService" mi mostra l'errore:

The 'contract' attribute is invalid - The value 'CompanyService.ICompanyService' is invalid according to its datatype 'clientContractType' - The Enumeration constraint failed.

Ora, se aggiungo il riferimento CompanyService direttamente al progetto UserService WCF, la l'errore va via (ovviamente). Tuttavia, non dovrei farlo. Ho provato a qualificare completamente lo spazio dei nomi del contratto ICompanyService e anche questo non funziona. Ho eliminato il file .suo e ricostruito il progetto e questo non funziona (suggerito altrove sul web). Inoltre, se si digita contract=, ottengo l'elenco a discesa ma CompanyService.ICompanyService non si trova da nessuna parte (solo quando faccio riferimento al servizio direttamente nel progetto UserService).

Ho provato a configurarlo utilizzando Tools > WCF Service Configuration Editor e questo non aiuta.

Devo notare che tutto sembra funzionare bene, ma non mi piace il fatto che intellisense mi stia dando la sottolineatura blu ondulata e quel messaggio di errore. Ho la sensazione che ho bisogno di qualcos'altro nello web.config per farlo funzionare poiché il UserService fa riferimento allo DoWork.dll, che a sua volta fa riferimento allo CompanyService il cui contratto non riesco a vedere correttamente.

Qualsiasi suggerimento è molto apprezzato. Grazie in anticipo.

+0

Mi sono imbattuto recentemente in questo e ho scoperto che in realtà includere lo spazio dei nomi completo stava contribuendo ai miei problemi. Utile da notare per chiunque altro con questo problema. – Ian

risposta

2

Hai ragione, non dovresti farlo.

L'architettura di avere una DLL (DoWork.dll) con un "riferimento di servizio" (ComanyService) non è buona. A meno che la DLL non abbia codificato l'endpoint del client (nel codice) per chiamare l'CompanyService, chiunque utilizzi la DLL dovrà cercare di capire come configurare l'endpoint client per un servizio di cui non sono a conoscenza. Qual è il tuo incontro.

Il motivo per cui questo funziona quando si aggiunge un riferimento al servizio direttamente dal proprio UserService è che quando si esegue questa operazione, si ottiene una copia del ServiceContract dai metadati di CompanyService. Per provarlo, guarda nel file Reference.cs che viene generato, cerca CompanyService e troverai che ha l'attributo [ServiceContract], identificandolo come servizio WCF. Inoltre, vedrai gli attributi [OperationContract] per i metodi, oltre a qualsiasi [DataContracts], il servizio che faccio anche per lo scambio. In altre parole, tutti questi "tipi" sono stati importati nel progetto e quando si compila, WCF è ora in grado di trovare questi tipi durante l'istanziazione dell'endpoint del client.

Se CompanyService è uno dei servizi, prendere in considerazione l'estrazione della definizione ServiceContract (interfaccia) in una DLL separata. Quindi, è possibile fare riferimento a tali tipi come "riferimenti di assembly" dal servizio (CompanyService) e qualsiasi applicazione client, come UserService.Almeno in questo modo non devi aggiungere un riferimento al servizio. Ma devi ancora compilare la sezione .... nella tua domanda per un servizio che tecnicamente potresti non conoscere i dettagli di. Non l'approccio migliore.

Un approccio migliore è spostare la dipendenza del servizio da DoWork.dll. È possibile farlo semplicemente spostando la logica nell'implementazione di UserService.

Oppure, se è necessario mantenere indipendente DoWork.dll, prendere in considerazione la possibilità di includere DoWork con il servizio WCF, che dipende da CompanyService. Quindi, da UserService, aggiungere un riferimento al servizio nuovo DoWork. Questo è più in linea con gli inquilini di SOA e consentirà ai tuoi servizi di evolvere in modo indipendente.

+0

Grazie per le informazioni. Forse la mia architettura è cattiva. Il CompanyService è SOLO un servizio WCF perché ho bisogno che funzioni come un singleton con il comportamento di servizio di InstanceContextMode.Single. Nel mio sistema ora, il metodo di un servizio in CompanyService non dovrebbe MAI essere chiamato da qualsiasi altro oltre a DoWork.DLL. Quindi la mia domanda di follow-up è se dovessi eseguire un hard-code dell'endpoint nel DoWork.DLL o dovrei eliminare il ComapnyService tutti insieme e in qualche modo spostare la sua logica nel DoWork.dll (in qualche modo mantenendo il comportamento del singleton)? Grazie. – BBauer42

+1

No, non inserire l'hardcode nell'endpoint. L'ultima opzione che ti ho presentato probabilmente funzionerà meglio per il tuo scenario. Esistono modi (tramite le impostazioni di protezione) per assicurare che il servizio che esegue il wrapping DoWork.DLL sia l'unico servizio che può chiamare CompanyService. Quindi, qualcosa di simile. UserService <--> NewWrapperService (dowork) <--> CompanyService –