Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En el ejemplo WsdlDocumentation se muestra cómo:
Implemente en System.ServiceModel.Description.IWsdlExportExtension un atributo personalizado System.ServiceModel.Description.IContractBehavior para exportar propiedades de atributo como anotaciones WSDL.
Implemente System.ServiceModel.Description.IWsdlImportExtension para importar las anotaciones WSDL personalizadas.
Implemente System.ServiceModel.Description.IServiceContractGenerationExtension y System.ServiceModel.Description.IOperationContractGenerationExtension en un comportamiento de contrato personalizado y un comportamiento de operación personalizada, respectivamente, para escribir anotaciones importadas como comentarios en CodeDom para el contrato y la operación importados.
System.ServiceModel.Description.MetadataExchangeClient Use para descargar el WSDL, un System.ServiceModel.Description.WsdlImporter para importar el WSDL mediante el importador de WSDL personalizado y para System.ServiceModel.Description.ServiceContractGenerator generar código de cliente de Windows Communication Foundation (WCF) con las anotaciones WSDL como /// y comentarios """ en C# y Visual Basic.
Nota:
El procedimiento de instalación y las instrucciones de compilación de este ejemplo se encuentran al final de este tema.
Servicio
El servicio de este ejemplo se marca con dos atributos personalizados. La primera, , WsdlDocumentationAttribute
acepta una cadena en el constructor y se puede aplicar para proporcionar una interfaz de contrato o una operación con una cadena que describe su uso. El segundo, WsdlParamOrReturnDocumentationAttribute
, se puede aplicar a valores devueltos o parámetros para describir esos valores en la operación. En el ejemplo siguiente se muestra un contrato de servicio, ICalculator
, descrito mediante estos atributos.
// 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
implementa IContractBehavior y IOperationBehavior, por lo que las instancias de atributo se agregan al correspondiente ContractDescription o OperationDescription cuando se abre el servicio. El atributo también implementa IWsdlExportExtension. Cuando ExportContract(WsdlExporter, WsdlContractConversionContext) se llama a , que WsdlExporter se usa para exportar los metadatos y que WsdlContractConversionContext contiene los objetos de descripción del servicio se pasan como parámetros que permiten la modificación de los metadatos exportados.
En este ejemplo, dependiendo de si el objeto de contexto de exportación tiene o ContractDescription , OperationDescriptionse extrae un comentario del atributo mediante la propiedad text y se agrega al elemento de anotación WSDL como se muestra en el código siguiente.
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);
}
}
}
Si se exporta una operación, el ejemplo usa la reflexión para obtener los WsdlParamOrReturnDocumentationAttribute
valores de los parámetros y los valores devueltos y los agrega a los elementos de anotación WSDL para esa operación de la siguiente manera.
// 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);
}
}
A continuación, el ejemplo publica metadatos de la manera estándar mediante el siguiente archivo de configuración.
<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>
Cliente Svcutil
Este ejemplo no usa Svcutil.exe. El contrato se proporciona en el archivo generatedClient.cs para que después del ejemplo muestre la importación personalizada de WSDL y la generación de código, se puede invocar el servicio. Para usar el siguiente importador de WSDL personalizado para este ejemplo, puede ejecutar Svcutil.exe y especificar la /svcutilConfig
opción , lo que proporciona la ruta de acceso al archivo de configuración de cliente usado en este ejemplo, que hace referencia a la WsdlDocumentation.dll
biblioteca. Sin embargo, para cargar , WsdlDocumentationImporter
Svuctil.exe debe poder localizar y cargar la WsdlDocumentation.dll
biblioteca, lo que significa que está registrado en la caché global de ensamblados, en la ruta de acceso o está en el mismo directorio que Svcutil.exe. Para obtener un ejemplo básico, como este, lo más sencillo es copiar Svcutil.exe y el archivo de configuración de cliente en el mismo directorio que WsdlDocumentation.dll
y ejecutarlo desde allí.
El importador de WSDL personalizado
El objeto personalizado IWsdlImportExtension también implementa IContractBehavior y IOperationBehavior se va a agregar a los ServiceEndpoints importados y IServiceContractGenerationExtension para IOperationContractGenerationExtension que se invoque para modificar la generación de código cuando se crea el código de contrato o WsdlDocumentationImporter
operación.
En primer lugar, en el ImportContract(WsdlImporter, WsdlContractConversionContext) método , el ejemplo determina si la anotación WSDL está en el nivel de contrato o operación, y se agrega como un comportamiento en el ámbito adecuado, pasando el texto de anotación importado a su 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));
}
}
}
}
A continuación, cuando se genera el código, el sistema invoca los GenerateContract(ServiceContractGenerationContext) métodos y GenerateOperation(OperationContractGenerationContext) , pasando la información de contexto adecuada. El ejemplo da formato a las anotaciones WSDL personalizadas e los inserta como comentarios en 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.");
}
La aplicación cliente
La aplicación cliente carga el importador de WSDL personalizado especificando en el archivo de configuración de la aplicación.
<client>
<endpoint address="http://localhost/servicemodelsamples/service.svc"
binding="wsHttpBinding"
contract="ICalculator" />
<metadata>
<wsdlImporters>
<extension type="Microsoft.ServiceModel.Samples.WsdlDocumentationImporter, WsdlDocumentation"/>
</wsdlImporters>
</metadata>
</client>
Una vez especificado el importador personalizado, el sistema de metadatos de WCF carga el importador personalizado en cualquier WsdlImporter creado para ese propósito. En este ejemplo se usa MetadataExchangeClient para descargar los metadatos, el WsdlImporter configurado correctamente para importar los metadatos mediante el importador personalizado que crea el ejemplo y para ServiceContractGenerator compilar la información de contrato modificada en código de cliente de Visual Basic y C# que se puede usar en Visual Studio para admitir IntelliSense o compilar en documentación XML.
/// 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);
}
Para configurar, compilar y ejecutar el ejemplo
Asegúrese de que ha realizado el procedimiento de instalación única para los ejemplos de Windows Communication Foundation.
Para compilar el código C# o Visual Basic .NET Edition de la solución, siga las instrucciones de Building the Windows Communication Foundation Samples.
Para ejecutar el ejemplo en una configuración de una máquina única o entre máquinas, siga las instrucciones de Ejecución de los ejemplos de Windows Communication Foundation.