2009-12-14 7 views
5

Tôi sẽ đến đây. Tôi đã nhìn vào các mục sau đây và none trong số họ đang điều chỉnh các hành vi khác thường tôi nhìn thấy:.NET ASMX - Trả lại JSON thuần túy?

Tôi cũng đã xem xét và đã xác nhận thiết lập của tôi: http://www.asp.net/AJAX/documentation/live/ConfiguringASPNETAJAX.aspx

Đây là mã của tôi (mã ASMX đằng sau):

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; 
     } 
    } 

Khi tôi chạy này từ dụ localhost của tôi Tôi nhận này tập kết quả:

<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> 

tôi thiếu gì ???


Chú ý: Tôi đang sử dụng framework 3.5 (hoặc ít nhất tôi nghĩ rằng tôi là như tất cả mọi thứ trong web.config của tôi được đánh dấu cho 3.5.0.0)


UPDATE: Tôi đang duyệt tới dịch vụ và sử dụng hộp nhập liệu trên trang đó. Bạn có thể thử tại đây: http://dev.rivworks.com/services/Negotiate.asmx?op=GetSetup. Chúng tôi cũng đang cố gắng truy cập nó từ một ứng dụng web dựa trên JS chạy trên một trang web khác (mục đích chính của dịch vụ cụ thể này). Tôi không có mã cho điều đó ở đây. (Xin lỗi, hình thức kiểm tra chỉ có sẵn từ localhost.)


UPDATE: Tôi được thêm vào trang kiểm tra sau (JsonTest.htm) để thử để xem những gì đang xảy ra qua lại. Tất cả tôi nhận được là một lỗi 500! Tôi thậm chí đã cố gắng gắn vào quá trình và đột nhập vào dịch vụ của tôi. Lỗi 500 được ném trước khi đường ống ASP bao giờ được đưa vào mã của tôi.

<!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> 

Tại sao điều này cực kỳ khó khăn?!?! :)


CẬP NHẬT: Làm việc qua dịch vụ WCF. Đây là thiết lập của tôi: Interface:

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); 
    } 
} 

Class:

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.cấu hình

<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> 

trang kiểm tra đơn giản

<!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> 

Và bây giờ tôi đang nhận được lỗi này: IIS 'IntegratedWindowsAuthentication, Anonymous' lược đồ xác thực cụ thể, nhưng các ràng buộc chỉ hỗ trợ đặc tả chính xác một lược đồ xác thực. Các lược đồ xác thực hợp lệ là Digest, Negotiate, NTLM, Basic hoặc Anonymous. Thay đổi các thiết lập IIS để chỉ có một lược đồ xác thực duy nhất được sử dụng.

Làm cách nào để xử lý việc này? < trạng thái cảm xúc = 'wrung out' physical = 'beat up'/>

+0

Bạn có thể đăng mã bạn đang sử dụng để gọi dịch vụ không? –

+0

Keith, về bản cập nhật mới nhất của bạn, tại sao bạn không thử tự lưu trữ ứng dụng WCF của bạn chỉ để thử nghiệm? Nó sẽ đưa IIS ra khỏi phương trình. Tự lưu trữ với ứng dụng Console rất dễ dàng. (kiểm tra WCFHost.cs trong câu trả lời của tôi). –

+0

Đã khắc phục sự cố IIS bằng cách thả bảo mật Tích hợp (mà chúng tôi không sử dụng anyways). Bây giờ nhận được một lỗi 500 trên SVC. --- Chuyển đổi từ một máy chủ tự lưu trữ sang một máy chủ lưu trữ web không phải là một vấn đề lớn? Chúng tôi có mgmt muốn điều này và chạy tuần trước. "Chỉ mất 10 phút". Có lẽ tôi đang "bên trong" vấn đề bây giờ. –

Trả lời

8

Tại sao bạn không chuyển dịch vụ web ASMX sang WCF?

API WCF trong .NET Framework 3.5 hỗ trợ các dịch vụ web JSON nguyên bản.

Ngoài ra, Microsoft đã tuyên bố ASMX là "công nghệ kế thừa" và đề xuất "Các dịch vụ web và máy khách dịch vụ Web XML bây giờ sẽ được tạo bằng cách sử dụng Windows Communication Foundation (WCF)". (Source).

Bạn có thể muốn kiểm tra những liên kết này để bắt đầu:

Ngoài ra, bạn cũng có thể muốn đọc qua ví dụ sau đây mà tôi "trích xuất" từ một dự án WCF tự lưu trữ của tôi. Các dịch vụ WCF tự lưu trữ không yêu cầu IIS, nhưng có thể được phục vụ từ bất kỳ ứng dụng .NET được quản lý nào. Ví dụ này đang được lưu trữ trong một rất đơn giản C# Console Application:

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 (Bảng điều khiển Ứng dụng)

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> 

Ví dụ trên là rất cơ bản. Nếu bạn xây dựng một yêu cầu với Fiddler đến http://127.0.0.1:8000/api/CustomerName/1000, nó sẽ đơn giản trả lại "Customer Name: 1000".

Đảm bảo đặt content-type: application/json trong tiêu đề yêu cầu. Để trả về các cấu trúc dữ liệu phức tạp hơn, bạn sẽ phải sử dụng các Hợp đồng Dữ liệu. Đây là những tạo như sau:

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

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

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

Bạn cần phải thêm .NET Tài liệu tham khảo để System.RuntimeSerialization, System.ServiceModelSystem.ServiceModel.Web ví dụ dự án này để biên dịch.

+0

Hmmm. Có vẻ một cái gì đó là FUBAR trên máy tính của tôi. Tôi không có tùy chọn tạo Dịch vụ AJAX WFC. Có điều gì tôi nên cài đặt trên đầu trang của VS2008? –

+0

Bạn chỉ có thể tạo một dịch vụ WCF bình thường; bạn có thể trang trí giao diện của bạn với các thuộc tính để chỉ ra rằng ResponseFormat sẽ là JSON. –

+0

Tôi không có tùy chọn để tạo * bất kỳ dịch vụ WCF nào. http://screencast.com/t/OGQwMDlk –

3

"Loại nội dung" được đặt theo yêu cầu cho phương pháp này là gì?

Từ những gì tôi đã thực hiện với ASP.NET, nếu được đặt thành text/xml, bạn sẽ lấy lại XML; nhưng nếu được đặt thành application/json, bạn sẽ nhận lại JSON.

+0

application/json in JS. Lưu ý: JS không có trên các trang của chúng tôi! WS cần đáp ứng yêu cầu JS nước ngoài. –

+0

Tôi nghĩ rằng vấn đề là nó sẽ trả về phản hồi theo kiểu được yêu cầu, có vẻ là 'text/xml' trong ví dụ của bạn. Thậm chí nếu nó không phải là yêu cầu từ nội dung bạn viết, bạn có thể dễ dàng viết một tập lệnh JS nhỏ của riêng mình để kiểm tra nó bằng 'application/json' –

+0

Loại nội dung rất quan trọng. Cảm ơn! –