2010-04-19 21 views
5

Quindi attualmente ho 2 WSDL aggiunti come riferimenti di servizio nella mia soluzione. Sembrano come questo nel mio file app.config (ho rimosso il campo "binding", perché è poco interessante):Cambia indirizzo/porta di WSDL EndPointAddress in fase di runtime?

<system.serviceModel> 
    <client> 
    <endpoint address="http://localhost:8080/query-service/jse" binding="basicHttpBinding" bindingConfiguration="QueryBinding" contract="QueryService.Query" name="QueryPort" /> 
    <endpoint address="http://localhost:8080/dataimport-service/jse" binding="basicHttpBinding" bindingConfiguration="DataImportBinding" contract="DataService.DataImport" name="DataImportPort" /> 
    </client> 
</system.serviceModel> 

Quando ho utilizzare un WSDL, sembra qualcosa di simile:

using (DataService.DataClient dClient = new DataService.DataClient()) 
{ 
    DataService.importTask impt = new DataService.importTask(); 
    impt.String_1 = "someData"; 
    DataService.importResponse imptr = dClient.importTask(impt); 
} 

Nell'istruzione "using", quando si crea un'istanza dell'oggetto DataClient, sono disponibili 5 costruttori. In questo scenario, io uso il costruttore di default:

new DataService.DataClient() 

che utilizza il built-in Endpoint stringa di Indirizzo, che presumo si estrae dalla app.config. Ma voglio che l'utente dell'applicazione abbia l'opzione di cambiare questo valore.

1) Qual è il modo migliore/più semplice per ottenere questa stringa in modo programmatico?

2) Quindi, una volta che ho autorizzato l'utente a modificare e verificare il valore, dove dovrei memorizzarlo?

Preferirei essere memorizzato in un posto (come app.config o equivalente) in modo che non ci sia bisogno di controllare se il valore esiste o no e se dovrei usare un costruttore alternativo. (Cercando di mantenere il mio codice stretto, sai?)

Qualche idea? Suggerimenti?

EDIT

Forse dovrei chiedere su questi costruttori alternative pure.

Per esempio, uno di loro si presenta così:

Quali valori potrebbe ottenere passato per "endPointConfigurationName" e "RemoteAddress"?

EDIT2

rispondere alle mie domande proprio qui, il "endPointConfigurationName" sembra essere lo stesso del "nome" nella XML app.config e il "RemoteAddress" è formattato lo stesso di "indirizzo dell'endpoint "nel codice XML app.config.

Inoltre! La risposta alla mia prima domanda su come ottenere i EndPointAddresses è la seguente:

ClientSection clSection = 
    ConfigurationManager.GetSection("system.serviceModel/client") as ClientSection; 

ChannelEndpointElementCollection endpointCollection = 
    clSection.ElementInformation.Properties[string.Empty].Value as ChannelEndpointElementCollection; 

Dictionary<string, string> nameAddressDictionary = 
    new Dictionary<string, string>(); 

foreach (ChannelEndpointElement endpointElement in endpointCollection) 
{ 
    nameAddressDictionary.Add(endpointElement.Name, 
          endpointElement.Address.ToString()); 
} 

Edit3

Ok, credo di aver capito 2 ° tempo (e quindi, piena soluzione) al mio problema . Ho trovato questo su un altro sito e ho modificato per soddisfare le mie esigenze:

Configuration configuration; 
ServiceModelSectionGroup serviceModelSectionGroup; 
ClientSection clientSection; 

configuration = 
    ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 
serviceModelSectionGroup = 
    ServiceModelSectionGroup.GetSectionGroup(configuration); 
clientSection = serviceModelSectionGroup.Client; 

foreach (ChannelEndpointElement endPt in clientSection.Endpoints) 
{ 
    MessageBox.Show(endPt.Name + " = " + endPt.Address); 
} 
configuration.Save(); 

Con questo codice, abbiamo accesso alle clientSection.Endpoints e in grado di accedere e modificare tutte le proprietà dei membri, come "Indirizzo". E quando abbiamo finito di cambiarli, possiamo fare configuration.Save() e tutti i valori vengono scritti su un file utente.

Ora ecco il trucco.In modalità debug, "configuration.save()" non sembra effettivamente mantenere i tuoi valori dall'esecuzione all'esecuzione, ma quando si esegue l'applicazione normale (fuori dalla modalità debug), i valori persistono. (Che è buono.) Quindi questo è l'unico avvertimento.

edit4

C'è un altro avvertimento. Le modifiche apportate ai WSDL non hanno effetto durante il runtime. L'applicazione deve essere riavviato per rileggere i valori del file di configurazione utente nella memoria (a quanto pare.)


L'unica altra cosa che potrei essere interessato a è trovare un modo (una volta che i valori sono stati cambiati) per ripristinare i valori ai loro valori predefiniti. Certo, probabilmente puoi eliminare il file dell'utente, ma questo elimina tutte le impostazioni personalizzate.

Qualche idea?

EDIT5

sto pensando Dependency Injection potrebbe essere perfetto qui, ma necessario per la ricerca più ...

EDIT 6

non ho commento privilegi, ma si è necessario eseguire

ConfigurationManager.RefreshSection("client"); 

per aggiornare la cache in modo che le modifiche avvengano immediatamente.

risposta

2

Se si utilizza Microsoft Aggiungi riferimento Web per creare il riferimento del servizio, quindi penso che potrebbe essere difficile modificare la connessione a livello di codice. Anche se hai modificato il codice generato automaticamente, non appena hai fatto un riferimento al servizio di aggiornamento , verrebbe sovrascritto.

La soluzione migliore è cancellare il codice generato automaticamente da Microsoft e creare le proprie classi WCF. Non è difficile e offre molta flessibilità/scalabilità.

Here's an excellent article proprio su questo argomento.

Per quanto riguarda la memorizzazione degli indirizzi personalizzati, dipenderà dalla app se si tratta di un'applicazione Silverlight, Windows o Web. La mia scelta personale è il database.

+0

Leggerò di nuovo quell'articolo (i miei occhi iniziarono a velare a circa metà dell'articolo). Ma non sarei d'accordo: è * abbastanza * difficile. Soprattutto considerando che a malapena so che cosa dovrebbero fare questi WSDL. E potrei avere fino a 22 WSDL che alla fine dovrò integrare. "Aggiungi riferimento al servizio" era una magia meravigliosa. Sicuramente limitante, ma meraviglioso in quanto ha portato rapidamente il mio progetto. (Ti darò un +1 comunque, dato che è una buona scoperta Grazie!) – Pretzel

+0

Sì, mi rendo conto di sembrare un pigro programmatore. Non siamo tutti, in una certa misura? :-) Giuro che prenderò qualche altro scatto in questo, ma sembra che sto cercando di ottenere una laurea in Ingegneria Civile e Architettura, solo per costruire una baracca nel mio cortile. Lo sai? – Pretzel

+0

@Pretzel - Bel dolore, 22 riferimenti! In quel caso c'è una soluzione rapida e sporca che ho usato in passato. Prova a sfruttare le lezioni parziali. L'idea dovrebbe avere una classe parziale per quelli generati automaticamente in modo da non perdere il codice su un aggiornamento di riferimento del servizio. Ad ogni modo sei a un bivio però. Apprendi e analizza il codice generato da Microsoft o scrivi il tuo. – Matt

Problemi correlati