次の方法で共有


HTML フォーム ハンドラのサンプル

Download sample

このサンプルは、Windows Communication Foundation (WCF) Web プログラミング モデルを拡張して、Web ブラウザで生成されるような HTML フォーム ポストを処理する方法を示します。

Noteメモ :

このサンプルをビルドして実行するには、.NET Framework Version 3.5 をインストールする必要があります。Visual Studio 2008 では、プロジェクト ファイルとソリューション ファイルを開く必要があります。

フォーム データの解析

HTML フォーム ポストは、コンテンツ タイプが application/x-www-form-urlencoded の HTTP POST エンティティ本体内の一連の名前と値のペアとしてエンコードされます。ParseQueryString メソッドは、生のエンティティ本体文字列と共に存在する場合、これらの値を NameValueCollection に解析できます。この名前/値のコレクションをパラメータとして WCF サービス操作に渡すには、サンプル内の FormDataProcessor クラスでは IDispatchMessageFormatter 機能拡張ポイントが使用されます。

FormDataProcessor クラスの DeserializeRequest の実装では、ParseQueryString を使用して NameValueCollection 内のエンティティ本体を解析します。Microsoft 統合言語クエリ (LINQ: Language Integrated Query) を使用して、操作に要求をディスパッチするために使用された UriTemplateMatch を通じてその値を使用できるその他のメソッドのパラメータに指定します。

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

カスタムの RequestFormatter を使用した WebHttpBehavior の拡張

WebHttpBehavior からクラスを派生させて、各操作の WCF ランタイムを拡張できます。サンプルでは、FormProcessingBehaviorGetRequestDispatchFormatter をオーバーライドし、最後のパラメータが NameValueCollection である Web 呼び出し操作の FormDataFormatter が組み込まれます。

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

フォーム処理サービスの実装

FormProcessingBehavior は HTML フォーム処理の詳細を表示しません。次のコード例に示すように、HTML フォームについて特別な知識がなくても、サービス実装を書き込むことができます。

[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);
        }
        );
}
Noteメモ :

StreamMessageHelper クラスの詳細については、「プッシュ型ストリーミングのサンプル」を参照してください。

フォーム処理サービスのホスティング

サービスは ServiceHost クラスを使用してホストされます。次のコード例に示すように、Open の呼び出し前に、カスタムの FormProcessingBehaviorServiceEndpoint に手動で追加されます。

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

また、次のコード例に示すように、既定で存在する HTTP GET エンドポイント (既定の HTML ヘルプ ページを生成するエンドポイント) は、ServiceMetadataBehavior および ServiceDebugBehavior を無効にすると削除されます。

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

サンプルの実行

サンプルの出力を表示するには、HtmlFormProcessing プロジェクトをコンパイルして実行し、Web ブラウザで https://localhost:8000/FormTest に移動します。

関連項目

その他の技術情報

プッシュ型ストリーミングのサンプル

Footer image

Copyright © 2007 by Microsoft Corporation.All rights reserved.