servicemodel example app c# wcf app-config configuration-files

c# - example - ¿Cómo modificar programáticamente la configuración de la dirección del punto final WCF app.config?



wcf service binding configuration (11)

¿Esto está en el lado del cliente?

Si es así, debe crear una instancia de WsHttpBinding y EndpointAddress, y luego pasar esos dos al constructor del cliente proxy que toma estos dos parámetros.

// using System.ServiceModel; WSHttpBinding binding = new WSHttpBinding(); EndpointAddress endpoint = new EndpointAddress(new Uri("http://localhost:9000/MyService")); MyServiceClient client = new MyServiceClient(binding, endpoint);

Si está en el lado del servidor, tendrá que crear su propia instancia de ServiceHost, y agregarle los puntos finales de servicio apropiados.

ServiceHost svcHost = new ServiceHost(typeof(MyService), null); svcHost.AddServiceEndpoint(typeof(IMyService), new WSHttpBinding(), "http://localhost:9000/MyService");

Por supuesto, puede agregar varios de estos puntos finales de servicio a su servidor de servicio. Una vez que haya terminado, debe abrir el host del servicio llamando al método .Open ().

Si desea poder dinámicamente (en tiempo de ejecución) elegir qué configuración usar, puede definir múltiples configuraciones, cada una con un nombre único, y luego llamar al constructor apropiado (para su servidor de servicio o su cliente proxy) con la configuración nombre que desea usar

Por ejemplo, podría tener fácilmente:

<endpoint address="http://mydomain/MyService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IASRService" contract="ASRService.IASRService" name="WSHttpBinding_IASRService"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="https://mydomain/MyService2.svc" binding="wsHttpBinding" bindingConfiguration="SecureHttpBinding_IASRService" contract="ASRService.IASRService" name="SecureWSHttpBinding_IASRService"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="net.tcp://mydomain/MyService3.svc" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IASRService" contract="ASRService.IASRService" name="NetTcpBinding_IASRService"> <identity> <dns value="localhost" /> </identity> </endpoint>

(tres nombres diferentes, diferentes parámetros mediante la especificación de diferentes configuraciones de enlace) y luego elija el correcto para crear una instancia de su servidor (o proxy de cliente).

Pero en ambos casos, servidor y cliente, debe elegir antes de crear realmente el servidor de servicio o el cliente proxy. Una vez creados, estos son inmutables ; no puede modificarlos una vez que estén en funcionamiento.

Bagazo

Me gustaría modificar programáticamente mi archivo app.config para establecer qué punto final del archivo de servicio debería usarse. ¿Cuál es la mejor manera de hacer esto en tiempo de ejecución? Para referencia:

<endpoint address="http://mydomain/MyService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IASRService" contract="ASRService.IASRService" name="WSHttpBinding_IASRService"> <identity> <dns value="localhost" /> </identity> </endpoint>


Creo que lo que quieres es cambiar en tiempo de ejecución una versión de tu archivo de configuración, si es así crea una copia de tu archivo de configuración (también dale la extensión relevante como .Debug o .Release) que tenga las direcciones correctas (lo que te da una versión de depuración y una versión de tiempo de ejecución) y crea un paso posterior a la compilación que copia el archivo correcto según el tipo de compilación.

Aquí hay un ejemplo de un evento de postconstrucción que he usado en el pasado que anula el archivo de salida con la versión correcta (depuración / tiempo de ejecución)

copy "$(ProjectDir)ServiceReferences.ClientConfig.$(ConfigurationName)" "$(ProjectDir)ServiceReferences.ClientConfig" /Y

donde: $ (ProjectDir) es el directorio del proyecto donde se encuentran los archivos de configuración $ (ConfigurationName) es el tipo de compilación de configuración activa

EDITAR: Consulte la respuesta de Marc para obtener una explicación detallada sobre cómo hacer esto mediante programación.


Este es el código más corto que puede usar para actualizar el archivo de configuración de la aplicación, incluso si no tiene definida una sección de configuración:

void UpdateAppConfig(string param) { var doc = new XmlDocument(); doc.Load("YourExeName.exe.config"); XmlNodeList endpoints = doc.GetElementsByTagName("endpoint"); foreach (XmlNode item in endpoints) { var adressAttribute = item.Attributes["address"]; if (!ReferenceEquals(null, adressAttribute)) { adressAttribute.Value = string.Format("http://mydomain/{0}", param); } } doc.Save("YourExeName.exe.config"); }


