Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Im WsdlDocumentation-Beispiel wird veranschaulicht, wie:
Implementieren Sie eine System.ServiceModel.Description.IWsdlExportExtension auf einem benutzerdefinierten System.ServiceModel.Description.IContractBehavior-Attribut, um die Attributeigenschaften als WSDL-Anmerkungen zu exportieren.
Implementieren Sie System.ServiceModel.Description.IWsdlImportExtension, um die benutzerdefinierten WSDL-Anmerkungen zu importieren.
Implementieren Sie System.ServiceModel.Description.IServiceContractGenerationExtension für ein benutzerdefiniertes Vertragsverhalten und System.ServiceModel.Description.IOperationContractGenerationExtension für ein benutzerdefiniertes Vorgangsverhalten, um importierte Anmerkungen als Kommentare im CodeDom für den importierten Vertrag und Vorgang zu hinterlegen.
Verwenden Sie System.ServiceModel.Description.MetadataExchangeClient zum Herunterladen der WSDL, System.ServiceModel.Description.WsdlImporter zum Importieren der WSDL mit dem benutzerdefinierten WSDL-Importer und System.ServiceModel.Description.ServiceContractGenerator zum Generieren von Windows Communication Foundation (WCF)-Clientcode mit den WSDL-Anmerkungen als ///- and '''-Kommentare in C# und Visual Basic.
Hinweis
Die Einrichtungsverfahren und Build-Anweisungen für dieses Beispiel befinden sich am Ende dieses Themas.
Dienstleistung
Der Dienst in diesem Beispiel ist mit zwei benutzerdefinierten Attributen gekennzeichnet. Der erste, der WsdlDocumentationAttribute, akzeptiert eine Zeichenfolge im Konstruktor und kann angewendet werden, um eine Vertragsschnittstelle oder einen Vorgang mit einer Zeichenfolge bereitzustellen, die seine Verwendung beschreibt. Die zweite, WsdlParamOrReturnDocumentationAttribute, kann auf Rückgabewerte oder Parameter angewendet werden, um diese Werte in der Operation zu beschreiben. Das folgende Beispiel zeigt einen Dienstvertrag, ICalculatorder mit diesen Attributen beschrieben wird.
// Define a service contract.
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
// Document it.
[WsdlDocumentation("The ICalculator contract performs basic calculation services.")]
public interface ICalculator
{
[OperationContract]
[WsdlDocumentation("The Add operation adds two numbers and returns the result.")]
[return:WsdlParamOrReturnDocumentation("The result of adding the two arguments together.")]
double Add(
[WsdlParamOrReturnDocumentation("The first value to add.")]double n1,
[WsdlParamOrReturnDocumentation("The second value to add.")]double n2
);
[OperationContract]
[WsdlDocumentation("The Subtract operation subtracts the second argument from the first.")]
[return:WsdlParamOrReturnDocumentation("The result of the second argument subtracted from the first.")]
double Subtract(
[WsdlParamOrReturnDocumentation("The value from which the second is subtracted.")]double n1,
[WsdlParamOrReturnDocumentation("The value that is subtracted from the first.")]double n2
);
[OperationContract]
[WsdlDocumentation("The Multiply operation multiplies two values.")]
[return:WsdlParamOrReturnDocumentation("The result of multiplying the first and second arguments.")]
double Multiply(
[WsdlParamOrReturnDocumentation("The first value to multiply.")]double n1,
[WsdlParamOrReturnDocumentation("The second value to multiply.")]double n2
);
[OperationContract]
[WsdlDocumentation("The Divide operation returns the value of the first argument divided by the second argument.")]
[return:WsdlParamOrReturnDocumentation("The result of dividing the first argument by the second.")]
double Divide(
[WsdlParamOrReturnDocumentation("The numerator.")]double n1,
[WsdlParamOrReturnDocumentation("The denominator.")]double n2
);
}
Die WsdlDocumentationAttribute implementieren IContractBehavior und IOperationBehavior, sodass die Attributinstanzen dem entsprechenden ContractDescription oder OperationDescription hinzugefügt werden, wenn der Dienst geöffnet wird. Das Attribut implementiert auch IWsdlExportExtension. Wenn ExportContract(WsdlExporter, WsdlContractConversionContext) aufgerufen wird, werden die WsdlExporter, die zum Exportieren der Metadaten verwendet werden, und die WsdlContractConversionContext, die die Dienstbeschreibungsobjekte enthalten, als Parameter übergeben, die die Änderung der exportierten Metadaten ermöglichen.
In diesem Beispiel wird abhängig davon, ob das Exportkontextobjekt über ein ContractDescription oder ein OperationDescriptionObjekt verfügt, ein Kommentar aus dem Attribut mithilfe der Texteigenschaft extrahiert und dem WSDL-Anmerkungselement hinzugefügt, wie im folgenden Code gezeigt.
public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
{
if (contractDescription != null)
{
// Inside this block it is the contract-level comment attribute.
// This.Text returns the string for the contract attribute.
// Set the doc element; if this isn't done first, there is no XmlElement in the
// DocumentElement property.
context.WsdlPortType.Documentation = string.Empty;
// Contract comments.
XmlDocument owner = context.WsdlPortType.DocumentationElement.OwnerDocument;
XmlElement summaryElement = owner.CreateElement("summary");
summaryElement.InnerText = this.Text;
context.WsdlPortType.DocumentationElement.AppendChild(summaryElement);
}
else
{
Operation operation = context.GetOperation(operationDescription);
if (operation != null)
{
// We are dealing strictly with the operation here.
// This.Text returns the string for the operation-level attributes.
// Set the doc element; if this isn't done first, there is no XmlElement in the
// DocumentElement property.
operation.Documentation = String.Empty;
// Operation C# triple comments.
XmlDocument owner = operation.DocumentationElement.OwnerDocument;
XmlElement newSummaryElement = owner.CreateElement("summary");
newSummaryElement.InnerText = this.Text;
operation.DocumentationElement.AppendChild(newSummaryElement);
}
}
}
Wenn ein Vorgang exportiert wird, verwendet das Beispiel Spiegelung, um Werte WsdlParamOrReturnDocumentationAttribute für Parameter und Rückgabewerte abzurufen, und fügt sie den WSDL-Anmerkungselementen für diesen Vorgang wie folgt hinzu.
// Get returns information
ParameterInfo returnValue = operationDescription.SyncMethod.ReturnParameter;
object[] returnAttrs = returnValue.GetCustomAttributes(typeof(WsdlParamOrReturnDocumentationAttribute), false);
if (returnAttrs.Length != 0)
{
// <returns>text.</returns>
XmlElement returnsElement = owner.CreateElement("returns");
returnsElement.InnerText = ((WsdlParamOrReturnDocumentationAttribute)returnAttrs[0]).ParamComment;
operation.DocumentationElement.AppendChild(returnsElement);
}
// Get parameter information.
ParameterInfo[] args = operationDescription.SyncMethod.GetParameters();
for (int i = 0; i < args.Length; i++)
{
object[] docAttrs = args[i].GetCustomAttributes(typeof(WsdlParamOrReturnDocumentationAttribute), false);
if (docAttrs.Length == 1)
{
// <param name="Int1">Text.</param>
XmlElement newParamElement = owner.CreateElement("param");
XmlAttribute paramName = owner.CreateAttribute("name");
paramName.Value = args[i].Name;
newParamElement.InnerText = ((WsdlParamOrReturnDocumentationAttribute)docAttrs[0]).ParamComment;
newParamElement.Attributes.Append(paramName);
operation.DocumentationElement.AppendChild(newParamElement);
}
}
Dann veröffentlicht das Beispiel Metadaten auf standardmäßige Weise mithilfe der folgenden Konfigurationsdatei.
<services>
<service
name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<!-- ICalculator is exposed at the base address provided by host: http://localhost/servicemodelsamples/service.svc -->
<endpoint address=""
binding="wsHttpBinding"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
<!-- the mex endpoint is exposed at http://localhost/servicemodelsamples/service.svc/mex -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
Svcutil-Client
In diesem Beispiel wird Svcutil.exenicht verwendet. Der Vertrag wird in der generatedClient.cs-Datei bereitgestellt, sodass der Dienst aufgerufen werden kann, nachdem das Beispiel den benutzerdefinierten WSDL-Import und die Codegenerierung veranschaulicht hat. Um den folgenden benutzerdefinierten WSDL-Importer für dieses Beispiel zu verwenden, können Sie Svcutil.exe ausführen und die /svcutilConfig Option angeben, wodurch der Pfad zur in diesem Beispiel verwendeten Clientkonfigurationsdatei angegeben wird, die auf die WsdlDocumentation.dll Bibliothek verweist. Um die WsdlDocumentationImporterBibliothek zu laden, muss Svuctil.exe jedoch in der Lage sein, die WsdlDocumentation.dll Bibliothek zu finden und zu laden. Dies bedeutet, dass sie entweder im globalen Assemblycache, im Pfad oder im selben Verzeichnis wie Svcutil.exeregistriert ist. Für ein einfaches Beispiel wie dies ist es am einfachsten, Svcutil.exe und die Clientkonfigurationsdatei in dasselbe Verzeichnis zu kopieren und WsdlDocumentation.dll von dort aus auszuführen.
Der benutzerdefinierte WSDL-Importer
Das benutzerdefinierte IWsdlImportExtension Objekt WsdlDocumentationImporter implementiert auch IContractBehavior und IOperationBehavior und wird zu den importierten ServiceEndpoints hinzugefügt. Die Methoden IServiceContractGenerationExtension und IOperationContractGenerationExtension werden aufgerufen, um die Codegenerierung zu ändern, wenn der Vertrags- oder Vorgangscode erstellt wird.
Zuerst bestimmt das Beispiel in der ImportContract(WsdlImporter, WsdlContractConversionContext)-Methode, ob sich die WSDL-Anmerkung auf der Vertrags- oder der Vorgangsebene befindet und fügt sich selbst dem entsprechenden Bereich als Verhalten hinzu, wobei der importierte Anmerkungstext an ihren Konstruktor übergeben wird.
public void ImportContract(WsdlImporter importer, WsdlContractConversionContext context)
{
// Contract Documentation
if (context.WsdlPortType.Documentation != null)
{
// System examines the contract behaviors to see whether any implement IWsdlImportExtension.
context.Contract.Behaviors.Add(new WsdlDocumentationImporter(context.WsdlPortType.Documentation));
}
// Operation Documentation
foreach (Operation operation in context.WsdlPortType.Operations)
{
if (operation.Documentation != null)
{
OperationDescription operationDescription = context.Contract.Operations.Find(operation.Name);
if (operationDescription != null)
{
// System examines the operation behaviors to see whether any implement IWsdlImportExtension.
operationDescription.Behaviors.Add(new WsdlDocumentationImporter(operation.Documentation));
}
}
}
}
Wenn der Code generiert wird, ruft das System dann die GenerateContract(ServiceContractGenerationContext) und GenerateOperation(OperationContractGenerationContext) methoden auf, und übergibt die entsprechenden Kontextinformationen. Im Beispiel werden die benutzerdefinierten WSDL-Anmerkungen formatiert und als Kommentare in den CodeDom eingefügt.
public void GenerateContract(ServiceContractGenerationContext context)
{
Debug.WriteLine("In generate contract.");
context.ContractType.Comments.AddRange(FormatComments(text));
}
public void GenerateOperation(OperationContractGenerationContext context)
{
context.SyncMethod.Comments.AddRange(FormatComments(text));
Debug.WriteLine("In generate operation.");
}
Die Clientanwendung
Die Clientanwendung lädt den benutzerdefinierten WSDL-Importer, indem er in der Anwendungskonfigurationsdatei angegeben wird.
<client>
<endpoint address="http://localhost/servicemodelsamples/service.svc"
binding="wsHttpBinding"
contract="ICalculator" />
<metadata>
<wsdlImporters>
<extension type="Microsoft.ServiceModel.Samples.WsdlDocumentationImporter, WsdlDocumentation"/>
</wsdlImporters>
</metadata>
</client>
Nachdem der benutzerdefinierte Importeur angegeben wurde, lädt das WCF-Metadatensystem den benutzerdefinierten Importeur in jeden für diesen Zweck erstellten WsdlImporter. In diesem Beispiel wird der MetadataExchangeClient verwendet, um die Metadaten herunterzuladen. Der WsdlImporter ist ordnungsgemäß konfiguriert, um die Metadaten mithilfe des benutzerdefinierten Importers zu importieren, den das Beispiel erstellt. Außerdem wird die ServiceContractGenerator verwendet, um die geänderten Vertragsinformationen in Visual Basic- und C#-Clientcode zu kompilieren. Dieser Code kann in Visual Studio genutzt werden, um IntelliSense zu unterstützen oder in der XML-Dokumentation kompiliert zu werden.
/// From WSDL Documentation:
///
/// <summary>The ICalculator contract performs basic calculation
/// services.</summary>
///
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://Microsoft.ServiceModel.Samples", ConfigurationName="ICalculator")]
public interface ICalculator
{
/// From WSDL Documentation:
///
/// <summary>The Add operation adds two numbers and returns the
/// result.</summary><returns>The result of adding the two arguments
/// together.</returns><param name="n1">The first value to add.</param><param
/// name="n2">The second value to add.</param>
///
[System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Add", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/AddResponse")]
double Add(double n1, double n2);
/// From WSDL Documentation:
///
/// <summary>The Subtract operation subtracts the second argument from the
/// first.</summary><returns>The result of the second argument subtracted from the
/// first.</returns><param name="n1">The value from which the second is
/// subtracted.</param><param name="n2">The value that is subtracted from the
/// first.</param>
///
[System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Subtract", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/SubtractResponse")]
double Subtract(double n1, double n2);
/// From WSDL Documentation:
///
/// <summary>The Multiply operation multiplies two values.</summary><returns>The
/// result of multiplying the first and second arguments.</returns><param
/// name="n1">The first value to multiply.</param><param name="n2">The second value
/// to multiply.</param>
///
[System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Multiply", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/MultiplyResponse")]
double Multiply(double n1, double n2);
/// From WSDL Documentation:
///
/// <summary>The Divide operation returns the value of the first argument divided
/// by the second argument.</summary><returns>The result of dividing the first
/// argument by the second.</returns><param name="n1">The numerator.</param><param
/// name="n2">The denominator.</param>
///
[System.ServiceModel.OperationContractAttribute(Action="http://Microsoft.ServiceModel.Samples/ICalculator/Divide", ReplyAction="http://Microsoft.ServiceModel.Samples/ICalculator/DivideResponse")]
double Divide(double n1, double n2);
}
So können Sie das Beispiel einrichten, erstellen und ausführen
Stellen Sie sicher, dass Sie das One-Time Setup-Verfahren für die Windows Communication Foundation-Beispieleausgeführt haben.
Um die C#- oder Visual Basic .NET-Edition der Lösung zu erstellen, befolgen Sie die Anweisungen in Building the Windows Communication Foundation Samples.
Wenn Sie das Beispiel in einer Konfiguration mit einem Computer oder über Computer hinweg ausführen möchten, folgen Sie den Anweisungen unter Durchführen der Windows Communication Foundation-Beispiele.