Compartir a través de


Ejemplo de controlador de formulario HTML

Download sample

Este ejemplo muestra cómo extender el Modelo de programación de web Windows Communication Foundation (WCF) para administrar exposiciones de formulario HTML, como aquéllos generados por un explorador web.

Nota

Para generar y ejecutar este ejemplo, es necesario que esté instalado .NET Framework versión 3.5. Para abrir los archivos de solución y proyecto se necesita Visual Studio 2008.

Analizar formularios de datos

Los envíos del formulario HTML están codificados como una serie de pares de nombre y valor dentro de un cuerpo de entidad HTTP POST con un tipo de contenido application/x-www-form-urlencoded. El método ParseQueryString es capaz de analizar estos valores en NameValueCollection cuando se hayan presentado con una cadena de cuerpo de entidad sin formato. Para permitir pasar esta colección de nombre/valor como un parámetro a una operación del servicio WCF, la clase FormDataProcessor en el ejemplo utiliza el punto de extensibilidad IDispatchMessageFormatter.

La implementación de clase FormDataProcessor de DeserializeRequest utiliza ParseQueryString para analizar el cuerpo de la entidad en NameValueCollection. La Consulta integrada de lenguaje de Microsoft (LINQ) se utiliza para rellenar los parámetros de método adicionales, cuyos valores están disponibles a través de UriTemplateMatch utilizados para enviar la solicitud a la operación.

public void DeserializeRequest(System.ServiceModel.Channels.Message message, object[] parameters)
{
    if (WebOperationContext.Current.IncomingRequest.ContentType 
                         != "application/x-www-form-urlencoded")
        throw new InvalidDataException("Unexpected content type");
    Stream s = StreamMessageHelper.GetStream(message);
    string formData = new StreamReader(s).ReadToEnd();
    NameValueCollection parsedForm = 
            System.Web.HttpUtility.ParseQueryString(formData);
    UriTemplateMatch match = 
     message.Properties["UriTemplateMatchResults"] as UriTemplateMatch;
    ParameterInfo[] paramInfos = operation.SyncMethod.GetParameters();
    var binder = CreateParameterBinder( match );
    object[] values = (from p in paramInfos
                       select binder(p)).ToArray<Object>();
    values[paramInfos.Length - 1] = parsedForm;
    values.CopyTo(parameters, 0);
}

private Func<ParameterInfo, object> CreateParameterBinder(UriTemplateMatch match)
{
    QueryStringConverter converter = new QueryStringConverter();
    return delegate( ParameterInfo pi )
    {
        string value = match.BoundVariables[pi.Name];
        if (converter.CanConvert(pi.ParameterType) && value != null)
            return converter.ConvertStringToValue(value, 
                                                   pi.ParameterType);
        else
        return value;
    };
}

Extienda WebHttpBehavior con un RequestFormatter personalizado

Puede derivar una clase de WebHttpBehavior para extender WCF en tiempo de ejecución para cada operación. En el ejemplo, FormProcessingBehavior invalida GetRequestDispatchFormatter para complementar un FormDataFormatter para cualquier operación de invocación de Web cuyo último parámetro sea NameValueCollection.

public class FormProcessingBehavior : WebHttpBehavior
{
    protected override IDispatchMessageFormatter GetRequestDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
    {
        //Messages[0] is the request message
        MessagePartDescriptionCollection parts = 
                 operationDescription.Messages[0].Body.Parts;

        //This formatter looks for [WebInvoke] operations that have
        // their last parameter typed as NameValueCollection
        if (operationDescription.Behaviors.Find<WebInvokeAttribute>() 
                != null &&
            parts.Count > 0 &&
            parts[parts.Count - 1].Type == typeof(NameValueCollection))
        {
            return new FormDataRequestFormatter(operationDescription);
        }
        else
        {
            return base.GetRequestDispatchFormatter(
                      operationDescription, endpoint);
        }
    }
}

Implementar un formulario de procesamiento de servicio

FormProcessingBehavior oculta los detalles del procesamiento del formulario HTML. La implementación del servicio se puede escribir a continuación sin un conocimiento especial de formularios HTML, como se muestra en el código muestra siguiente.

[OperationContract]
[WebInvoke(UriTemplate = "ProcessForm/{templateParam1}/{templateParam2}")]
public Message ProcessForm(string templateParam1, string templateParam2, NameValueCollection formData)
{
    DumpValues(Console.Out, templateParam1, templateParam2, formData);

    return StreamMessageHelper.CreateMessage(
        MessageVersion.None, "",
        "text/plain",
        delegate(Stream output)
        {
          TextWriter writer = new StreamWriter(output);
          DumpValues(writer, templateParam1, templateParam2, formData);
        }
        );
}

Nota

Para obtener una descripción detallada de la clase StreamMessageHelper, veaEjemplo de secuencia de estilo de inserción..

Hospedar el servicio de procesamiento de formulario

El servicio se hospeda utilizando la clase ServiceHost. El FormProcessingBehavior personalizado se agrega manualmente a ServiceEndpoint antes de llamar a Open como se muestra en el código siguiente.

ServiceHost host = new ServiceHost(typeof(Service), new Uri("https://localhost:8000/FormTest"));

ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(Service), new WebHttpBinding(), "");
endpoint.Behaviors.Add(new FormProcessingBehavior());

Además, el extremo HTTP GET que existe de forma predeterminada se quita (el extremo que genera la página de ayuda HTML predeterminada) deshabilitando ServiceMetadataBehavior y ServiceDebugBehavior como se muestra en el ejemplo de código siguiente.

ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();

if (smb != null)
      {
    smb.HttpGetEnabled = false;
    smb.HttpsGetEnabled = false;
}

ServiceDebugBehavior sdb = host.Description.Behaviors.Find<ServiceDebugBehavior>();
if (sdb != null)
{
    sdb.HttpHelpPageEnabled = false;
}

Ejecutar el ejemplo

Para ver el resultado del ejemplo, compile y ejecute el proyecto HtmlFormProcessing y a continuación, navegar por https://localhost:8000/FormTest con un explorador web.

Consulte también

Otros recursos

Ejemplo de secuencia de estilo de inserción

Footer image

Copyright © 2007 Microsoft Corporation. Reservados todos los derechos.