He modificado y extendido el código de Malcolm Swaine para modificar un nodo específico por su atributo de nombre y también para modificar un archivo de configuración externo. Espero eso ayude.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using System.Reflection; namespace LobbyGuard.UI.Registration { public class ConfigSettings { private static string NodePath = "//system.serviceModel//client//endpoint"; private ConfigSettings() { } public static string GetEndpointAddress() { return ConfigSettings.loadConfigDocument().SelectSingleNode(NodePath).Attributes["address"].Value; } public static void SaveEndpointAddress(string endpointAddress) { // load config document for current assembly XmlDocument doc = loadConfigDocument(); // retrieve appSettings node XmlNodeList nodes = doc.SelectNodes(NodePath); foreach (XmlNode node in nodes) { if (node == null) throw new InvalidOperationException("Error. Could not find endpoint node in config file."); //If this isnt the node I want to change, look at the next one //Change this string to the name attribute of the node you want to change if (node.Attributes["name"].Value != "DataLocal_Endpoint1") { continue; } try { // select the ''add'' element that contains the key //XmlElement elem = (XmlElement)node.SelectSingleNode(string.Format("//add[@key=''{0}'']", key)); node.Attributes["address"].Value = endpointAddress; doc.Save(getConfigFilePath()); break; } catch (Exception e) { throw e; } } } public static void SaveEndpointAddress(string endpointAddress, string ConfigPath, string endpointName) { // load config document for current assembly XmlDocument doc = loadConfigDocument(ConfigPath); // retrieve appSettings node XmlNodeList nodes = doc.SelectNodes(NodePath); foreach (XmlNode node in nodes) { if (node == null) throw new InvalidOperationException("Error. Could not find endpoint node in config file."); //If this isnt the node I want to change, look at the next one if (node.Attributes["name"].Value != endpointName) { continue; } try { // select the ''add'' element that contains the key //XmlElement elem = (XmlElement)node.SelectSingleNode(string.Format("//add[@key=''{0}'']", key)); node.Attributes["address"].Value = endpointAddress; doc.Save(ConfigPath); break; } catch (Exception e) { throw e; } } } public static XmlDocument loadConfigDocument() { XmlDocument doc = null; try { doc = new XmlDocument(); doc.Load(getConfigFilePath()); return doc; } catch (System.IO.FileNotFoundException e) { throw new Exception("No configuration file found.", e); } } public static XmlDocument loadConfigDocument(string Path) { XmlDocument doc = null; try { doc = new XmlDocument(); doc.Load(Path); return doc; } catch (System.IO.FileNotFoundException e) { throw new Exception("No configuration file found.", e); } } private static string getConfigFilePath() { return Assembly.GetExecutingAssembly().Location + ".config"; } }

}


Por lo que vale, necesitaba actualizar el puerto y el esquema de SSL para mi servicio RESTFul. Esto es lo que hice. Disculpa que es un poco más que la pregunta original, pero afortunadamente útil para alguien.

// Don''t forget to add references to System.ServiceModel and System.ServiceModel.Web using System.ServiceModel; using System.ServiceModel.Configuration; var port = 1234; var isSsl = true; var scheme = isSsl ? "https" : "http"; var currAssembly = System.Reflection.Assembly.GetExecutingAssembly().CodeBase; Configuration config = ConfigurationManager.OpenExeConfiguration(currAssembly); ServiceModelSectionGroup serviceModel = ServiceModelSectionGroup.GetSectionGroup(config); // Get the first endpoint in services. This is my RESTful service. var endp = serviceModel.Services.Services[0].Endpoints[0]; // Assign new values for endpoint UriBuilder b = new UriBuilder(endp.Address); b.Port = port; b.Scheme = scheme; endp.Address = b.Uri; // Adjust design time baseaddress endpoint var baseAddress = serviceModel.Services.Services[0].Host.BaseAddresses[0].BaseAddress; b = new UriBuilder(baseAddress); b.Port = port; b.Scheme = scheme; serviceModel.Services.Services[0].Host.BaseAddresses[0].BaseAddress = b.Uri.ToString(); // Setup the Transport security BindingsSection bindings = serviceModel.Bindings; WebHttpBindingCollectionElement x =(WebHttpBindingCollectionElement)bindings["webHttpBinding"]; WebHttpBindingElement y = (WebHttpBindingElement)x.ConfiguredBindings[0]; var e = y.Security; e.Mode = isSsl ? WebHttpSecurityMode.Transport : WebHttpSecurityMode.None; e.Transport.ClientCredentialType = HttpClientCredentialType.None; // Save changes config.Save();


Puedes hacerlo así:

  • Mantenga su configuración en un archivo xml separado y léala cuando cree un proxy para su servicio.

Por ejemplo, quiero modificar mi dirección de punto final de servicio en tiempo de ejecución, así que tengo el siguiente archivo ServiceEndpoint.xml .

<?xml version="1.0" encoding="utf-8" ?> <Services> <Service name="FileTransferService"> <Endpoints> <Endpoint name="ep1" address="http://localhost:8080/FileTransferService.svc" /> </Endpoints> </Service> </Services>

  • Para leer tu xml:

    var doc = new XmlDocument(); doc.Load(FileTransferConstants.Constants.SERVICE_ENDPOINTS_XMLPATH); XmlNodeList endPoints = doc.SelectNodes("/Services/Service/Endpoints"); foreach (XmlNode endPoint in endPoints) { foreach (XmlNode child in endPoint) { if (child.Attributes["name"].Value.Equals("ep1")) { var adressAttribute = child.Attributes["address"]; if (!ReferenceEquals(null, adressAttribute)) { address = adressAttribute.Value; } } } }

  • A continuación, obtenga su archivo web.config de su cliente en tiempo de ejecución y asigne la dirección del punto final del servicio como:

    Configuration wConfig = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap { ExeConfigFilename = @"C:/FileTransferWebsite/web.config" }, ConfigurationUserLevel.None); ServiceModelSectionGroup wServiceSection = ServiceModelSectionGroup.GetSectionGroup(wConfig); ClientSection wClientSection = wServiceSection.Client; wClientSection.Endpoints[0].Address = new Uri(address); wConfig.Save();


Uso el siguiente código para cambiar la dirección del punto final en el archivo App.Config. Es posible que desee modificar o eliminar el espacio de nombres antes de su uso.

using System; using System.Xml; using System.Configuration; using System.Reflection; //... namespace Glenlough.Generations.SupervisorII { public class ConfigSettings { private static string NodePath = "//system.serviceModel//client//endpoint"; private ConfigSettings() { } public static string GetEndpointAddress() { return ConfigSettings.loadConfigDocument().SelectSingleNode(NodePath).Attributes["address"].Value; } public static void SaveEndpointAddress(string endpointAddress) { // load config document for current assembly XmlDocument doc = loadConfigDocument(); // retrieve appSettings node XmlNode node = doc.SelectSingleNode(NodePath); if (node == null) throw new InvalidOperationException("Error. Could not find endpoint node in config file."); try { // select the ''add'' element that contains the key //XmlElement elem = (XmlElement)node.SelectSingleNode(string.Format("//add[@key=''{0}'']", key)); node.Attributes["address"].Value = endpointAddress; doc.Save(getConfigFilePath()); } catch( Exception e ) { throw e; } } public static XmlDocument loadConfigDocument() { XmlDocument doc = null; try { doc = new XmlDocument(); doc.Load(getConfigFilePath()); return doc; } catch (System.IO.FileNotFoundException e) { throw new Exception("No configuration file found.", e); } } private static string getConfigFilePath() { return Assembly.GetExecutingAssembly().Location + ".config"; } } }


este código corto funcionó para mí:

Configuration wConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); ServiceModelSectionGroup wServiceSection = ServiceModelSectionGroup.GetSectionGroup(wConfig); ClientSection wClientSection = wServiceSection.Client; wClientSection.Endpoints[0].Address = <your address>; wConfig.Save();

Por supuesto, debe crear el proxy ServiceClient DESPUÉS de que la configuración haya cambiado. También necesita hacer referencia a los ensamblados System.Configuration y System.ServiceModel para que esto funcione.

Aclamaciones



MyServiceClient client = new MyServiceClient(binding, endpoint); client.Endpoint.Address = new EndpointAddress("net.tcp://localhost/webSrvHost/service.svc"); client.Endpoint.Binding = new NetTcpBinding() { Name = "yourTcpBindConfig", ReaderQuotas = XmlDictionaryReaderQuotas.Max, ListenBacklog = 40 }

Es muy fácil modificar el uri en configuración o información de enlace en config. ¿Es esto lo que quieres?


SomeServiceClient client = new SomeServiceClient(); var endpointAddress = client.Endpoint.Address; //gets the default endpoint address EndpointAddressBuilder newEndpointAddress = new EndpointAddressBuilder(endpointAddress); newEndpointAddress.Uri = new Uri("net.tcp://serverName:8000/SomeServiceName/"); client = new SomeServiceClient("EndpointConfigurationName", newEndpointAddress.ToEndpointAddress());

Lo hice así. Lo bueno es que aún recoge el resto de las configuraciones de enlace de su punto final de la configuración y simplemente reemplaza el URI .