我正在尝试使用返回 json 的 Mono 3.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 版构建的,因此我确保包含了 System.Web.Extensions 的 3.5 版。
然后 web.config 的 httpHandlers 被修改为通过 ScriptHandlerFactory (如我发现的几页所述)
http://vampirebasic.blogspot.com/2009/04/aspnet-ajax-in-mono.html
http://encosia.com/asmx-scriptservice-mistakes-installation-and-configuration/
敏锐的眼睛可能会注意到两个页面上指定的 web.config 更改存在差异。“Culture=neutral”属性在第一页的 type 属性的字符串内部指定,但在第二页作为 add 标记的属性。但是我发现当指定第二种方式时,启动服务时出现错误。
我的最终 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 页面或使用来自 javascript 的 ajax 查询(使用 JQuery 库)访问服务(本地),它总是返回 XML。使用 Charles 和 Firefox 调试工具检查响应标头向我显示了 text/xml 的响应类型。
经研究,调用时似乎需要向服务请求json,所以我设置了ajax调用的contentType、accept和dataType参数来指定json,但这并没有什么区别。奇怪的是,即使请求标头显示“Accepts”参数在我在 Ajax 调用中明确设置后仍然指定 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.Extensions dll,发现其中似乎不存在 ScriptHandlerFactory。修改 web.config 中添加工厂的行以指定“FOOScriptHandlerFactory”作为类型在启动服务时没有产生任何错误,这似乎表明 Mono 没有在 web.config 中报告未找到的类型。但我对 .Net 和 Mono 的这方面了解不够,无法肯定地说。但由于这个工厂是自动 Json 序列化的关键,这可能很重要。
我不确定我在这里省略了什么。我觉得我没有在服务器端正确配置一些东西,或者它会在 WSDL 页面上的某处报告返回类型的 json。正如您可能已经猜到的那样,我还是在线开发的新手,所以如果我忽略了非常明显的事情,我深表歉意。