JSON.stringify是为Web方法创建参数所必需的,不允许使用wcf REST方法的参数

时间:2014-07-07 17:23:32

标签: asp.net json wcf web-config webmethod

数小时的困惑导致我向SO提出自己的贡献问题:

我已将问题缩小到测试解决方案,这就是我所拥有的:

单击按钮后, RunService()会调用WCF服务(webHttpBinding),然后显示服务的响应。接下来的步骤是将一些数据保存到HttpContext.Current.Session(另一个多天的头痛,通过盲目刺伤找到解决方案)。

这是一个Visual Studio 2012解决方案,具有Webforms项目(com.dwf)和WCF服务项目(com.dwf.services),这些项目被发送到本地主机(不同的本地主机,因为它们是两个不同的项目)。为了解决跨域问题,在javascript方面,我添加了 $ .support.cors = true 标志以防止“No Transport”错误。当它发布到共享服务器时,该服务将存在于虚拟目录中,该目录是原始域的子目录(httpdocs / Service)。

当用户单击按钮时,以下功能在客户端运行。

function RunService() {
    $.support.cors = true;
    $.ajax({
        url: 'http://localhost:XXXX/Service1.svc/web/GetData',
        cache:false,
        data: {
            userName: 'DWF',
            password: 'ban',
        },
        contentType: 'application/json; charset=utf-8', 
        success: function (response) {
            $('#results').text('jQuery says ' + response);            
            $.ajax({
                type:'POST',
                url: location.href.slice('http://localhost:7177/'.length + '/SaveToSession',
                data: JSON.stringify({userName: 'DWF',password: 'ban'}),
                error: function (e) {
                    alert(e.statusText);
               },
                contentType: 'application/json; charset=utf-8'
            });
        },
        error: function (err) {
            $('#results').text(err.statusText);
        }

    });
}

Service1.svc是一个支持REST的服务,如下所示:

[System.ServiceModel.Activation.AspNetCompatibilityRequirements
(RequirementsMode=
System.ServiceModel.Activation.AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService1
{
    public string GetData(string userName, string password)
    {
        return string.Format("You entered: {0}/{1}", userName, password);
    }
}

当然,它的界面是这样的:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [WebGet(ResponseFormat=WebMessageFormat.Json)]
    string GetData(string userName, string password);
}

,网络配置就像这样

  <system.serviceModel>
  ...
    <behaviors>
      <endpointBehaviors>
        <behavior name="RESTEndpointBehavior">
          <webHttp helpEnabled="true"/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service name="com.dwf.services.Service1">
        <endpoint address="web" behaviorConfiguration="RESTEndpointBehavior" binding="webHttpBinding" contract="com.dwf.services.IService1"></endpoint>
        <endpoint address="ws" binding="wsHttpBinding" contract="com.dwf.services.IService1"></endpoint>
      </service>
    </services>

我调用的WebMethod SaveToSession存在于每个页面都将继承的BasePage类中。它看起来像这样:

public class BasePage : Page
{
    [System.Web.Services.WebMethod]
    [System.ServiceModel.Web.WebInvoke(Method="POST")]
    public static void SaveToSession(string userName, string password)
    {
        HttpContext.Current.Session["TextValue"] = "Session says " + userName + " entered " + password;
    }
}

如果我使用 JSON.stringify 调用第一个方法(WCF的GetData),我的参数将为null。 如果我在不使用 JSON.stringify 的情况下调用第二种方法(WebMethod的SaveToSession),我的方法会收到内部服务器错误。只有使用上面的ajax调用才能解决此问题。

EDIT 为什么WCF服务需要JSON.stringify,而WebMethod不适用?

为什么JSON.stringify对WCF服务不合适,而WebMethod需要?

这最初是为了更好地理解ASP.NET,Sessions,WCF和静态方法之间的通信,并希望揭开Web.config的神秘面纱。看起来好像我正在努力解决它的一切工作方式的每一步,最后似乎没有什么方便。

1 个答案:

答案 0 :(得分:1)

WCF服务将参数作为对象,服务器在输入时解释输入,“理解”参数名称是传入JSON对象的成员名称。

通过对其进行字符串化来发送整个对象正在发送一个巨大的字符串,其中服务器端代码需要将对象解析为其各自的部分。一种序列化/反序列化的交易。如果有人想要将服务的签名简化为一个参数,则可以使用此选项,如果您拥有可以默认值的对象,这将非常有用。

<强>伪代码

GetData(string data)
{
    EstablishedDataObject obj = DeserializeData(data);
    DoSomething(obj);
}

这比

更容易服务器端代码
GetData(int id, string name, bool likesBruceWillisAsASinger, int numberOfFelonies, 
    string streetName, int numberOfTattoos, bool dislikesTacosButLikesTheIdeaOfTacos)

WebMethod,我仍然坚持的那个。它可能最终变得像“微软如何编程它一样简单,但祝你好运找到可靠的文档。”