.NET ASMX - 返回纯JSON?

Kei*_*ows 5 .net wcf json web-services asmx

我在这里疯了.我查看了以下条目,但没有一个能纠正我看到的异常行为:

我也看过了,并确认了我的设置: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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

当我从我的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>
Run Code Online (Sandbox Code Playgroud)

我错过了什么?


注意:我正在使用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>
Run Code Online (Sandbox Code Playgroud)

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


更新:通过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);
    }
}
Run Code Online (Sandbox Code Playgroud)

类:

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 = "";
    }
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

简单的测试页面

<!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>
Run Code Online (Sandbox Code Playgroud)

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

我该如何处理?<state emotion ='拧干'physical ='beat up'/>

Dan*_*llo 8

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

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

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

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

此外,您可能还想阅读以下示例,该示例是我从我自己托管的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

的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>
Run Code Online (Sandbox Code Playgroud)

上面的例子非常基本.如果你建立一个请求提琴手http://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; }
}
Run Code Online (Sandbox Code Playgroud)

您需要添加.NET引用System.RuntimeSerialization,System.ServiceModelSystem.ServiceModel.Web为此示例项目进行编译.