Share via


Beispiel für HTML-Formularhandler

In diesem Beispiel wird veranschaulicht, wie das Windows Communication Foundation (WCF)-Webprogrammiermodell für die Behandlung von HTML-Formularbereitstellungen erweitert wird, wie sie beispielsweise von einem Webbrowser erstellt werden.

Tipp

Zum Erstellen und Ausführen dieses Beispiels muss .NET Framework, Version 3.5 installiert sein. Zum Öffnen des Projekts und der Projektmappendateien ist Visual Studio 2008 erforderlich.

Analysieren von Formulardaten

HTML-Formularbereitstellungen werden als eine Folge von Name-Wert-Paaren innerhalb eines HTTP POST-Entitättexts mit dem Inhaltstyp application/x-www-form-urlencoded codiert. Die ParseQueryString-Methode kann diese Werte in eine NameValueCollection analysieren, wenn eine unformatierte Entitätstextzeichenfolge bereitgestellt wird. Damit diese Name-Wert-Auflistung als Parameter an einen WCF-Dienstvorgang übergeben werden kann, verwendet die FormDataProcessor-Klasse in dem Beispiel den IDispatchMessageFormatter-Erweiterungspunkt.

Die Implementierung von DeserializeRequest der FormDataProcessor-Klasse verwendet ParseQueryString, um den Entitätstext in einer NameValueCollection zu analysieren. Eine Microsoft Language Integrated Query (LINQ) wird verwendet, um zusätzliche Methodenparameter einzugeben, deren Werte durch die UriTemplateMatch verfügbar sind, die für die Übermittlung der Anforderung an den Vorgang verwendet wird.

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

Erweitern von WebHttpBehavior mit einem benutzerdefinierten RequestFormatter

Sie können eine Klasse von dem WebHttpBehavior ableiten, um die WCF-Laufzeit für jeden Vorgang zu erweitern. In diesem Beispiel überschreibt FormProcessingBehavior GetRequestDispatchFormatter, um einen FormDataFormatter für alle im Web aufgerufenen Vorgänge einzusetzen, deren letzter Parameter eine NameValueCollection ist.

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

Implementieren eines Formularverarbeitungsdiensts

Das FormProcessingBehavior blendet die Details der HTML-Formularverarbeitung aus. Die Dienstimplementierung kann anschließend ohne besondere Kenntnisse über HTML-Formulare geschrieben werden, wie im folgenden Beispielcode dargestellt.

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

Tipp

Eine ausführliche Erläuterung der StreamMessageHelper-Klasse finden Sie unter Beispiel für Push-Streaming.

Hosten des Formularverarbeitungsdiensts

Der Dienst wird mithilfe der ServiceHost-Klasse gehostet. Das benutzerdefinierte FormProcessingBehavior wird dem ServiceEndpoint manuell hinzugefügt, bevor Open aufgerufen wird, wie im folgenden Beispielcode dargestellt.

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

Außerdem wird der standardmäßig vorhandene HTTP GET-Endpunkt (der Endpunkt, der die HTML-Hilfeseite erstellt) entfernt, indem das ServiceMetadataBehavior und das ServiceDebugBehavior deaktiviert werden, wie im folgenden Beispielcode dargestellt.

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

Ausführen des Beispiels

Um die Ausgabe des Beispiels anzuzeigen, kompilieren Sie das HtmlFormProcessing-Projekt, und führen Sie es aus. Navigieren Sie anschließend mit einem Webbrowser zu https://localhost:8000/FormTest.

Siehe auch

Aufgaben

Beispiel für Push-Streaming

Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.