【发布时间】: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 合同。
【问题讨论】: