2009-12-14 14 views
5

Oszalałem tutaj. Szukałem w następujących zapisów i żaden z nich korekty nieprawidłowej zachowanie widzę:.NET ASMX - powracający czysty JSON?

Ja również wyglądał na i potwierdziłem moją konfigurację: http://www.asp.net/AJAX/documentation/live/ConfiguringASPNETAJAX.aspx

Oto mój kod (kod ASMX tył):

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

Kiedy uruchomić ten przykład z mojego localhost otrzymuję ten zestaw wyników:

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

Czego mi brakuje ???


UWAGA: Używam 3.5 Framework (lub przynajmniej Myślałem, że jak wszystko w moim web.config jest oznaczony do 3.5.0.0)


UPDATE: Ja do przeglądania usługę i korzystanie z pola wprowadzania na tej stronie. Możesz spróbować tutaj: http://dev.rivworks.com/services/Negotiate.asmx?op=GetSetup. Próbujemy również uzyskać do niego dostęp z aplikacji internetowej opartej na JS działającej w innej witrynie (głównym celem tej konkretnej usługi). Nie mam tutaj tego kodu. (Niestety, forma testu jest dostępna tylko z localhost.)


UPDATE: I dodaje następującą stronę testową (JsonTest.htm), aby spróbować zobaczyć, co się tam iz powrotem. Mam tylko 500 błędów! Próbowałem nawet dołączyć do procesu i włamać się do mojej służby. 500 błędów jest zgłaszanych, zanim potok ASP dostanie się do mojego kodu.

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

Dlaczego jest to tak boleśnie trudne?!?! :)


AKTUALIZACJA: Praca za pośrednictwem usługi WCF. Oto moja konfiguracja: Interfejs:

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

Klasa:

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

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

prosta strona testowa

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

A teraz ja dostaję ten błąd: IIS 'IntegratedWindowsAuthentication, anonimowy' określonych schematów uwierzytelniania, ale wiązanie obsługuje tylko specyfikację dokładnie jeden schemat uwierzytelniania. Prawidłowe schematy uwierzytelniania to Digest, Negotiate, NTLM, Basic lub Anonim. Zmień ustawienia IIS tak, aby używany był tylko jeden schemat uwierzytelniania.

Jak sobie z tym poradzić? < stan emocji = „wykręconą” fizyczny = „bić”/>

+0

Czy możesz opublikować kod, którego używasz do wywołania usługi? –

+0

Keith, jeśli chodzi o twoją najnowszą aktualizację, dlaczego nie spróbujesz samodzielnie hostować aplikacji WCF tylko do testowania? To wyjmie IIS z równania. Samodzielny hosting za pomocą aplikacji Console jest bardzo łatwy. (sprawdź w moim odpowiedzi WCFHost.cs). –

+0

Naprawiono problem IIS przez zrzucenie Zintegrowanego zabezpieczenia (którego w ogóle nie używaliśmy). Teraz otrzymuję błąd 500 na SVC. --- Konwersja z hostingu na hostowaną stronę to nic wielkiego? Mamy mgmt, które chce tego i działa w zeszłym tygodniu. "Powinno to zająć 10 minut". Być może mam teraz "w środku" problemu. –

Odpowiedz

8

Dlaczego nie można migrować do ASMX usługa WCF?

Interfejs API WCF w programie .NET Framework 3.5 obsługuje usługi WWW JSON natywnie.

Ponadto firma Microsoft oświadczyła, że ​​ASMX jest "starszą technologią", i sugeruje, że "Usługi internetowe i klienci usług sieci Web XML powinni teraz zostać utworzeni za pomocą Windows Communication Foundation (WCF)". (Source).

Możesz sprawdzić te linki, aby zacząć:

Ponadto możesz również przeczytać poniższy przykład, który "wyodrębniłem" z samodzielnie hostowanego projektu WCF. Samohostowane usługi WCF nie wymagają usług IIS, ale mogą być obsługiwane z dowolnej zarządzanej aplikacji .NET. Przykład ten jest organizowany w bardzo prosty C# aplikacji konsoli:

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 (Console Aplikacja)

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> 

Powyższy przykład jest bardzo proste. Jeśli zbudujesz żądanie z Fiddler na http://127.0.0.1:8000/api/CustomerName/1000, po prostu zwróci on "Customer Name: 1000".

Upewnij się, że ustawiono content-type: application/json w nagłówku żądania. Aby zwrócić bardziej złożone struktury danych, będziesz musiał użyć umów danych. Są one skonstruowane w następujący sposób:

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

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

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

Trzeba dodać .NET Odwołania do System.RuntimeSerialization, System.ServiceModel i System.ServiceModel.Web dla tego przykładu projektu skompilować.

+0

Hmmm. Wydaje się, że coś jest FUBAR na mojej maszynie. Nie mam opcji utworzenia usługi AJAX WFC. Czy jest coś, co powinienem zainstalować na VS2008? –

+0

Możesz po prostu utworzyć normalną usługę WCF; możesz udekorować interfejs za pomocą atrybutów, aby wskazać, że ResponseFormat będzie JSON. –

+0

Nie mam opcji do tworzenia * dowolnej * usługi WCF. http://screencast.com/t/OGQwMDlk –

3

Co to jest "Typ zawartości" na żądanie do metody?

Z tego, co zrobiłem z ASP.NET, jeśli jest ustawiony na text/xml, otrzymasz zwrot XML; ale jeśli jest ustawiony na application/json, odzyskasz JSON.

+0

application/json w JS. Uwaga: JS nie ma na naszych stronach! WS musi odpowiedzieć na obce żądanie JS. –

+0

myślę, że chodzi o to, że powróci odpowiedź w rodzaju, który jest przedmiotem wniosku, który wydaje się być „text/xml” w przykładzie. Nawet jeśli nie jest to prośba z czymś, co napisał, można łatwo napisać mały skrypt JS własnych w celu przetestowania go „application/json” –

+0

typu treści jest bardzo ważne. Dzięki! –

Powiązane problemy