Compartir a través de


Procedimientos recomendados de desarrollo mediante el SDK del adaptador de LOB de WCF

Puede usar los procedimientos recomendados de este tema para mejorar las aplicaciones y los adaptadores.

Anular llamada antes de cerrarse en la excepción de canal

Al escribir una aplicación que usa el modelo de canal WCF, debe llamar IRequestChannel.Abort a antes de llamar a ChannelFactory.Close. Si no lo hace, ChannelFactory.Close produce una excepción.

En el ejemplo siguiente, las operaciones de canal se intentan dentro de un bloque try/catch. Si se produce una excepción, se anula el canal.

ChannelFactory<IRequestChannel> cf = new  ChannelFactory<IRequestChannel>();  
IRequestChannel channel = null;  
try  
{  
  cf.Open();  
  channel = cf.CreateChannel();  
  channel.Open();  
  channel.Request();// This causes the channel to go into a faulted state.  
  channel.Close();  
}  
catch (Exception e)  
{  
  // Abort the channel if we have one  
  if(channel != null)  
    channel.Abort();  
}  
finally  
{  
  if (cf.State == CommunicationState.Opened)  
  {  
    cf.Close(); // It throws an exception that the channel is in a faulted state.  
  }  
}  

Implementación de controladores asincrónicos y sincrónicos

Si es posible, implemente controladores asincrónicos y sincrónicos en el adaptador. Si el adaptador solo implementa llamadas sincrónicas, puede encontrarse con problemas de bloqueo al procesar un gran volumen de mensajes o cuando el adaptador se usa en un entorno multiproceso.

Usar agrupación de conexiones

El SDK del adaptador de LOB de WCF admite la agrupación de conexiones de forma predeterminada. Sin embargo, es necesario que el desarrollador del adaptador determine qué propiedades de agrupación de conexiones se exponen como propiedades de enlace. La configuración del grupo de conexiones disponible se define en Microsoft.ServiceModel.Channels.Common.ConnectionPoolSettings.

No hay ninguna opción en el complemento Consumir servicio adaptador para exponer fácilmente estas propiedades como propiedades de conexión del adaptador. El desarrollador del adaptador debe definir manualmente las propiedades de la implementación del adaptador.

public CustomAdapter(): base()  
{  
   this.Settings.ConnectionPool.EnablePooling = true;  
   this.Settings.ConnectionPool.HandlersShareSameConnection = true;  
   this.Settings.ConnectionPool.MaxConnectionsPerSystem = 50;  
   this.Settings.ConnectionPool.MaxAvailableConnections = 5;  
}  

Asegúrese de que el adaptador admite operaciones de Two-Way

Si se llama al adaptador desde BizTalk Server, debe admitir operaciones bidireccionales, incluso si el valor devuelto es void. Esto se debe a que BizTalk Server espera una respuesta devuelta de cualquier solicitud saliente y produce una excepción si el adaptador solo implementa operaciones unidireccionales.

Este es un ejemplo de un contrato de solicitud-respuesta que devuelve void.

[ServiceContract(Namespace=”Http:Microsoft.BizTalk.Samples.WCFAdapterSample”)]  
public interface ICalculator  
{  
   [OperationContract]  
   void Add(double n1, double n2);  
}  

Implementación del seguimiento

Durante el ciclo de desarrollo, es posible que no parezca importante agregar seguimiento al adaptador, ya que puede recorrer el código y depurar cualquier problema. Sin embargo, una vez instalado el adaptador en un entorno de producción, es posible que no pueda usar la depuración en tiempo de ejecución para aislar problemas. Si ha habilitado el seguimiento en todo el adaptador, se puede usar para aislar dónde se producen los errores.

Consulte Seguimiento de un adaptador con el SDK del adaptador de LOB de WCF para obtener más detalles.

Usar propiedades de URI para la configuración modificada con frecuencia

Al decidir si exponer una propiedad personalizada como una propiedad de enlace o URI, se recomienda usar una propiedad URI si el valor cambia con frecuencia. Las propiedades de enlace deben reservarse para valores que rara vez cambian.

Una propiedad de enlace de ejemplo sería un nombre de servidor de base de datos que usan todas las conexiones. Una propiedad de URI de ejemplo sería una tabla o procedimiento almacenado específico que usará esa conexión específica.

No pasar valores de nombre de usuario o contraseña en el URI

Si el adaptador requiere las credenciales del autor de la llamada, se recomienda usar la clase ClientCredentials para recuperar los valores de credenciales en lugar de pasar las credenciales de cliente como parte del URI. La clase ClientCredentials es una característica estándar de WCF que está pensada para pasar información de credenciales del cliente al servicio de forma más segura. Pasar la información del usuario como parte de la cadena de URI puede exponer la información del usuario durante el tránsito.

