HTML Form Handler, exemple

Cet exemple indique comment étendre le modèle de programmation Web Windows Communication Foundation (WCF) pour gérer les publications de formulaire HTML, telles que celles produites par un navigateur Web.

Bb943485.note(fr-fr,VS.90).gifRemarque :
Cet exemple requiert l'installation de .NET Framework version 3.5 pour être généré et exécuté. Visual Studio 2008 est nécessaire pour l'ouverture des fichiers projet et solution.

Analyse des données de formulaire

Les publications de formulaire HTML sont codées comme une série de paires nom-valeur dans un corps d'entité HTTP POST avec un type de contenu application/x-www-form-urlencoded. La méthode ParseQueryString est capable d'analyser ces valeurs dans un NameValueCollection lorsqu'elles sont présentées avec une chaîne du corps de l'entité brute. Pour permettre à cette paire nom/valeur d'être transmise en tant que paramètre à une opération de service WCF, la classe FormDataProcessor dans l'exemple utilise le point d'extensibilité IDispatchMessageFormatter.

L'implémentation de la classe FormDataProcessor de DeserializeRequest utilise ParseQueryString pour analyser le corps de l'entité dans un NameValueCollection. Une requête LINQ (Microsoft Language Integrated Query) permet de remplir d'autres paramètres de méthode dont les valeurs sont disponibles via UriTemplateMatch utilisé pour distribuer la demande à l'opération.

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

Extension de WebHttpBehavior avec RequestFormatter personnalisé

Vous pouvez dériver une classe du WebHttpBehavior pour étendre l'exécution WCF pour chaque opération. Dans l'exemple, FormProcessingBehavior remplace GetRequestDispatchFormatter pour incorporer un FormDataFormatter pour toute opération d'appel Web dont le dernier paramètre est un 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);
        }
    }
}

Implémentation d'un service de traitement de formulaire

Le FormProcessingBehavior masque les détails de traitement de formulaire HTML. L'implémentation de service peut ensuite être écrite sans connaissance spéciale des formulaires HTML, comme illustré dans l'exemple de code suivant.

[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);
        }
        );
}
Bb943485.note(fr-fr,VS.90).gifRemarque :
Pour obtenir une description détaillée de la classe StreamMessageHelper, consultez la rubrique Push-Style Streaming, exemple.

Hébergement du service de traitement de formulaire

Le service est hébergé à l'aide de la classe ServiceHost. Le FormProcessingBehavior personnalisé est ajouté manuellement au ServiceEndpoint avant l'appel de Open comme illustré dans l'exemple de code suivant.

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

En outre, le point de terminaison HTTP GET qui existe par défaut (point de terminaison qui produit la page d'aide HTML par défaut) est supprimé lorsque ServiceMetadataBehavior et ServiceDebugBehavior sont désactivés, comme illustré dans l'exemple de code suivant.

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

Exécution de l'exemple

Pour consulter la sortie de l'exemple, compilez et exécutez le projet HtmlFormProcessing, puis accédez à l'adresse https://localhost:8000/FormTest avec un navigateur Web.

Voir aussi

Tâches

Push-Style Streaming, exemple

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