Delen via


Aangepaste WSDL-publicatie

In het WsdlDocumentation-voorbeeld ziet u het volgende:

Notitie

De installatieprocedure en build-instructies voor dit voorbeeld bevinden zich aan het einde van dit onderwerp.

Service

De service in dit voorbeeld is gemarkeerd met twee aangepaste kenmerken. De eerste, de WsdlDocumentationAttribute, accepteert een tekenreeks in de constructor en kan worden toegepast om een contractinterface of bewerking te bieden met een tekenreeks die het gebruik beschrijft. De tweede, WsdlParamOrReturnDocumentationAttributekan worden toegepast om waarden of parameters te retourneren om deze waarden in de bewerking te beschrijven. In het volgende voorbeeld ziet u een servicecontract, ICalculatorbeschreven met behulp van deze kenmerken.

// 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
    );
}

De WsdlDocumentationAttribute implementaties IContractBehavior en IOperationBehavior, zodat de kenmerkexemplaren worden toegevoegd aan de bijbehorende ContractDescription of OperationDescription wanneer de service wordt geopend. Het kenmerk implementeert IWsdlExportExtensionook . Wanneer ExportContract(WsdlExporter, WsdlContractConversionContext) deze wordt aangeroepen, worden de WsdlExporter metagegevens die worden gebruikt voor het exporteren van de metagegevens en de WsdlContractConversionContext objecten die de servicebeschrijvingsobjecten bevatten doorgegeven als parameters, waardoor de wijziging van de geëxporteerde metagegevens mogelijk wordt.

In dit voorbeeld wordt, afhankelijk van of het exportcontextobject een ContractDescription of een OperationDescriptionopmerking heeft, geëxtraheerd uit het kenmerk met behulp van de teksteigenschap en wordt deze toegevoegd aan het WSDL-annotatieelement, zoals wordt weergegeven in de volgende code.

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);
        }
    }
}

Als een bewerking wordt geëxporteerd, gebruikt het voorbeeld weerspiegeling om waarden voor parameters te verkrijgen WsdlParamOrReturnDocumentationAttribute en waarden te retourneren en deze als volgt toe te voegt aan de WSDL-annotatie-elementen voor die bewerking.

// 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);
    }
}

Het voorbeeld publiceert vervolgens metagegevens op de standaardmethode met behulp van het volgende configuratiebestand.

<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 dit voorbeeld wordt geen gebruikgemaakt van Svcutil.exe. Het contract wordt geleverd in het generatedClient.cs-bestand, zodat nadat het voorbeeld aangepaste WSDL-import en codegeneratie heeft gedemonstreerd, de service kan worden aangeroepen. Als u de volgende aangepaste WSDL-importfunctie voor dit voorbeeld wilt gebruiken, kunt u Svcutil.exe uitvoeren en de /svcutilConfig optie opgeven, waardoor het pad naar het clientconfiguratiebestand dat in dit voorbeeld wordt gebruikt, verwijst naar de WsdlDocumentation.dll bibliotheek. Als u de WsdlDocumentationImporterbibliotheek echter wilt laden, moet Svuctil.exe de bibliotheek kunnen vinden en laden, wat betekent dat deze WsdlDocumentation.dll is geregistreerd in de globale assemblycache, in het pad of zich in dezelfde map bevindt als Svcutil.exe. Voor een eenvoudig voorbeeld, zoals dit, is het eenvoudigst om Svcutil.exe en het clientconfiguratiebestand te kopiëren naar dezelfde map als WsdlDocumentation.dll en het daar uit te voeren.

De aangepaste WSDL Importer

Het aangepaste object implementeert en moet ook worden toegevoegd aan de geïmporteerde IWsdlImportExtension ServiceEndpoints en IOperationContractGenerationExtensionIServiceContractGenerationExtension worden aangeroepen om de codegeneratie te wijzigen wanneer de contract- of bewerkingscode wordt gemaakt.IOperationBehaviorIContractBehaviorWsdlDocumentationImporter

In de ImportContract(WsdlImporter, WsdlContractConversionContext) methode bepaalt het voorbeeld eerst of de WSDL-annotatie zich op contract- of bewerkingsniveau bevindt en zichzelf toevoegt als gedrag op het juiste bereik, waarbij de geïmporteerde annotatietekst wordt doorgegeven aan de constructor.

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));
            }
        }
    }
}

Wanneer de code wordt gegenereerd, roept het systeem vervolgens de GenerateContract(ServiceContractGenerationContext) en GenerateOperation(OperationContractGenerationContext) methoden aan, waarbij de juiste contextinformatie wordt doorgegeven. In het voorbeeld worden de aangepaste WSDL-aantekeningen opgemaakt en ingevoegd als opmerkingen in de CodeDom.

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.");
}

De clienttoepassing

De clienttoepassing laadt de aangepaste WSDL-importfunctie door deze op te geven in het configuratiebestand van de toepassing.

<client>
  <endpoint address="http://localhost/servicemodelsamples/service.svc"
  binding="wsHttpBinding"
  contract="ICalculator" />
  <metadata>
    <wsdlImporters>
      <extension type="Microsoft.ServiceModel.Samples.WsdlDocumentationImporter, WsdlDocumentation"/>
    </wsdlImporters>
  </metadata>
</client>

Zodra de aangepaste importeur is opgegeven, laadt het WCF-metagegevenssysteem de aangepaste importeur in alle WsdlImporter gemaakte importprogramma's voor dat doel. In dit voorbeeld wordt gebruikgemaakt van het MetadataExchangeClient downloaden van de metagegevens, de WsdlImporter correct geconfigureerde voor het importeren van de metagegevens met behulp van de aangepaste importeur die het voorbeeld maakt, en het ServiceContractGenerator compileren van de gewijzigde contractgegevens in zowel Visual Basic- als C#-clientcode die in Visual Studio kan worden gebruikt om IntelliSense te ondersteunen of gecompileerd in XML-documentatie.

/// 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);
}

Het voorbeeld instellen, compileren en uitvoeren

  1. Zorg ervoor dat u de eenmalige installatieprocedure voor de Windows Communication Foundation-voorbeelden hebt uitgevoerd.

  2. Als u de C# of Visual Basic .NET-editie van de oplossing wilt bouwen, volgt u de instructies in het bouwen van de Windows Communication Foundation-voorbeelden.

  3. Als u het voorbeeld wilt uitvoeren in een configuratie met één of meerdere computers, volgt u de instructies in Het uitvoeren van de Windows Communication Foundation-voorbeelden.