WCF "已经添加了具有相同键的元素"同时从ClientBase创建通道

本文关键字:quot 元素 创建 通道 ClientBase 添加 WCF | 更新日期: 2023-09-27 18:04:00

我使用的是用西班牙语编写的旧而蹩脚的解决方案。我们使用System.ServiceModel.ClientBase替换代理的服务引用。我们为24个服务设置了24个代理,其中一个服务出现了ArgumentException。属性"ParamName"为空,因此您可以想象找到这个问题的根源是多么困难。在进行了大量的网络研究之后,我认为出现这种例外的原因有以下两个:

    我有重复的元素在系统内。serviceModel标签,在服务器的Web.config
  • 我在datcontract属性中有重复的名称空间,在已知类型中包含的两个或多个实体中。

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

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"

很抱歉名字混淆了" contrto "在西班牙语中是业务逻辑合同的意思。

WCF "已经添加了具有相同键的元素"同时从ClientBase创建通道

问题解决。使用wcfsvchost.exe,我发现了重复的元素、数据合同和数据成员。重命名后,代理工作。