Los métodos recomendados para pasar credenciales se muestran en la tabla siguiente.

Método Descripción
Tiempo de diseño Al usar el complemento Agregar referencia de servicio de adaptador, puede especificar los tipos de credenciales de cliente que admite el adaptador.
Tiempo de ejecución Al usar un proxy CLR de .NET generado, puede establecer mediante programación las credenciales de cliente.

static void Main(string[] args) { EchoServiceClient client = new EchoServiceClient(); client.ClientCredentials.UserName.UserName = "TestUser"; client.ClientCredentials.UserName.Password = "TestPassword"; string response=client.EchoString("Test String"); }

Como alternativa, si necesita interactuar directamente con el canal, puede usar el modelo de canal WCF para especificar las credenciales de cliente al crear un generador de canales.

EchoAdapterBinding binding = new EchoAdapterBinding(); binding.Count = 3; ClientCredentials clientCredentials = new ClientCredentials(); clientCredentials.UserName.UserName = "TestUser"; clientCredentials.UserName.Password = "TestPassword"; BindingParameterCollection bindingParms = new BindingParameterCollection(); bindingParms.Add(clientCredentials); EndpointAddress address = new EndpointAddress("echo://"); IChannelFactory<IRequestChannel> requestChannelFactory = binding.BuildChannelFactory<IRequestChannel>(bindingParms); requestChannelFactory.Open();
Configuración de WCF En el archivo de configuración de cliente, agregue un <elemento endpointBehaviors> que incluya <clientCredentials>.

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <system.serviceModel> . . . . . <behaviors> <endpointBehaviors> <behavior name="clientEndpointCredential"> <clientCredentials> <windows allowNtlm="false" allowedImpersonationLevel="Delegation" /> </clientCredentials> </behavior> </endpointBehaviors> </behaviors> </system.serviceModel> </configuration>
Uso de BizTalk Al usar el adaptador WCF para consumir el adaptador, puede agregar la extensión de comportamiento clientCredentials en la pestaña Comportamiento . Una vez que se haya agregado, puede establecer las credenciales de cliente deseadas en el comportamiento del punto de conexión.

No devolver StrongDataSetType y WeakDataSetType

Si el adaptador devuelve , DataSetuse Microsoft.ServiceModel.Channels.Common.QualifiedType.StrongDataSetType%2A o Microsoft.ServiceModel.Channels.Common.QualifiedType.WeakDataSetType%2A, pero no use ambos al mismo tiempo. El nombre y el espacio de nombres del nodo raíz generados por ambos tipos son idénticos y no pueden existir simultáneamente en un WSDL.

Aunque WeakDataSetType y StrongDataSetType ambos representan , System.Data.DataSetStrongDataSetType es más fácil de usar en aplicaciones .NET, ya que el proxy generado aparece como System.Data.Dataset. El proxy generado por WeakDataSetType es XmlElement[], que es más difícil de usar en una aplicación .NET. BizTalk Server no puede consumir el esquema devuelto de StrongDataSet, pero es capaz de consumir WeakDataSetType.

Nota

StrongDataSetType y WeakDataSetType solo controlan cómo interpreta la aplicación cliente los mensajes XML pasados por el adaptador. El mensaje XML es el mismo independientemente del tipo especificado.

Nota

Al devolver StrongDataSetType, debe establecer en Microsoft.ServiceModel.Channels.Common.MetadataSettings.CompileWsdl%2Afalse. Cuando se establece trueen , se llama al valor predeterminado XmlSchemaSet::Compile dentro del adaptador para asegurarse de que no hay errores en el WSDL, pero el esquema generado por StrongDataSetType genera una excepción en XmlSchemaSet.

Al establecer CompileWsdl para false omitir la validación del esquema WSDL dentro del adaptador y la validación se produce durante la generación de proxy. Las utilidades como svcutil.exe pueden generar un proxy para StrongDataSetType y WeakDataSetType.

Para trabajar con entornos de BizTalk y .NET, considere la posibilidad de implementar una propiedad de enlace que permita cambiar entre los dos tipos devueltos según lo dicta el entorno.

internal static QualifiedType GetDataSetQualifiedType(MyAdapterBindingProperties bindingProperties)  
{  
   if (bindingProperties.EnableBizTalkCompatibility)  
      return QualifiedType.WeakDataSetType;  
   else  
      return QualifiedType.StrongDataSetType;  
}  

Crear nombres de esquema XSD significativos en BizTalk Server

Cuando se usa la herramienta de tiempo de diseño del complemento de complemento de bizTalk de servicio de adaptador de consumo, el nombre del esquema XSD generado en el proyecto de BizTalk se crea con la DefaultXsdFileNamePrefix propiedad , la fileNameHint anotación en el WSDL y, si es necesario, un valor entero único.

