HTML フォーム ハンドラのサンプル
このサンプルは、Windows Communication Foundation (WCF) Web プログラミング モデルを拡張して、Web ブラウザで生成されるような HTML フォーム ポストを処理する方法を示します。
メモ : |
---|
このサンプルをビルドして実行するには、.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 ランタイムを拡張できます。サンプルでは、FormProcessingBehavior
は GetRequestDispatchFormatter をオーバーライドし、最後のパラメータが 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);
}
);
}
メモ : |
---|
|
フォーム処理サービスのホスティング
サービスは ServiceHost クラスを使用してホストされます。次のコード例に示すように、Open の呼び出し前に、カスタムの FormProcessingBehavior
が ServiceEndpoint に手動で追加されます。
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 に移動します。
関連項目
その他の技術情報
Copyright © 2007 by Microsoft Corporation.All rights reserved.