.NET ASMX - 返回纯JSON?

时间:2009-12-14 19:44:22

标签: .net wcf web-services json asmx

我在这里疯了。我查看了以下条目, none 正在纠正我看到的异常行为:

我也看过了,并确认了我的设置:http://www.asp.net/AJAX/documentation/live/ConfiguringASPNETAJAX.aspx

这是我的代码(ASMX代码背后):

namespace RivWorks.Web.Services
{
    /// <summary>
    /// Summary description for Negotiate
    /// </summary>
    [WebService(Namespace = "http://rivworks.com/webservices/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    [ScriptService]
    public class Negotiate : System.Web.Services.WebService
    {
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public RivWorks.Data.Objects.rivProduct GetSetup(string jsonInput)
        {
            // Deserialize the input and get all the data we need...
            // TODO:  This is a quick hack just to work with this for now...
            char[] tokens = { '(', '{', '}', ')', ',', '"' };
            string[] inputs = jsonInput.Split(tokens);
            string inputRef = "";
            string inputDate = "";
            string inputProductID = "";
            for (int i = 0; i < inputs.Length; i++)
            {
                if (inputs[i].Equals("ref", StringComparison.CurrentCultureIgnoreCase))
                    inputRef = inputs[i+2];
                if (inputs[i].Equals("dt", StringComparison.CurrentCultureIgnoreCase))
                    inputDate = inputs[i+2];
                if (inputs[i].Equals("productid", StringComparison.CurrentCultureIgnoreCase))
                    inputProductID = inputs[i+2];
            }

            Guid pid = new Guid(inputProductID);
            RivWorks.Data.Objects.rivProduct product = RivWorks.Data.rivProducts.GetProductById(pid);

            return product;
        }
    }

当我从我的localhost实例运行时,我得到了这个结果集:

  <ResultSet>
    <uiType>modal</uiType>
    <width>775</width>
    <height>600</height>
    <swfSource>
    http://localhost.rivworks.com/flash/negotiationPlayer.swf
    </swfSource>
    <buttonConfig>
    http://cdn1.rivworks.com/Element/Misc/734972de-40ae-45f3-9610-5331ddd6e8f8/apple-logo-2.jpg
    </buttonConfig>
  </ResultSet>

我缺少什么?


注意:我正在使用3.5框架(或者至少我认为我的web.config标记为3.5.0.0)


更新:我正在浏览该服务并使用该页面上的输入框。你可以在这里试试:http://dev.rivworks.com/services/Negotiate.asmx?op=GetSetup。我们还试图从在另一个站点上运行的基于JS的Web应用程序(此特定服务的主要目的)访问它。我这里没有代码。 (对不起,测试表只能从localhost获得。)


更新:我添加了以下测试页面(JsonTest.htm)以尝试查看来回的内容。我得到的只是500错误!我甚至试图加入这个过程并打破我的服务。在ASP管道进入我的代码之前,会抛出500错误。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Untitled Page</title>
    <script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.js" type="text/javascript"></script>

    <script language="javascript" type="text/javascript">
        function sendReq() {
            alert("Before AJAX call");
            $.ajax(
            {
                type: "POST"
                , url: "http://kab.rivworks.com/Services/Negotiate.asmx/GetSetup"
                , data: "{ \"ref\":\"http://www.rivworks.com/page.htm\", \"dt\":\"Mon Dec 14 2009 10:45:25 GMT-0700 (MST)\", \"productId\":\"5fea7947-251d-4779-85b7-36796edfe7a3\" }"
                , contentType: "application/json; charset=utf-8"
                , dataType: "json"
                , success: GetMessagesBack
                , error: Failure
            }
            );
            alert("After AJAX call");
        }
        function GetMessagesBack(data, textStatus) {
            alert(textStatus + "\n" + data);
        }
        function Failure(XMLHttpRequest, textStatus, errorThrown) {
            alert(textStatus + "\n" + errorThrown + "\n" + XMLHttpRequest);
        }
    </script>
</head>
<body>
    <div id="test">Bleh</div>
    <a href="javascript:sendReq()">Test it</a>
</body>
</html>

为什么这么痛苦?!?! :)


更新:通过WCF服务。这是我的设置: 接口:

namespace RivWorks.Web.Services
{
    [ServiceContract(Name = "Negotiater", Namespace = "http://www.rivworks.com/services")]
    public interface INegotiaterJSON
    {
        //[WebMethod]
        [OperationContract]
        [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        [ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
        ResultSet GetSetup(string jsonInput);
    }
}

类别:

namespace RivWorks.Web.Services
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class Negotiater : INegotiaterJSON
    {
        public ResultSet GetSetup(string jsonInput)
        {
            //code removed for brevity - see ASMX code above if you are really interested.
            return resultSet;
        }
    }


    [DataContract()]
    public class ResultSet
    {
        [DataMember]
        public string uiType = "modal";
        [DataMember]
        public int width = 775;
        [DataMember]
        public int height = 600;
        [DataMember]
        public string swfSource = "";
        [DataMember]
        public string buttonConfig = "";
    }
}

的web.config

  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name ="soapBinding">
          <security mode="None" />
        </binding>
      </basicHttpBinding>
      <webHttpBinding>
        <binding name="webBinding">
          <security mode="None" />
        </binding>
      </webHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="poxBehavior">
          <webHttp/>
        </behavior>
        <behavior name="jsonBehavior">
          <enableWebScript  />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="defaultBehavior">
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="RivWorks.Web.Services.Negotiater" behaviorConfiguration="defaultBehavior">
        <endpoint address="json"
                  binding="webHttpBinding"
                  bindingConfiguration="webBinding"
                  behaviorConfiguration="jsonBehavior"
                  contract="RivWorks.Web.Services.INegotiaterJSON" />
      </service>
    </services>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
      <baseAddressPrefixFilters>
        <add prefix="http://dev.rivworks.com" />
      </baseAddressPrefixFilters>
    </serviceHostingEnvironment>
  </system.serviceModel>

简单测试页

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Untitled Page</title>
    <script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.js" type="text/javascript"></script>

    <script language="javascript" type="text/javascript">
        function sendReq() {
            alert("Before AJAX call");
            $.ajax(
            {
                type: "POST"
                , url: "http://dev.rivworks.com/Services/Negotiater.svc/GetSetup"
                , data: "{ \"ref\":\"http://www.rivworks.com/page.htm\", \"dt\":\"Mon Dec 14 2009 10:45:25 GMT-0700 (MST)\", \"productId\":\"5fea7947-251d-4779-85b7-36796edfe7a3\" }"
                , contentType: "application/json; charset=utf-8"
                , dataType: "json"
                , success: GetMessagesBack
                , error: Failure
            }
            );
            alert("After AJAX call");
        }
        function GetMessagesBack(data, textStatus) {
            alert(textStatus + "\n" + data);
        }
        function Failure(XMLHttpRequest, textStatus, errorThrown) {
            alert(textStatus + "\n" + errorThrown + "\n" + XMLHttpRequest);
        }
    </script>

</head>
<body>
    <div id="test">Bleh</div>
    <!--<button onclick="javascript:sendReq()">TEST IT</button>-->
    <a href="javascript:sendReq()">Test it</a>
</body>
</html>

现在我收到了这个错误: IIS指定的身份验证方案“IntegratedWindowsAuthentication,Anonymous”,但绑定仅支持一种身份验证方案的规范。有效的身份验证方案是Digest,Negotiate,NTLM,Basic或Anonymous。更改IIS设置,以便仅使用单个身份验证方案。

我该如何处理? &lt; state emotion ='拧干'physical ='beat up'/&gt;

2 个答案:

答案 0 :(得分:8)

为什么不将ASMX Web服务迁移到WCF?

.NET Framework 3.5中的WCF API本身支持JSON Web服务。

此外,Microsoft将ASMX称为“遗留技术”,并建议“现在应使用Windows Communication Foundation(WCF)创建Web服务和XML Web服务客户端”。 (Source)。

您可以查看这些链接以开始使用:

此外,您可能还想阅读以下我从我自己托管的WCF项目中“提取”的示例。自托管WCF服务不需要IIS,但可以从任何托管的.NET应用程序提供。此示例托管在一个非常简单的 C#控制台应用程序

<强> IContract.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace MyFirstWCF
{
    [ServiceContract] 
    public interface IContract
    {
        [OperationContract]
        [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "/CustomerName/{CustomerID}")]
        string GET_CustomerName(string CustomerID);
    }
}

<强> Service.cs

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Syndication;
using System.ServiceModel.Web;

namespace MyFirstWCF
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.NotAllowed)]
    public class Service : IContract
    {
        public string GET_CustomerName(string CustomerID)
        {
            return "Customer Name: " + CustomerID;
        }
    }
}

