title: Change Address/Port of WSDL EndPointAddress at runtime?
body: <p>So I currently have 2 WSDLs added as Service References in my solution. They look like this in my app.config file (I removed the "bindings" field, because it's uninteresting):</p>
  
  <pre><code>&lt;system.serviceModel&gt;
    &lt;client&gt;
      &lt;endpoint address="http://localhost:8080/query-service/jse" binding="basicHttpBinding" bindingConfiguration="QueryBinding" contract="QueryService.Query" name="QueryPort" /&gt;
      &lt;endpoint address="http://localhost:8080/dataimport-service/jse" binding="basicHttpBinding" bindingConfiguration="DataImportBinding" contract="DataService.DataImport" name="DataImportPort" /&gt;
    &lt;/client&gt;   
  &lt;/system.serviceModel&gt;
  </code></pre>
  
  <p>When I utilize a WSDL, it looks something like this:</p>
  
  <pre><code>using (DataService.DataClient dClient = new DataService.DataClient())
  {
    DataService.importTask impt = new DataService.importTask();
    impt.String_1 = "someData";
    DataService.importResponse imptr = dClient.importTask(impt);
  }
  </code></pre>
  
  <p>In the "using" statement, when instantiating the DataClient object, I have 5 constructors available to me. In this scenario, I use the default constructor:</p>
  
  <pre><code>   new DataService.DataClient()
  </code></pre>
  
  <p>which uses the built-in Endpoint Address string, which I assume is pulled from app.config. But I want the user of the application to have the option to change this value.</p>
  
  <p>1) What's the best/easiest way of programatically obtaining this string?</p>
  
  <p>2) Then, once I've allowed the user to edit and test the value, where should I store it? </p>
  
  <p>I'd prefer having it be stored in a place (like app.config or equivalent) so that there is no need for checking whether the value exists or not and whether I should be using an alternate constructor. (Looking to keep my code tight, ya know?)</p>
  
  <p>Any ideas? Suggestions?</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>Maybe I should ask about these Alternate constructors as well.</p>
  
  <p>For example, one of them looks like this:</p>
  
  <pre><code>   new DataService.DataClient(string endPointConfigurationName, 
                                string remoteAddress)
  </code></pre>
  
  <p>What values could get passed for "endPointConfigurationName" and "remoteAddress"?</p>
  
  <p><strong>EDIT2</strong></p>
  
  <p>Answering my own questions here, the "endPointConfigurationName" appears to be the same as the "name" in the app.config XML and the "remoteAddress" is formatted the same as "endpoint address" in the app.config XML.</p>
  
  <p>Also!  The answer to my first question about getting the EndPointAddresses is the following:</p>
  
  <pre><code>ClientSection clSection =
     ConfigurationManager.GetSection("system.serviceModel/client") as ClientSection;
  
  ChannelEndpointElementCollection endpointCollection =
     clSection.ElementInformation.Properties[string.Empty].Value as ChannelEndpointElementCollection;
  
  Dictionary&lt;string, string&gt; nameAddressDictionary = 
     new Dictionary&lt;string, string&gt;();
  
  foreach (ChannelEndpointElement endpointElement in endpointCollection)
  {
     nameAddressDictionary.Add(endpointElement.Name, 
                               endpointElement.Address.ToString());
  }
  </code></pre>
  
  <p><strong>EDIT3</strong></p>
  
  <p>Ok, I think I've figured out the 2nd half (and thus, full solution) to my problem. I found this on another website and I modified it to meet my needs:</p>
  
  <pre><code>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();
  </code></pre>
  
  <p>With this code, we have access to the clientSection.Endpoints and can access and change all the member properties, like "Address". And then when we're done changing them, we can do configuration.Save() and all the values get written out to a user file. </p>
  
  <p>Now here's the catch. In debug mode, the "configuration.save()" does not appear to actually persist your values from execution to execution, but when running the application normal (outside of debug mode), the values persist. (Which is good.) So that's the only caveat.</p>
  
  <p><strong>EDIT4</strong></p>
  
  <p>There is another caveat. The changes made to the WSDLs do not take effect during runtime. The application needs to be restarted to re-read the user config file values into memory (apparently.)</p>
  
  <hr>
  
  <p>The only other thing that I might be interested in is finding a way (once the values have been changed) to revert the values to their defaults. Sure, you can probably delete the user file, but that deletes all of the custom settings.</p>
  
  <p>Any ideas?</p>
  
  <p><strong>EDIT5</strong></p>
  
  <p>I'm thinking Dependency Injection might be perfect here, but need to research it more...</p>
  
  <p>EDIT 6</p>
  
  <p>I don't have comment privileges but you need to run</p>
  
  <pre><code>ConfigurationManager.RefreshSection("client");
  </code></pre>
  
  <p>to have the cache updated so that changes happen immediately.</p>