HTML 表單處理常式範例

這個範例示範如何擴充 Windows Communication Foundation (WCF) Web 程式設計模型以處理 HTML 表單張貼 (例如 Web 瀏覽器所產生者)。

Bb943485.note(zh-tw,VS.90).gif注意:
要建置和執行這個範例,必須安裝 .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 Language Integrated Query (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);
        }
        );
}
Bb943485.note(zh-tw,VS.90).gif注意:
如需 StreamMessageHelper 類別的詳細說明,請參閱Push-Style 資料流範例

裝載表單處理服務

服務是使用 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());

此外,還會停用 ServiceMetadataBehaviorServiceDebugBehavior,將預設存在的 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。

請參閱

工作

Push-Style 資料流範例

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