WCFHost.cs (控制台应用程序)

using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Description;
using System.Threading;
using System.Text;

namespace MyFirstWCF
{
    class Program
    {
        private static WebServiceHost M_HostWeb = null;

        static void Main(string[] args)
        {
            M_HostWeb = new WebServiceHost(typeof(MyFirstWCF.Service));

            M_HostWeb.Open();

            Console.WriteLine("HOST OPEN");
            Console.ReadKey();

            M_HostWeb.Close();
        }
    }
}

<强>的app.config

<?xml version="1.0" encoding="utf-8" ?>

<configuration>
  <system.serviceModel>
    <services>
      <service name="MyFirstWCF.Service">

        <endpoint address="http://127.0.0.1:8000/api"
                  binding="webHttpBinding"
                  contract="MyFirstWCF.IContract" />

      </service>
    </services>

  </system.serviceModel>
</configuration>

以上示例非常基本。如果您使用Fiddlerhttp://127.0.0.1:8000/api/CustomerName/1000建立请求,则只会返回"Customer Name: 1000"

确保在请求标头中设置content-type: application/json。要返回更复杂的数据结构,您必须使用数据协定。这些构造如下:

[DataContract]
public class POSITION
{
    [DataMember]
    public int      AssetID { get; set; }

    [DataMember]
    public decimal  Latitude { get; set; }

    [DataMember]
    public decimal  Longitude { get; set; }
}

您需要将System.RuntimeSerializationSystem.ServiceModelSystem.ServiceModel.Web的.NET引用添加到此示例项目中进行编译。

答案 1 :(得分:3)

对方法的请求设置的“内容类型”是什么?

从我对ASP.NET所做的工作来看,如果设置为text/xml,你将获得XML;但如果它设置为application/json,你将获得JSON。