Por ejemplo, si DefaultXsdFileNamePrefix se establece en "MyAdapter" y la fileNameHint anotación se establece en "Stream", el esquema XSD creado se denomina MyAdapterStream.xsd.

<xs:schema elementFormDefault='qualified' targetNamespace='http://schemas.microsoft.com/Message' xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:tns='http://schemas.microsoft.com/Message'>  
<xs:annotation>  
<xs:appinfo>  
<fileNameHint xmlns='http://schemas.microsoft.com/servicemodel/adapters/metadata/xsd'>Stream</fileNameHint>  
</xs:appinfo>  
</xs:annotation>  
<xs:simpleType name='StreamBody'>  
<xs:restriction base='xs:base64Binary' />  
</xs:simpleType>  
</xs:schema>  

Nota

El valor predeterminado de DefaultXsdFileNamePrefix es el nombre del enlace. Para especificar un valor diferente, invalide DefaultXsdFileNamePrefix en la clase Adapter que se deriva de Microsoft.ServiceModel.Channels.Common.AdapterBinding.

Hay dos métodos posibles para agregar la fileNameHint anotación al esquema: invalidar export... Los métodos de esquema en OperationMetadata\TypeMetadata o invalidan la implementación IWsdlRetrieval del adaptador. Para cualquiera de los métodos, puede llamar a la implementación base y, a continuación, agregar la anotación a los esquemas de la colección de esquemas.

Nota

Al invalidar la exportación... Métodos de esquema, puede haber varias definiciones de operación y tipo en el mismo esquema; El adaptador debe asegurarse de que varias apariciones de la fileNameHints anotación en el mismo esquema no entren en conflicto. El Complemento de servicio consumir adaptador usa la primera aparición de si se produce varias veces dentro de fileNameHint un esquema.

En el ejemplo siguiente, se usa IWsdlRetrieval para agregar la fileNameHint anotación al WSDL.

sealed class MyAdapterWsdlRetrieval : IWsdlRetrieval  
{  
   IWsdlRetrieval mBaseWsdlRetrieval;  
   public MyAdapterWsdlRetrieval(IWsdlRetrieval baseWsdlRetrieval)  
   {  
      mBaseWsdlRetrieval = baseWsdlRetrieval;  
   }  

   ServiceDescription IWsdlRetrieval.GetWsdl(Microsoft.ServiceModel.Channels.MetadataRetrievalNode[] nodes, Uri uri, TimeSpan timeout)  
   {  
      ServiceDescription baseDesc = mBaseWsdlRetrieval.GetWsdl(nodes, uri, timeout);  
      foreach (XmlSchema schema in baseDesc.Types.Schemas)  
      {  
         CreateFileNameHint(schema);  
      }  
      return baseDesc;  
   }  

   void CreateFileNameHint(XmlSchema schema)  
   {  
      string targetNamespace = schema.TargetNamespace;  
      if (string.IsNullOrEmpty(targetNamespace))  
         return;  
      string fileNameHint = null;  
      //determine the filename based on namespace  
      if (targetNamespace.StartsWith("myadapter:// adapters.samples.myadaptpter/HelloWorld"))  
      {  
         fileNameHint = "HelloWorld";  
      }  
      if (targetNamespace.StartsWith("myadapter:// adapters.samples.myadapter/Hello"))  
      {  
         fileNameHint = "Hello";  
      }  
      //create the annotation and populate it with fileNameHint  
      XmlSchemaAnnotation annotation = new XmlSchemaAnnotation();  
      XmlSchemaAppInfo appInfo = new XmlSchemaAppInfo();  
      XmlDocument doc = new XmlDocument();  
      XmlNode[] fileNameHintNodes = new XmlNode[1];  
      fileNameHintNodes[0] = doc.CreateElement(null, "fileNameHint", "http://schemas.microsoft.com/servicemodel/adapters/metadata/xsd");  
      fileNameHintNodes[0].AppendChild(doc.CreateTextNode(fileNameHint));  
      appInfo.Markup = fileNameHintNodes;  
      annotation.Items.Add(appInfo);  
      schema.Items.Insert(0, annotation);  
   }  

No modificar adapterEnvironmentSettings durante el procesamiento

El adaptador solo debe establecer AdapterEnvironmentSettings, ConnectionPoolManager, ConnectionPool y CommonCacheSize durante la inicialización del adaptador y no debe intentar modificar los valores de una instancia en ejecución.

Si estas opciones se modifican en una instancia de adaptador que se está ejecutando actualmente, esto puede dar lugar a que las nuevas conexiones sobrescriban las opciones de configuración para ejecutar conexiones actualmente.

Consulte también

Procedimientos recomendados de desarrollo mediante el SDK del adaptador de LOB de WCF