使用 jQuery 从 .NET 服务获取 JSON 数据:与 ajax 设置混淆

Posted

技术标签:

【中文标题】使用 jQuery 从 .NET 服务获取 JSON 数据:与 ajax 设置混淆【英文标题】:Get JSON data with jQuery from a .NET service: confused with ajax setup 【发布时间】:2011-08-07 03:31:46 【问题描述】:

我花了六个小时试图弄清楚这一点,但我没有成功。

我的本​​地计算机上有一个 HelloWorld .NET 3.5 Web 服务。 Set up as required. 该服务返回自定义结构的List

我正在尝试使用 jQuery 1.4.4 来使用它。

当我尝试执行the documentation 所说的操作时,我总是从服务返回一个 XML 响应,这会导致 jQuery 中的 parseerror 或作为哑字符串传递给 success 函数。 也就是说,但是我结合了 dataTypeaccepts(根据文档,控制如何处理接收到的数据),我得到了一个 XML。

但是,当我做一些不符合文档逻辑的事情时,我成功地获得了我的对象数组。 也就是说,当我忽略 dataTypeaccepts 并设置 contentType: "application/json; charset=utf-8" 时,它可以正常工作。 但是 contentType,根据文档,控制正在发送的数据 到服务器,没有收到。


在代码中:

$.ajax(
  
  type: "GET",
  url: "http://localhost:52624/Service1.asmx/HelloWorld",
  dataType: "json",
  //accepts can be anything, or it can be missing, doesn't matter, only depends on dataType
  success: function(data, textStatus, jqXHR) ...,
  error: function(jqXHR, textStatus, errorThrown) ...
  
)

结果:调用错误处理程序,textStatus = parseerror


$.ajax(
  
  type: "GET",
  url: "http://localhost:52624/Service1.asmx/HelloWorld",
  dataType: "application/json",
  //accepts can be anything, or it can be missing, doesn't matter, only depends on dataType
  success: function(data, textStatus, jqXHR) ...,
  error: function(jqXHR, textStatus, errorThrown) ...
  
)

结果:Web 服务返回 XML,它作为 string 传递给成功处理程序。


$.ajax(
  
  type: "GET",
  url: "http://localhost:52624/Service1.asmx/HelloWorld",
  accepts: "json",  // or "application/json"
  success: function(data, textStatus, jqXHR) ...,
  error: function(jqXHR, textStatus, errorThrown) ...
  
)

结果:Web 服务返回 XML,它被解析并作为 IXMLDOMDocument2 传递。


$.ajax(
  
  type: "GET",
  url: "http://localhost:52624/Service1.asmx/HelloWorld",
  contentType: "application/json; charset=utf-8",
  success: function(data, textStatus, jqXHR) ...,
  error: function(jqXHR, textStatus, errorThrown) ...
  
)

结果:Web 服务返回 JSON,它被 jQuery 部分解析(数字和字符串被解析为对象的属性,但日期仍为 "/Date(1303003305724)/" 的形式)。


问题:

    我了解 jQuery 规范吗?为什么说控制发送数据的参数实际上控制接收数据? 我做错了什么? 获取由 jQuery 解析的日期的最后一步是什么?

【问题讨论】:

Asmx web service how to return JSON and not XML?的可能重复 @StephenKennedy 这个问题在两年后出现,可以说包含的材料要少得多。如果有的话,您应该投票关闭 it 作为重复项。 我认为较新的版本更直接,对普通读者更有用,但我接受这是一个判断电话,其他人可能不同意:) 我撤回了我的投票,因为这个更关注 jQuery 而我今天正在看 javascriptSerializer 的东西。 【参考方案1】:

看来我要自己回答了。我并不是说以下是绝对真理。相反,这是我发现的工作。


首先找到三篇解释很多的文章:

Using jQuery to Consume ASP.NET JSON Web Services ASMX ScriptService mistake – Invalid JSON primitive 3 mistakes to avoid when using jQuery with ASP.NET AJAX

简而言之,.NET Web 服务的问题在于您必须以特殊方式调用它们:

使用 POST 请求(但见下文),以及 提供Content-Typeapplication/json; charset=utf-8

这是设计使然,出于安全原因。 后者可能无法避免,您必须提供该内容类型。由于内容类型确实决定了参数在请求中的编码方式,因此您必须将参数编码为 JSON。

这是 jQuery 介入的地方。jQuery 会无缘无故地忽略 contentType 并在 application/x-www-form-urlencoded 中编码您的参数。届时,Web 服务将不喜欢您说“这里是 JSON”并提供表单编码的内容。

在这些文章中,作者建议您通过将 JSON 数据括在另一对引号中来使用 jQuery,以便将其解释为字符串并且不会被 jQuery 处理:

