2

我有一个当前为 HTTP GET 请求设置的 WCF 4.0 服务。我正在尝试修改它以使其使用 POST,但保持与现有 GET URI 的向后兼容性。使用 jQuery 和 JSON 数据调用 Web 服务。因此,我的要求如下:

  • 匹配现有的 GET URI,大概是使用 WebInvoke 属性的 UriTemplate 参数。
  • 从 POST 正文中的 JSON 数据中获取现有参数,大概是通过使用带有 WebInvoke 属性的 WebMessageBodyStyle.Wrapped 和 WebMessageFormat.Json。
  • 最好有办法从 POST 正文中提取大块数据,可能也包含在 JSON 对象中。

好吧,不碍事,这就是我到目前为止所得到的。我的小测试服务称为 AjaxService,它有一种方法称为 ToUpper。首先,我的 web.config:

<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>

    <system.serviceModel>
        <behaviors>
            <endpointBehaviors>
                <behavior name="WebApplication2.AjaxServiceAspNetAjaxBehavior">
                    <!--<enableWebScript />-->
                    <webHttp helpEnabled="true" />
                </behavior>
            </endpointBehaviors>
        </behaviors>

        <protocolMapping>
            <remove scheme="http" />
            <add scheme="http" binding="webHttpBinding" />
        </protocolMapping>

        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />

        <services>
            <service name="WebApplication2.AjaxService">
                <endpoint address=""
                    behaviorConfiguration="WebApplication2.AjaxServiceAspNetAjaxBehavior"
                    binding="webHttpBinding"
                    contract="WebApplication2.AjaxService" />
            </service>
        </services>
    </system.serviceModel>
</configuration>

我的 ToUpper 函数的以下版本允许我在 URI 中传递它的参数,就像 HTTP GET 一样。

  [OperationContract]
  [WebInvoke( UriTemplate="ToUpper?str={str}",
              Method = "POST",
              BodyStyle = WebMessageBodyStyle.WrappedRequest,
              RequestFormat=WebMessageFormat.Json,
              ResponseFormat=WebMessageFormat.Json)]
  public string ToUpper(string str)
  {
      return str.ToUpper();
  }

它在 Javascript 中的使用如下所示,并正确返回“这是来自 URI”。

$(document).ready(function () {
    $.ajax({
        type: "POST",
        url: "AjaxService.svc/ToUpper?str=this%20is%20from%20the%20uri",
        contentType: "application/json; charset=utf-8",
        success: function (data) {
            console.log("result: " + JSON.stringify(data));
        },
        error: function (jqXHR, textStatus, errorThrown) {
            console.log("error", jqXHR, textStatus, errorThrown);
        }
    });
});

UriTemplate="ToUpper?str={str}"我可以通过从 WebInvoke 参数中删除并改用此 javascript 来将参数放入 POST 数据而不是 URI 。它正确返回“这是来自帖子”。

$(document).ready(function () {
    $.ajax({
        type: "POST",
        url: "AjaxService.svc/ToUpper",
        data: JSON.stringify({str:"This is from the POST"}),
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        success: function (data) {
            console.log("result: " + JSON.stringify(data));
        },
        error: function (jqXHR, textStatus, errorThrown) {
            console.log("error", jqXHR, textStatus, errorThrown);
        }
    });
});

我希望如果我离开UriTemplate="ToUpper?str={str}"原地并使用上面的 javascript,将 str 参数从 POST 数据而不是 URI 中提取出来就足够聪明了。不幸的是,它只是给了我一个错误 400。有没有办法让它工作?

我尝试的另一件事是使用可选的 Stream 参数来获取 POST 数据的原始内容。但正如这篇博文指出的那样,只有将内容类型设置为纯文本而不是 JSON,才能获取该流。我可以这样做并手动解析流,但我认为我还需要手动检查 URL 以确定我是否获得了真实值或默认值。呸。

如果无法使用系统绑定/设置进行此操作,我正在考虑尝试编写一个自定义绑定,该绑定可以智能地从 POST 和 URI 中提取参数,并且即使在你“重新使用 JSON。我花了几个小时试图弄清楚如何做到这一点,但我很难过!

有没有其他人解决过这个问题或对如何使其工作有任何想法?我无法想象我是第一个尝试这样做的人,但经过大量搜索后我空手而归。

4

0 回答 0