jsonを返すMono3.0.3.5を使用してWebサービスを作成しようとしています。
しかし、これまでのところ、xml以外のものを返すサービスを取得することはできませんでした。これは過去に多くの議論の的となったようですが、ここや他の場所で多くのリソースに対して私の試みをチェックした後でも、私が何を省略しているのかわかりません。
空のASP.NETソリューションを作成し、それにコードビハインドページを含むasmxを追加しました。私の知る限り、サービスクラス名をScriptService属性で装飾し、メソッド/関数名をScriptMethodで装飾し、ResponseFormat属性にJsonを指定することが、コードで必要な唯一の手順です。
using System;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;
namespace MonoJsonTest
{
[WebService]
[ScriptService]
public class GimmeJson : System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod(ResponseFormat=ResponseFormat.Json)]
public string simpleTestString()
{
return DateTime.Now.ToString();
}
}
}
(jsonに日付を入れる際の問題を認識しています。その後のサービスの呼び出しで変更される文字列が必要でした)
次に、System.Web.Extensionsをプロジェクトの参照に追加しました。これは.NETバージョン3.5に基づいて構築されているため、3.5バージョンのSystem.Web.Extensionsが含まれていることを確認しました。
次に、web.configのhttpHandlersが、ScriptHandlerFactoryを通過するように変更されました(私が見つけたいくつかのページで概説されています)。
http://vampirebasic.blogspot.com/2009/04/aspnet-ajax-in-mono.html
http://encosia.com/asmx-scriptservice-mistakes-installation-and-configuration/
鋭い目は、2つのページで指定されたweb.configの変更に違いがあることに気付くかもしれません。「Culture=neutral」属性は、最初のページのtype属性の文字列内で指定されますが、2番目のページのaddタグの属性として指定されます。しかし、2番目の方法で指定すると、サービスの開始時にエラーが発生することがわかりました。
私の最後のweb.config:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation defaultLanguage="C#" debug="true">
<assemblies>
<add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</assemblies>
</compilation>
<customErrors mode="RemoteOnly">
</customErrors>
<authentication mode="None">
</authentication>
<authorization>
<allow users="*" />
</authorization>
<httpHandlers>
<!-- should produce json responses -->
<remove verb="*" path="*.asmx" />
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</httpHandlers>
<trace enabled="false" localOnly="true" pageOutput="false" requestLimit="10" traceMode="SortByTime" />
<sessionState mode="InProc" cookieless="false" timeout="20" />
<globalization requestEncoding="utf-8" responseEncoding="utf-8" />
<pages>
</pages>
</system.web>
</configuration>
ただし、WSDLページから(ローカルで)サービスをヒットするか、(JQueryライブラリを使用して)javascriptからajaxクエリを使用すると、常にXMLが返されます。CharlesとFirefoxの両方のデバッグツールを使用して応答ヘッダーを調べると、応答タイプがtext/xmlであることがわかります。
調査の結果、呼び出し時にサービスにjsonをリクエストする必要があるようだったので、ajax呼び出しのcontentType、accepts、dataTypeパラメーターを設定してjsonを指定しましたが、違いはありませんでした。不思議なことに、リクエストヘッダーでさえ、Ajax呼び出しで明示的に設定した後でも、「Accepts」パラメーターがまだxmlを指定していることを示しています。
これがajax呼び出しです(受け入れ、dataTypeタイプがjsonに設定されていることに注意してください):
$.ajax({
url: "http://localhost:8080/GimmeJson.asmx/simpleTestString",
type: "POST",
contentType: "application/json; charset=utf-8",
accepts: "application/json; charset=utf-8",
data: "{}",
dataType: "json",
success: function (data, textStatus, jqXHR) { console.log( "success" ); alert.show("success"); },
error: function(request, type, errorThrown) { console.log( "error" ); }
});
その呼び出しによって生成されたリクエストヘッダーは次のとおりです(Acceptは引き続きxmlです)。
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding:gzip,deflate
Accept-Language:en-us,en;q=0.5
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Cache-Control:no-cache
Host:localhost:8080
Origin:null
Pragma:no-cache
Proxy-Connection:keep-alive
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:14.0) Gecko/20100101 Firefox/14.0.1
これにより、200のHTTPコードが生成され、この応答ヘッダー(コンテンツタイプはxmlであることに注意してください):
Cache-Control:private
Content-Length:103
Content-Type:text/xml; charset=utf-8
Date:Thu, 09 Aug 2012 23:38:59 GMT
Keep-Alive:timeout=15, max=100
Proxy-Connection:Keep-alive
Server:Mono.WebServer2/0.2.0.0
UnixX-AspNet-Version:2.0.50727
よくわからないことに気づいたのは、重要なポイントですが、奇妙に思えます。MonoでSystem.Web.Extensionsdllを参照しましたが、ScriptHandlerFactoryがその中に存在していないように見えました。ファクトリを追加するweb.configの行を変更して、タイプとして「FOOScriptHandlerFactory」を指定しても、サービスの開始時にエラーは発生しませんでした。これは、Monoがweb.configで見つからないタイプを報告していないことを示しているようです。しかし、私は.NetやMonoのその側面について、確かにそれを言うのに十分なことを知りません。ただし、このファクトリはJsonの自動シリアル化の要であるため、これは重要な場合があります。
ここで何を省略しているのかわかりません。サーバー側で何かを正しく構成していないように感じます。そうしないと、WSDLページのどこかにリターンタイプのjsonが報告されます。ご想像のとおり、私はまだオンライン開発に慣れていないので、非常に明白なことを見落としている場合はお詫び申し上げます。