HTML 窗体处理程序示例
本示例演示如何扩展 Windows Communication Foundation (WCF) Web 编程模型以处理 HTML 窗体发布,如那些用 Web 浏览器生成的发布。
提示
此示例需要安装 .NET Framework 3.5 版才能生成和运行。若要打开项目和解决方案文件,需要使用 Visual Studio 2008。
分析窗体数据
HTML 窗体发布编码为 HTTP POST 实体正文内的一系列名称/值对,其内容类型为 application/x-www-form-urlencoded。当用原始实体正文字符串表示时,ParseQueryString 方法可以将这些值分析成一个 NameValueCollection。为了可以将此名称/值集合作为参数传递给 WCF 服务操作,示例中的 FormDataProcessor
类使用了 IDispatchMessageFormatter 扩展点。
FormDataProcessor
类的 DeserializeRequest 实现使用 ParseQueryString 来分析 NameValueCollection 中的实体正文。可以使用 Microsoft 语言集成查询 (LINQ) 来填充附加方法参数,这些参数的值可通过用于将请求调度到操作的 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);
}
);
}
提示
有关 StreamMessageHelper
类的详细说明,请参见推送式流处理示例。
承载窗体处理服务
服务是使用 ServiceHost 类进行承载的。自定义 FormProcessingBehavior
是在调用 Open 之前将手动添加到 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());
另外,通过禁用 ServiceMetadataBehavior 和 ServiceDebugBehavior,可以移除默认存在的 HTTP GET 终结点(生成默认 HTML 帮助页的终结点),如下面的示例代码所示。
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。
另请参见
任务
Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.