$.ajax(
  type: "POST",
  url: "ServiceName.asmx/WebMethodName",
  data: "'fname':'dave','lname':'ward'",
  contentType: "application/json; charset=utf-8",
  dataType: "json",
  success: function(msg) ...
);

这确实有效。

另外,如果你没有任何数据,你仍然必须提供一个空的 JSON 对象,,因为如果你没有,jQuery 将不会设置Content-Length,并且没有Content-Length 的 web 服务会再次不喜欢你(更多安全原因)。


但是。 从 FW 3.5 开始,可以将 GET 与启用 JSON 的 .NET 服务一起使用。此时您可能想知道 JSON 编码的参数如何与 GET 请求保持一致。方法如下。

如果你的网络服务没有任何参数,调用很简单:

$.ajax(
  
    type: "GET",
    url: "ServiceName.asmx/WebMethodName",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(data, textStatus, jqXHR) ...
  
);

而且如果有参数,那么调用也很简单。你需要做的是在应该有它们的参数周围提供额外的引号!这是因为您希望这些引号作为表单编码请求的一部分出现。这样,表单编码的请求看起来有点像 json 编码的请求:

$.ajax(
  
    type: "GET",
    url: "ServiceName.asmx/WebMethodName",
    contentType: "application/json; charset=utf-8",
    data: DatePlaced:'"2011-05-13"',
    dataType: "json",
    success: function(data, textStatus, jqXHR) ...
  
);

此请求将产生类似于以下内容的请求:

GET /ServiceName.asmx/WebMethodName?DatePlaced="2011-05-13" HTTP/1.1 内容类型:应用程序/json;字符集=utf-8

注意类似 JSON 的 GET 请求所需的引号,但如果您要请求 XML,则会导致错误。

【讨论】:

【参考方案2】:

当发布到 asp.net 网络服务时,您总是必须将内容类型设置为 - 这是他们防止 json 劫持的方式。

关于日期,最简单的解决方案是将日期作为字符串返回,在客户端处理日期类型将是一个巨大的 PITA(至少根据我的经验)。

【讨论】:

【参考方案3】:

我认为你不了解 jQuery 规范:(Specs)

数据类型

默认:智能 猜测(xml、json、脚本或 html

您期望的数据类型 从服务器返回。如果没有 指定,jQuery 将尝试推断它 基于响应的 MIME 类型...

现在。看看你的各种情况。

案例 1:数据类型:“json”。

你收到“xml”但声明“json”=>你得到一个解析错误,因为你不能像 json 一样解析 xml。

案例 2:数据类型:“application/json”。

"application/json" 不是有效的数据类型,所以 jQuery 默认为字符串。

案例 3:无数据类型。

jQuery 做出了最好的猜测,在你的情况下结果很好。

案例 4:contentType: "application/json; charset=utf-8"

您要求 json 数据,但您没有指定数据类型。在这种情况下,您很幸运 Web 服务确实返回了 json 数据,并且 jQuery 正确猜测数据是 json 格式。

关于日期格式,你想看看:

How do I format a Microsoft JSON date?

【讨论】:

是的,我意识到这一点。我确实认为dataType 是从服务器请求特定的数据格式,而我现在意识到它只是告诉jQuery 会得到什么结果。让我感到困惑的是,为什么指示 Web 服务返回 json(而不是 xml)的唯一方法是设置 contentType,根据文档,这是为了不同的目的? @Greg:这将取决于 web 服务,而不是 jQuery。 contentType 并非用于此目的,但它是发送到 Web 服务的消息的一部分。 webservice 接收它并决定做任何它想做的事情,不管它在 jQuery 中的预期目的。 那是 GSerg,不是 Greg,所以我没有收到通知 :) 好吧,让我继续。使用 .NET Web 服务时,如果您在参数中提供 json 数据,则只能获取 json 数据(因为这首先是 contentType 的用途——它的 json-summoning 副作用不会取消它所描述的事实发送到服务器的参数格式)。所以我没有application/x-www-form-urlencoded了。但是 jQuery 会以某种方式处理这个问题。正确的?而且,鉴于这种情况,我可以使用 GET 吗?我认为 json 编码的参数需要 POST。

以上是关于使用 jQuery 从 .NET 服务获取 JSON 数据:与 ajax 设置混淆的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jQuery 和 ASP.NET MVC 从 AJAX 调用返回错误消息?

如何使用jQuery调用带有参数的asp.net asmx web服务来获取响应

如何使用 jQuery 调用 ASP.NET Web 服务?

使用 JQuery 从外部源获取 XML

如何使用 ASP.NET 从 MSSQL 中获取 JQuery 自动完成小部件的数据

如何使用 jquery 从 asp.net 列表框中仅获取当前选定的选项