Meilleures pratiques de développement à l’aide du Kit de développement logiciel (SDK) de l’adaptateur LOB WCF
Vous pouvez utiliser les meilleures pratiques de cette rubrique pour améliorer vos applications et adaptateurs.
Abandon de l’appel avant la fermeture sur l’exception de canal
Lorsque vous écrivez une application qui utilise le modèle de canal WCF, vous devez appeler IRequestChannel.Abort
avant d’appeler ChannelFactory.Close
. Si ce n’est pas le cas, ChannelFactory.Close
lève une exception.
Dans l’exemple suivant, les opérations de canal sont tentées dans un bloc try/catch. Si une exception se produit, le canal est abandonné.
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.
}
}
Implémenter des gestionnaires asynchrones et synchrones
Si possible, implémentez des gestionnaires asynchrones et synchrones dans votre adaptateur. Si votre adaptateur implémente uniquement des appels synchrones, vous pouvez rencontrer des problèmes de blocage lors du traitement d’un grand volume de messages ou lorsque l’adaptateur est utilisé dans un environnement multithread.
Utiliser le regroupement de connexions
Le Kit de développement logiciel (SDK) de l’adaptateur LOB WCF prend en charge le regroupement de connexions par défaut. Toutefois, il incombe au développeur de l’adaptateur de déterminer les propriétés de regroupement de connexions à exposer en tant que propriétés de liaison. Les paramètres de pool de connexions disponibles sont définis dans Microsoft.ServiceModel.Channels.Common.ConnectionPoolSettings
.
Il n’existe aucune option dans le complément Consommer le service d’adaptateur pour exposer facilement ces propriétés en tant que propriétés de connexion d’adaptateur. Le développeur de l’adaptateur doit définir manuellement les propriétés dans l’implémentation de l’adaptateur.
public CustomAdapter(): base()
{
this.Settings.ConnectionPool.EnablePooling = true;
this.Settings.ConnectionPool.HandlersShareSameConnection = true;
this.Settings.ConnectionPool.MaxConnectionsPerSystem = 50;
this.Settings.ConnectionPool.MaxAvailableConnections = 5;
}
Vérifier que l’adaptateur prend en charge les opérations de Two-Way
Si votre adaptateur est appelé à partir de BizTalk Server, il doit prendre en charge les opérations bidirectionnelles, même si la valeur de retour est void. Cela est dû au fait que BizTalk Server attend une réponse retournée à partir d’une demande sortante et lève une exception si votre adaptateur implémente uniquement des opérations unidirectionnelles.
Voici un exemple de contrat demande-réponse qui retourne void.
[ServiceContract(Namespace=”Http:Microsoft.BizTalk.Samples.WCFAdapterSample”)]
public interface ICalculator
{
[OperationContract]
void Add(double n1, double n2);
}
Implémenter le suivi
Pendant le cycle de développement, il peut ne pas sembler important d’ajouter un suivi à votre adaptateur, car vous pouvez parcourir le code et déboguer les problèmes éventuels. Toutefois, une fois l’adaptateur installé dans un environnement de production, vous ne pourrez peut-être pas utiliser le débogage au moment de l’exécution pour isoler les problèmes. Si vous avez activé le suivi dans l’ensemble de votre adaptateur, il peut être utilisé pour isoler l’endroit où les défaillances se produisent.
Pour plus d’informations, consultez Suivre un adaptateur avec le KIT DE développement logiciel (SDK) de l’adaptateur LOB WCF .
Utiliser des propriétés d’URI pour les paramètres fréquemment modifiés
Lorsque vous décidez d’exposer une propriété personnalisée en tant que liaison ou propriété d’URI, il est recommandé d’utiliser une propriété URI si la valeur change souvent. Les propriétés de liaison doivent être réservées aux valeurs qui changent rarement.
Un exemple de propriété de liaison serait un nom de serveur de base de données utilisé par toutes les connexions. Un exemple de propriété d’URI serait une table ou une procédure stockée spécifique à utiliser par cette connexion spécifique.
Ne pas transmettre les valeurs de nom d’utilisateur ou de mot de passe dans l’URI
Si votre adaptateur nécessite les informations d’identification de l’appelant, il est recommandé d’utiliser la classe ClientCredentials pour récupérer les valeurs d’informations d’identification au lieu de transmettre des informations d’identification client dans le cadre de l’URI. La classe ClientCredentials est une fonctionnalité standard de WCF destinée à transmettre des informations d’identification du client au service de manière plus sécurisée. La transmission des informations utilisateur dans le cadre de la chaîne d’URI peut exposer les informations utilisateur en transit.
Les méthodes recommandées pour passer des informations d’identification sont indiquées dans le tableau suivant.
Méthode | Description |
---|---|
Au moment du design | Lorsque vous utilisez le plug-in Add Adapter Service Reference, vous pouvez spécifier les types d’informations d’identification client pris en charge par l’adaptateur. |
En cours d’exécution | Lorsque vous utilisez un proxy CLR .NET généré, vous pouvez définir par programmation les informations d’identification du client.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"); } Si vous devez interagir directement avec le canal, vous pouvez également utiliser le modèle de canal WCF pour spécifier les informations d’identification du client lors de la création d’une fabrique de canaux. 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(); |
Configuration WCF | Dans le fichier de configuration du client, ajoutez un <élément endpointBehaviors> qui inclut <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> |
Utilisation de BizTalk | Lorsque vous utilisez l’adaptateur WCF pour consommer votre adaptateur, vous pouvez ajouter l’extension de comportement clientCredentials sous l’onglet Comportement . Une fois ce paramètre ajouté, vous pouvez définir les informations d’identification client souhaitées dans le comportement du point de terminaison. |
Ne pas retourner à la fois StrongDataSetType et WeakDataSetType
Si votre adaptateur retourne un DataSet
, utilisez Microsoft.ServiceModel.Channels.Common.QualifiedType.StrongDataSetType%2A
ou Microsoft.ServiceModel.Channels.Common.QualifiedType.WeakDataSetType%2A
, mais n’utilisez pas les deux en même temps. Le nom du nœud racine et l’espace de noms produits par les deux types sont identiques et ne peuvent pas exister simultanément dans un WSDL.
Alors que WeakDataSetType
et StrongDataSetType
représentent tous les deux un System.Data.DataSet
, StrongDataSetType
est plus facile à utiliser dans les applications .NET, car le proxy généré apparaît sous la forme System.Data.Dataset
. Le proxy généré par WeakDataSetType
est XmlElement[]
, ce qui est plus difficile à utiliser dans une application .NET. BizTalk Server ne peut pas utiliser le schéma retourné par StrongDataSet
, mais peut consommer WeakDataSetType
.
Notes
StrongDataSetType
et WeakDataSetType
contrôlent uniquement la façon dont l’application cliente interprète les messages XML transmis par l’adaptateur. Le message XML est le même quel que soit le type spécifié.
Notes
Lorsque vous retournez StrongDataSetType
, vous devez définir sur Microsoft.ServiceModel.Channels.Common.MetadataSettings.CompileWsdl%2A
false
. Quand la valeur est définie true
sur , la valeur par défaut XmlSchemaSet::Compile
est appelée dans l’adaptateur pour s’assurer qu’il n’y a pas d’erreurs dans WSDL, mais le schéma produit par StrongDataSetType
génère une exception dans XmlSchemaSet
.
La définition CompileWsdl
de sur false
contourne la validation du schéma WSDL dans l’adaptateur et la validation se produit pendant la génération du proxy. Les utilitaires tels que svcutil.exe sont en mesure de générer un proxy pour StrongDataSetType
et WeakDataSetType
.
Pour travailler avec les environnements BizTalk et .NET, envisagez d’implémenter une propriété de liaison qui permet de basculer entre les deux types de retour comme dicté par l’environnement.
internal static QualifiedType GetDataSetQualifiedType(MyAdapterBindingProperties bindingProperties)
{
if (bindingProperties.EnableBizTalkCompatibility)
return QualifiedType.WeakDataSetType;
else
return QualifiedType.StrongDataSetType;
}
Créer des noms de schéma XSD significatifs dans BizTalk Server
Lors de l’utilisation de l’outil de conception du complément de projet BizTalk service Consume Adapter Service, le nom du schéma XSD généré dans votre projet BizTalk est créé à l’aide de la DefaultXsdFileNamePrefix
propriété , de l’annotation fileNameHint
dans le WSDL et, si nécessaire, d’une valeur entière unique.
Par exemple, si DefaultXsdFileNamePrefix
est défini sur « MyAdapter » et que l’annotation fileNameHint
est définie sur « Stream », le schéma XSD créé est nommé 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>
Notes
La valeur par défaut de DefaultXsdFileNamePrefix
est le nom de votre liaison. Pour spécifier une valeur différente, remplacez DefaultXsdFileNamePrefix
dans votre classe Adapter dérivée de Microsoft.ServiceModel.Channels.Common.AdapterBinding
.
Il existe deux méthodes possibles pour ajouter l’annotation fileNameHint
au schéma : remplacer l’exportation... Les méthodes de schéma sur OperationMetadata\TypeMetadata ou remplacent l’implémentation IWsdlRetrieval de l’adaptateur. Pour l’une ou l’autre méthode, vous pouvez appeler l’implémentation de base, puis ajouter l’annotation aux schémas de la collection de schémas.
Notes
Lors du remplacement de l’exportation... Méthodes de schéma, il peut y avoir plusieurs définitions d’opération/type dans le même schéma ; l’adaptateur doit s’assurer que plusieurs occurrences de l’annotation fileNameHints
dans le même schéma ne sont pas en conflit. Le complément Consume Adapter Service utilise la première occurrence de fileNameHint
si elle se produit plusieurs fois dans un schéma.
Dans l’exemple suivant, IWsdlRetrieval est utilisé pour ajouter l’annotation fileNameHint
au 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);
}
Ne pas modifier AdapterEnvironmentSettings pendant le traitement
L’adaptateur doit uniquement définir AdapterEnvironmentSettings, ConnectionPoolManager, ConnectionPool et CommonCacheSize pendant l’initialisation de l’adaptateur et ne doit pas tenter de modifier les valeurs d’un instance en cours d’exécution.
Si ces paramètres sont modifiés sur un adaptateur en cours d’exécution instance, de nouvelles connexions peuvent remplacer les paramètres de configuration pour les connexions en cours d’exécution.