如何在 c# ASP.Net 中使用有效的 JSON 输出创建 JSON WebService 并使用 JQuery/Ajax 进行查询

Posted

技术标签:

【中文标题】如何在 c# ASP.Net 中使用有效的 JSON 输出创建 JSON WebService 并使用 JQuery/Ajax 进行查询【英文标题】:How to create a JSON WebService in c# ASP.Net with a valid JSON output and query with JQuery/Ajax 【发布时间】:2013-08-13 01:43:59 【问题描述】:

我创建了一个 c# ASP.Net JSON WebService。但是我在从这个 WebService 读取数据时遇到了很大的麻烦,因为在我看来,输出不是有效的 JSON 格式?

通常你应该得到一个 [object, object] 作为数据返回。但我得到 [对象,文件] 我做错了什么或我错过了什么?

我当前的输出如下所示:

<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">
  "Email": "james@example.com",
  "Active": true,
  "CreatedDate": "2013-01-20T00:00:00Z",
  "Roles": [
    "User",
    "Admin"
  ]
</string>

这是我的 JQuery-Ajax 调用:

$.ajax(
   type: "GET",
   //dataType: "json", <-- When I uncomment this line the request fails :(
   url: "http://webservices.domain.local/service.asmx/getData?name=",

   success: function(data)
      console.log(data); // Output is: [object Document] instead of [object, object]
   ,
   error: function(XMLHttpRequest, textStatus, errorThrown)

   
);

这是来自我的 WebService 的代码:

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Runtime.Serialization;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.Script.Services;
using System.Web.Services;
using Newtonsoft.Json;

