Özel WSDL Yayını

WsdlDocumentation örneği aşağıdakilerin nasıl yapılacağını gösterir:

Uyarı

Bu örnek için kurulum yordamı ve derleme yönergeleri bu konunun sonunda yer alır.

Hizmet

Bu örnekteki hizmet iki özel öznitelikle işaretlenmiştir. birincisi, oluşturucudaki bir dizeyi WsdlDocumentationAttributekabul eder ve kullanımını açıklayan bir dize ile bir sözleşme arabirimi veya işlemi sağlamak için uygulanabilir. İkincisi, WsdlParamOrReturnDocumentationAttribute işlemdeki bu değerleri açıklamak için dönüş değerlerine veya parametrelere uygulanabilir. Aşağıdaki örnekte, ICalculatorbu öznitelikler kullanılarak açıklanan bir hizmet sözleşmesi gösterilmektedir.

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

WsdlDocumentationAttribute, IContractBehavior ve IOperationBehavior uygular, bu nedenle hizmet açıldığında öznitelik örnekleri ilgili ContractDescription veya OperationDescription'e eklenir. özniteliği de uygular IWsdlExportExtension. Çağrıldığında ExportContract(WsdlExporter, WsdlContractConversionContext) , WsdlExporter meta verileri dışarı aktarmak için kullanılan ve WsdlContractConversionContext hizmet açıklaması nesnelerini içeren, dışarı aktarılan meta verilerin değiştirilmesini sağlayan parametre olarak geçirilir.

Bu örnekte, dışarı aktarma bağlam nesnesinin bir ContractDescription veya bir OperationDescription öğesine sahip olup olmamasına bağlı olarak, metin özelliği kullanılarak öznitelikten bir açıklama ayıklanır ve bu açıklama aşağıdaki kodda gösterildiği gibi WSDL ek açıklama öğesine eklenir.

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

Bir işlem dışarı aktarılıyorsa, örnek uygulama, parametreler ve döndürülen değerler için herhangi bir WsdlParamOrReturnDocumentationAttribute değeri elde etmek amacıyla yansıma kullanır ve bu değerleri o işlemin WSDL ek açıklama öğelerine aşağıdaki gibi ekler.

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

Örnek daha sonra aşağıdaki yapılandırma dosyasını kullanarak meta verileri standart şekilde yayımlar.

<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 istemcisi

Bu örnek Svcutil.exekullanmaz. Sözleşme, generatedClient.cs dosyasında sağlanır, böylece örnekte özel WSDL içeri aktarma ve kod oluşturma gösterildikten sonra hizmet çağrılabilir. Bu örnekte aşağıdaki özel WSDL içeri aktarıcısını kullanmak için Svcutil.exe çalıştırabilir ve /svcutilConfig seçeneğini belirterek bu örnekte kullanılan ve WsdlDocumentation.dll kitaplığına referans veren istemci yapılandırma dosyasının yolunu belirtebilirsiniz. Ancak WsdlDocumentationImporter dosyasını yüklemek için, Svuctil.exe'ın WsdlDocumentation.dll kitaplığını bulup yükleyebilmesi gerekir; yani genel derleme önbelleğinde, yol üzerinde kayıtlı veya Svcutil.exeile aynı dizindedir. Bunun gibi temel bir örnek için yapmanız gereken en kolay şey, Svcutil.exe ve istemci yapılandırma dosyasını ile aynı dizine WsdlDocumentation.dll kopyalamak ve oradan çalıştırmaktır.

Özel WSDL İçeri Aktarıcısı

Özel IWsdlImportExtension nesnesi WsdlDocumentationImporter, içeri aktarılan ServiceEndpoints'e eklenmesi gereken IContractBehavior ve IOperationBehavior ile sözleşme veya işlem kodu oluşturulurken kod oluşturmayı değiştirmek üzere çağrılan IServiceContractGenerationExtension ve IOperationContractGenerationExtension'i de uygular.

İlk olarak, ImportContract(WsdlImporter, WsdlContractConversionContext) yönteminde örnek nesne, WSDL ek açıklamasının sözleşme veya işlem düzeyinde olup olmadığını belirler ve içeri aktarılan ek açıklama metnini yapıcısında geçirerek uygun kapsamda bir davranış olarak kendisini ekler.

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

Ardından, kod oluşturulduğunda sistem, uygun bağlam bilgilerini aktararak GenerateContract(ServiceContractGenerationContext) ve GenerateOperation(OperationContractGenerationContext) yöntemlerini çağırır. Örnek uygulama, özel WSDL notlandırmalarını biçimlendirip bunları CodeDom'a açıklama olarak ekler.

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

İstemci Uygulaması

İstemci uygulaması, özel WSDL içeri aktarıcısını uygulama yapılandırma dosyasında belirterek yükler.

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

Özel içeri aktarıcı belirtildikten sonra, WCF meta veri sistemi özel içeri aktarıcıyı bu amaç için oluşturulan herhangi bir WsdlImporter öğeye yükler. Bu örnek, meta verileri indirmek için MetadataExchangeClient kullanır, özel bir içeri aktarıcı kullanarak meta verileri içeri aktarmak için doğru şekilde yapılandırılmış WsdlImporter, ve değiştirilmiş sözleşme bilgilerini hem Visual Basic hem de C# istemci koduna derlemek için ServiceContractGenerator kullanır; bu kod Visual Studio'da Intellisense'i desteklemek veya XML belgeleri olarak derlenmek üzere kullanılabilir.

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

Örneği ayarlamak, derlemek ve çalıştırmak için

  1. Windows Communication Foundation Örnekleri içinOne-Time Kurulum Yordamını yaptığınızdan emin olun.

  2. Çözümün C# veya Visual Basic .NET sürümünü oluşturmak için Windows Communication Foundation Örneklerioluşturma başlığındaki yönergeleri izleyin.

  3. Örneği tek bir makine veya makineler arası bir yapılandırmada çalıştırmak için, Windows Communication Foundation örneklerini çalıştırmayönergelerini izleyin.