title: WCF "An element with the same key has already been added" while creating channel from ClientBase
body: <p>I work with an old and crapy solution written in spanish. We are replacing service references by agents using System.ServiceModel.ClientBase. We have 24 agents for 24 services and with one of them this ArgumentException occurs. The property "ParamName" is null so you can imagine how hard is locate de source of this problem. After a lot of web research, I think the exception is happening because one of two of this reasons:</p>
  
  <ul>
  <li>I have duplicate elements inside system.serviceModel tag, in server's Web.config</li>
  <li>I have duplicate namespaces in DataContract atrribute, in two or more of the entities included in the knowntypes.</li>
  </ul>
  
  <p>Otherwise, I am not really sure of that and I know the first reason is not happeing. This is the code of GenericProxy, a child class of ClientBase:</p>
  
  <pre><code>public class GenericProxy&lt;T&gt; : ClientBase&lt;T&gt; where T : class
  {
      T _channel;
  
      public GenericProxy(string endpoint)
          : base(endpoint)
      {
      }
  
      public static ICredencialUsuario Credencial
      {
          set { Configurador.Instancia.Credencial = value; }
      }
  
      protected override T CreateChannel()
      {
          try
          {
              if (Configurador.Instancia.Credencial == null)
              {
                  if (ChannelFactory.Credentials != null) ChannelFactory.Credentials.UserName.UserName = "dummy";
              }
              else
              {
                  if (ChannelFactory.Credentials != null)
                  {
                      ChannelFactory.Credentials.UserName.UserName = Configurador.Instancia.Credencial.Usuario;
                      ChannelFactory.Credentials.UserName.Password = Configurador.Instancia.Credencial.Clave;
                  }
              }
  
              _channel = base.CreateChannel();
  
              return _channel;
          }
          catch (Exception ex)
          {
              throw new Exception("Error al crear el canal de comunicaciones del GenericProxy.", ex);
          }
      }
  
      public T Proxy
      {
          get { return Channel; }
      }
  
      public void InvocarOperacion(Action&lt;T&gt; action)
      {
          InvocarOperacion(action, false); //invocacion no asincrona
      }
  
      public void InvocarOperacionAsincrona(Action&lt;T&gt; action)
      {
          InvocarOperacion(action, true); //invocacion asincrona
      }
  
      private void InvocarOperacion(Action&lt;T&gt; action, bool asincrono)
      {
  
          T client = CreateChannel();
  
          try
          {
              DateTime comienzo = DateTime.Now;
              action(client);
  
              ClientCredentials clientCredentials = ChannelFactory.Credentials;
              if (clientCredentials != null)
                  Log.logDebug("GenericProxy", String.Format("Usuario {2} y Metodo {3} : Comienzo {0} Fin {1}", comienzo.ToString("HH:mm:ss-ffff"), DateTime.Now.ToString("HH:mm:ss-ffff"),
                      clientCredentials.UserName.UserName,
                      action.Method.Name));
  
              //si la petición no es asincrona se cierra el canal
              if (!asincrono)
              {
                  ((IClientChannel)client).Close();
              }
          }
          catch (MessageSecurityException mex)
          {
              ((IClientChannel)client).Abort();
              //si no hay un usuario valido, ha habido un fallo durante el proceso de validación, por lo que no se puede continuar
              if ((Configurador.Instancia.Credencial == null) || (Configurador.Instancia.Credencial.Usuario == null) || (Configurador.Instancia.Credencial.Usuario.Length == 0))
              {
                  OnOperacionError(mex);
              }
              else //ya existia un usuario valido, con lo que la sesion ha caducado
              {
                  OnSesionCaducada();
              }
          }
          catch (FaultException&lt;ErrorServicio&gt; ex)
          {
              ((IClientChannel)client).Abort();
              if (ex.Detail.TipoExcepcion.Equals(typeof(ValidationException).FullName))
              {
                  ValidationException error = new ValidationException(ex.Detail.Mensaje) {CodigoError = ex.Detail.Id};
                  throw error;
              }
              if (ex.Detail.TipoExcepcion.Equals(typeof(SecurityException).FullName))
              {
                  SecurityException error = new SecurityException {CodigoError = ex.Detail.Id};
                  throw error;
              }
              if (ex.Detail.TipoExcepcion.Equals(typeof(ServiceException).FullName))
              {
                  ServiceException error = new ServiceException(ex.Detail.Mensaje);
                  // Comprobamos si hay aviso de triger en base de datos para mostrar su mensaje
                  if (ex.Detail != null &amp;&amp; ex.Detail.Data != null &amp;&amp; ex.Detail.Data.Contains("Triger"))
                      DevExpress.XtraEditors.XtraMessageBox.Show(ex.Detail.Data["Triger"].ToString());
                  OnOperacionError(error);
              }
              if (ex.Detail.TipoExcepcion.Equals(typeof(MessageSecurityException).FullName))
              {
                  OnSesionCaducada();
              }
  
          }
          catch (CommunicationException e)
          {
              ((IClientChannel)client).Abort();
              OnOperacionError(e);
          }
          catch (Exception e)
          {
              ((IClientChannel)client).Abort();
              OnOperacionError(e);
          }
  
      }
  
      public void CloseChannel()
      {
          ICommunicationObject canal = _channel as ICommunicationObject;
          if (canal != null)
              canal.Close();
      }
  
      private void OnOperacionError(Exception ex)
      {
          Configurador.Instancia.OnOperacionError(ex);
      }
  
      private void OnSesionCaducada()
      {
          Configurador.Instancia.OnSesionCaducada();
      }
  }
  </code></pre>
  
  <p>The exception ocurrs at CreateChannel method, executing _channel = base.CreateChannel();. Finally, this is the service interface:</p>
  
  <pre><code>    [ServiceContract]
  //[ServiceKnownType("GetKnownTypes", typeof(KnownTypesProvider))]
  public interface IContratoService
  {
      [OperationContract]
      ColeccionNegocioBase&lt;ContratoEntidad&gt; ObtenerContratos(ContratoFiltro filtroContrato, OrdenFiltro filtroOrden, bool completo);
  
      [OperationContract]
      ContratoEntidad EmitirContrato(ContratoEntidad contrato, bool esContratoTv);
  
      [OperationContract]
      ContratoEntidad ReEmitirContrato(ContratoEntidad contrato);
  
      [OperationContract]
      ContratoEntidad ModificarContrato(ContratoEntidad contrato, List&lt;string&gt; liCampos);
  
      [OperationContract]
      ColeccionNegocioBase&lt;ContratoEntidad&gt; CancelacionContratos(ColeccionNegocioBase&lt;OrdenEntidad&gt; coleccion);
  
      [OperationContract]
      ColeccionNegocioBase&lt;ContratoEntidad&gt; CancelacionCondicionalContratos(ColeccionNegocioBase&lt;OrdenEntidad&gt; coleccion);
  
      [OperationContract]
      ColeccionNegocioBase&lt;ContratoEntidad&gt; CancelacionContratosTv(ColeccionNegocioBase&lt;OrdenTVPresentacionEntidad&gt; coleccion);
  
      [OperationContract]
      ColeccionNegocioBase&lt;ContratoEntidad&gt; CancelacionCondicionalContratosTv(ColeccionNegocioBase&lt;OrdenTVPresentacionEntidad&gt; coleccion);
  
      [OperationContract]
      ColeccionNegocioBase&lt;ContratoEntidad&gt; EmisionContratos(ColeccionNegocioBase&lt;OrdenEntidad&gt; coleccion);
  
      [OperationContract]
      ColeccionNegocioBase&lt;ContratoEntidad&gt; EmisionContratosTv(ColeccionNegocioBase&lt;OrdenTVPresentacionEntidad&gt; coleccion, PlanificacionTVEntidad mPlanificacion);
  
      [OperationContract]
      ColeccionNegocioBase&lt;ContratoEntidad&gt; EmisionContratosTvSinPlanificacion(ColeccionNegocioBase&lt;OrdenTVPresentacionEntidad&gt; coleccion);
  
      [OperationContract]
      ColeccionNegocioBase&lt;ContratoEntidad&gt; ReemisionContratos(ColeccionNegocioBase&lt;OrdenEntidad&gt; coleccion);
  
      [OperationContract]
      int NumeroOrdenesContrato(int codigoContrato);
  
      [OperationContract]
      ColeccionNegocioBase&lt;ContratoEntidad&gt; ObtenerContratosDisponibles(ContratoFiltro filtroContrato);
  
      [OperationContract]
      void ActualizarObservacionesContrato(ColeccionNegocioBase&lt;ContratoEntidad&gt; coleccion, string pObservaciones);}
  </code></pre>
  
  <p>This is the endpoint:</p>
  
  <pre><code>  &lt;endpoint address="http://localhost:8731/MMS/ContratoServicio.svc"
          binding="wsHttpBinding"
          bindingConfiguration="WindowsBinding_Service"
          behaviorConfiguration="ComunBehavior"
          contract="HM.MMS.Contrato.Interfaces.IServicios.IContratoService"
          name="ContratoService" /&gt;
  </code></pre>
  
  <p>This is the service:</p>
  
  <pre><code>&lt;service behaviorConfiguration="ComunBehavior" name="HM.MMS.Implementacion.Servicio.ContratoService"&gt;
    &lt;endpoint address="/mex" binding="mexHttpBinding" contract="IMetadataExchange" /&gt;
    &lt;endpoint address="" binding="wsHttpBinding" bindingConfiguration="WindowsBinding_Service" contract="HM.MMS.Contrato.Interfaces.IServicios.IContratoService"&gt;
      &lt;identity&gt;
        &lt;dns value="localhost" /&gt;
      &lt;/identity&gt;
    &lt;/endpoint&gt;
  &lt;/service&gt;
  </code></pre>
  
  <p>And this is the agent method i am testing:</p>
  
  <pre><code>    public static SingleListEntity&lt;int&gt; EmitirOrdenesEx(List&lt;int&gt; ordenes, Usuario usuario)
      {
          SingleListEntity&lt;int&gt; result = null;
          using (var servicio = new GenericProxy&lt;IContratoService&gt;(NombreServicio.CONTRATO_SERVICE))
          {
              servicio.InvocarOperacion(delegate(IContratoService serv)
              {
                  result = serv.EmitirOrdenesEx(ordenes, usuario);
              });
          }
          return result;
      }
  </code></pre>
  
  <p>NombreContrato.CONTRATO_SERVICE is "ContratoService"</p>
  
  <p>Sorry for the name confusion "Contrato" it means a bussines logic contract in spanish. It does not means a WCF contract.</p>