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 , DataSet
use 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.DataSet
StrongDataSetType
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%2A
false
. Cuando se establece true
en , 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