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
Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.