namespace DataWebService

    /// <summary>
    /// Summary description for Service1
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    [System.Web.Script.Services.ScriptService]
    public class SPServices : System.Web.Services.WebService
    
        [WebMethod]
        [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
        public string getData(string name)
        
            Account account = new Account
            
                Email = "james@example.com",
                Active = true,
                CreatedDate = new DateTime(2013, 1, 20, 0, 0, 0, DateTimeKind.Utc),
                Roles = new List<string>
                  
                    "User",
                    "Admin"
                  
            ;
            return JsonConvert.SerializeObject(account, Formatting.Indented);
        
    

    public class Account
    
        public string Email  get; set; 
        public bool Active  get; set; 
        public DateTime CreatedDate  get; set; 
        public IList<string> Roles  get; set; 
    

WebConfig 文件:

<?xml version="1.0"?>
<configuration>
    <configSections>
      <!--<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
        <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
          <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
          <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
            <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere" />
            <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
            <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
            <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
          </sectionGroup>
        </sectionGroup>
      </sectionGroup>-->
    </configSections>  
    <appSettings/>
    <connectionStrings/>
    <system.web>
      <webServices>
        <protocols>
          <add name="HttpGet"/>
          <add name="HttpPost"/>
        </protocols>
      </webServices>
        <compilation debug="true" >
          <assemblies>
            <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
            <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
          </assemblies>
        </compilation>
    <!--
      The <authentication> section enables configuration 
      of the security authentication mode used by 
      ASP.NET to identify an incoming user. 
    -->
    <authentication mode="Windows" />
    <!--
       The <customErrors> section enables configuration 
       of what to do if/when an unhandled error occurs 
       during the execution of a request. Specifically, 
       it enables developers to configure html error pages 
       to be displayed in place of a error stack trace.

       <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
         <error statusCode="403" redirect="NoAccess.htm" />
         <error statusCode="404" redirect="FileNotFound.htm" />
       </customErrors>
    -->
      <pages>
        <controls>
          <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        </controls>
      </pages>

      <httpHandlers>
        <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"/>
        <!--<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>-->
      </httpHandlers>
      <httpModules>
        <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </httpModules>
    </system.web>
    <system.codedom>
      <compilers>
        <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4"
                  type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <providerOption name="CompilerVersion" value="v3.5"/>
          <providerOption name="WarnAsError" value="false"/>
        </compiler>
      </compilers>
    </system.codedom>
    <!-- 
        The system.webServer section is required for running ASP.NET AJAX under Internet
        Information Services 7.0.  It is not necessary for previous version of IIS.
    -->
    <system.webServer>
      <validation validateIntegratedModeConfiguration="false"/>
      <modules>
        <remove name="ScriptModule" />
        <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </modules>
      <handlers>
        <remove name="WebServiceHandlerFactory-Integrated"/>
        <remove name="ScriptHandlerFactory" />
        <remove name="ScriptHandlerFactoryAppServices" />
        <remove name="ScriptResource" />
        <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode"
             type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode"
             type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </handlers>
      <httpProtocol>
        <customHeaders>
          <add name="Access-Control-Allow-Origin" value="*" />
          <add name="Access-Control-Allow-Headers" value="Content-Type" />
        </customHeaders>
      </httpProtocol>
    </system.webServer>
    <runtime>
      <assemblyBinding appliesTo="v2.0.50727" xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
          <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
          <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
        </dependentAssembly>
        <dependentAssembly>
          <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>
          <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
        </dependentAssembly>
      </assemblyBinding>
    </runtime>
</configuration>

如果有人可以帮助我,我会非常高兴...我整个周末都在做这个,但我找不到解决方案...:-(

【问题讨论】:

如果内容是 xml,则默认创建 XML 而不是 JSON 和 ajax,它会创建 xml 文档。 为什么要创建插入 JSON 的 XML?在我的 WebService 中,我定义了返回值应该是 JSON,并且我还尝试使用 JSON 库...知道如何将输出更改为 JSON 吗? 之前好像有人回答过这个问题:***.com/questions/5300855/… @JoeBrunscheon 我不认为,如果我尝试使用:return new javascriptSerializer().Serialize(new errMsg = "test" ); 我仍然返回错误的格式...还有什么想法吗? 【参考方案1】:

添加以下使用:

using System.Web.Mvc;

并将您的方法更改为:

[WebMethod]
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public JsonResult getData(string name)
        
            Account account = new Account
            
                Email = "james@example.com",
                Active = true,
                CreatedDate = new DateTime(2013, 1, 20, 0, 0, 0, DateTimeKind.Utc),
                Roles = new List<string>
                  
                    "User",
                    "Admin"
                  
            ;
            return Json(account);
        

我认为它会像这样工作

【讨论】:

【参考方案2】:

尝试使用 ASP.net web-api(MVC 4 的一部分)作为您的核心项目。当控制器操作返回一个对象时,它将根据请求自动序列化为 xml 或 json。那是您的浏览器需要一个,而服务提供。

他们甚至淘汰了用于 JSON 的旧 MS 库,并用 newtonsoft 替换它。这意味着有些场景是支持json序列化而不是xml序列化的。如果需要这些功能,可以去掉默认的 xml-serializer,只支持 json。

祝你好运! :)

【讨论】:

mh...我想我不太明白您的意思...也许您可以用更多细节来描述它,以便我找到正确的方向? (或者可能是一些链接?) 我的意思主要是asp.net/web-api,这是谷歌上第一次点击asp.net web-api。它应该告诉你你需要知道的一切。主要是我认为您通过选择一种较旧的更通用的技术而不是一种较新的更简化的技术来使自己的事情复杂化。因此,我为您指明了一项技术的方向,该技术应该让您的生活更轻松。但是,我不会为您完成全部工作。 :) 关于 newtonsoft 的事情是我提到的,因为您已将它包含在您的 Web 服务中。我一直在这条路上,它很乱。尝试更新的技术。 ;)

以上是关于如何在 c# ASP.Net 中使用有效的 JSON 输出创建 JSON WebService 并使用 JQuery/Ajax 进行查询的主要内容,如果未能解决你的问题,请参考以下文章

如何正确 URL 重写图像? C# ASP.NET

在 ASP.Net 网站项目中混合 VB.Net 和 C# 代码?

ASP.NET MVC / C#:如何从 url 中删除记录 id?

如何在asp.net c# web应用程序中使用asp.net vb页面

如何使用 C# 在 ASP.NET 中使用 MySql 数据库 [重复]

如何使用 c# 在 asp.net 中隐藏和显示警报