【问题标题】:WCF "An element with the same key has already been added" while creating channel from ClientBase从 ClientBase 创建通道时 WCF“已添加具有相同键的元素”
【发布时间】:2016-08-30 16:19:22
【问题描述】:

我使用的是用西班牙语编写的陈旧而蹩脚的解决方案。我们正在使用 System.ServiceModel.ClientBase 通过代理替换服务引用。我们有 24 个代理用于 24 项服务,其中一个代理会发生此 ArgumentException。属性“ParamName”是空的,所以你可以想象找到这个问题的源头有多难。经过大量的网络研究,我认为发生异常是因为以下两个原因之一:

  • 我在服务器的 Web.config 中的 system.serviceModel 标记中有重复的元素
  • 我在已知类型中包含的两个或多个实体中的 DataContract 属性中有重复的命名空间。

否则,我不太确定,我知道第一个原因是没有发生。这是ClientBase的子类GenericProxy的代码:

public class GenericProxy<T> : ClientBase<T> 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<T> action)
    {
        InvocarOperacion(action, false); //invocacion no asincrona
    }

    public void InvocarOperacionAsincrona(Action<T> action)
    {
        InvocarOperacion(action, true); //invocacion asincrona
    }

    private void InvocarOperacion(Action<T> 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<ErrorServicio> 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 && ex.Detail.Data != null && 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();
    }
}

CreateChannel方法出现异常,执行_channel = base.CreateChannel();。最后,这是服务接口:

    [ServiceContract]
//[ServiceKnownType("GetKnownTypes", typeof(KnownTypesProvider))]
public interface IContratoService
{
    [OperationContract]
    ColeccionNegocioBase<ContratoEntidad> 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<string> liCampos);

    [OperationContract]
    ColeccionNegocioBase<ContratoEntidad> CancelacionContratos(ColeccionNegocioBase<OrdenEntidad> coleccion);

    [OperationContract]
    ColeccionNegocioBase<ContratoEntidad> CancelacionCondicionalContratos(ColeccionNegocioBase<OrdenEntidad> coleccion);

    [OperationContract]
    ColeccionNegocioBase<ContratoEntidad> CancelacionContratosTv(ColeccionNegocioBase<OrdenTVPresentacionEntidad> coleccion);

    [OperationContract]
    ColeccionNegocioBase<ContratoEntidad> CancelacionCondicionalContratosTv(ColeccionNegocioBase<OrdenTVPresentacionEntidad> coleccion);

    [OperationContract]
    ColeccionNegocioBase<ContratoEntidad> EmisionContratos(ColeccionNegocioBase<OrdenEntidad> coleccion);

    [OperationContract]
    ColeccionNegocioBase<ContratoEntidad> EmisionContratosTv(ColeccionNegocioBase<OrdenTVPresentacionEntidad> coleccion, PlanificacionTVEntidad mPlanificacion);

    [OperationContract]
    ColeccionNegocioBase<ContratoEntidad> EmisionContratosTvSinPlanificacion(ColeccionNegocioBase<OrdenTVPresentacionEntidad> coleccion);

    [OperationContract]
    ColeccionNegocioBase<ContratoEntidad> ReemisionContratos(ColeccionNegocioBase<OrdenEntidad> coleccion);

    [OperationContract]
    int NumeroOrdenesContrato(int codigoContrato);

    [OperationContract]
    ColeccionNegocioBase<ContratoEntidad> ObtenerContratosDisponibles(ContratoFiltro filtroContrato);

    [OperationContract]
    void ActualizarObservacionesContrato(ColeccionNegocioBase<ContratoEntidad> coleccion, string pObservaciones);}

这是端点:

  <endpoint address="http://localhost:8731/MMS/ContratoServicio.svc"
        binding="wsHttpBinding"
        bindingConfiguration="WindowsBinding_Service"
        behaviorConfiguration="ComunBehavior"
        contract="HM.MMS.Contrato.Interfaces.IServicios.IContratoService"
        name="ContratoService" />

这是服务:

<service behaviorConfiguration="ComunBehavior" name="HM.MMS.Implementacion.Servicio.ContratoService">
  <endpoint address="/mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  <endpoint address="" binding="wsHttpBinding" bindingConfiguration="WindowsBinding_Service" contract="HM.MMS.Contrato.Interfaces.IServicios.IContratoService">
    <identity>
      <dns value="localhost" />
    </identity>
  </endpoint>
</service>

这是我正在测试的代理方法:

    public static SingleListEntity<int> EmitirOrdenesEx(List<int> ordenes, Usuario usuario)
    {
        SingleListEntity<int> result = null;
        using (var servicio = new GenericProxy<IContratoService>(NombreServicio.CONTRATO_SERVICE))
        {
            servicio.InvocarOperacion(delegate(IContratoService serv)
            {
                result = serv.EmitirOrdenesEx(ordenes, usuario);
            });
        }
        return result;
    }

NombreContrato.CONTRATO_SERVICE 是“ContratoService”

抱歉,“Contrato”这个名称混淆了,它在西班牙语中的意思是商业逻辑合同。这并不意味着 WCF 合同。

【问题讨论】:

    标签: c# .net wcf


    【解决方案1】:

    问题已解决。使用 wcfsvchost.exe 我发现重复的 elementens、Datacontracts 和 Datamembers。重命名后,代理正在工作。

    【讨论】:

      猜你喜欢
      • 2017-03-24
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 2021-05-14
      • 2017-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多