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 "在西班牙语中是业务逻辑合同的意思。
问题解决。使用wcfsvchost.exe,我发现了重复的元素、数据合同和数据成员。重命名后,代理工作。