如何通过 Jquery 调用 C# WCF 服务来修复“ERR_ABORTED 400 (Bad Request)”错误?

Posted

技术标签:

【中文标题】如何通过 Jquery 调用 C# WCF 服务来修复“ERR_ABORTED 400 (Bad Request)”错误?【英文标题】:How to fix "ERR_ABORTED 400 (Bad Request)" error with Jquery call to C# WCF service? 【发布时间】:2019-11-14 07:52:07 【问题描述】:

我创建了一个简单的 C# WCF 服务,它返回一个带有 html 代码的字符串。当我在 WCF 解决方案中通过一个简单的 MVC 项目使用此服务时,一切正常。

服务代码
    public class ConnectorService : IConnectorService
    
        public string GetData()
        
            return "<a href='www.test.com.br'>test</a>";
        
    
接口代码
    [ServiceContract]
    public interface IConnectorService
    
        [OperationContract]
        string GetData();
    

在此测试之后,我在本地 IIS 中发布了此服务,并尝试使用不在 WCF 解决方案中但位于服务的同一 IIS 目录中的 html 页面来使用此服务。

HTML 代码
    <html>
        <head>
        <title>test</title>
        <script src='Scripts/jquery-3.3.1.min.js'></script>
        </head>
    <body>
        <div id='divContent'></div>
    </body>
    </html>

    <script type='text/javascript'>
        $(document).ready(function () 

            $.ajax(
                url: 'http://localhost/ConnectorService.svc/GetData',
                contentType: 'application/json; charset=utf-8',
                type: "GET",
                dataType: 'jsonp',
            success: function (data) 
                $('#divContent').html(data); 
            ,
            error: function (error) 
                alert("error:  status - " + error.status + " | text: " + error.statusText);
            
        );

    );
    </script>

当我在浏览器上打开这个 html 文件时,出现 2 个错误:

1) CORS 政策 - 我用这样的 global.asax 文件修复了这个问题

protected void Application_BeginRequest(object sender, EventArgs e)
    
        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        
            HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
            HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
            HttpContext.Current.Response.End();
        
    

2) 错误 400 - 错误请求 我尝试了几种堆栈溢出的解决方案,通常会更改我的 ajax 调用、global.asax 和 web.config 文件,但我总是在 chrome 控制台中收到错误的请求错误。

web.config 代码
        <?xml version="1.0"?>
    <configuration>

      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.7.2" />
        <httpRuntime targetFramework="4.7.2"/>
      </system.web>
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior>
              <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
              <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <protocolMapping>
          <add binding="basicHttpsBinding" scheme="https" />
        </protocolMapping>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
      <system.webServer>

        <httpProtocol>
          <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*" />
            <add name="Access-Control-Allow-Credentials" value="true" />
            <add name="Access-Control-Allow-Headers" value="Content-Type,Accept" />
            <add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
          </customHeaders>
        </httpProtocol>

        <modules runAllManagedModulesForAllRequests="true"/>
        <!--
            To browse web app root directory during debugging, set the value below to true.
            Set to false before deployment to avoid disclosing web app folder information.
          -->
        <directoryBrowse enabled="true"/>
      </system.webServer>

    </configuration>

我相信这是一个简单的解决方案,但是经过几天的测试,我觉得我在追逐自己的尾巴。有人能指出我的解决方案吗?

提前致谢。

【问题讨论】:

控制器代码在哪里?它甚至被击中了吗?你试过调试吗? @Austin T French,正如我所说,在我的 MVC 代码中一切正常,问题是当我在 IIS 上发布我的服务并尝试使用独立于我的 MVC 项目的 html 文件访问它时。在这种情况下,没有要调试的控制器,因为我的 ajax 调用是在 html 代码中硬编码的。 @Mark 这只发生在Chrome 上吗?您在控制台上得到的详细错误是什么? @Rahul Sharma,Firefox 和 IE 也会出现此错误。详细的控制台错误是:jquery-3.3.1.min.js:2 GET localhost/ConnectorService.svc/… net::ERR_ABORTED 400 (Bad Request) 【参考方案1】:

调用有问题。通常,我们使用客户端代理类调用典型的 WCF 服务,而不是直接发送 http 请求。

$.ajax(
            url: 'http://localhost/ConnectorService.svc/GetData',
            contentType: 'application/json; charset=utf-8',
            type: "GET",
            dataType: 'jsonp',
        success: function (data) 
            $('#divContent').html(data); 
        ,
        error: function (error) 
            alert("error:  status - " + error.status + " | text: " + error.statusText);
        

这种直接发送http请求调用服务的风格一般适用于Restful风格服务,请参考以下链接。https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design Asp.net WebAPI 和 WCF 都可以创建 Restful 风格的服务。https://docs.microsoft.com/en-us/aspnet/web-api/https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/wcf-web-http-programming-model-overview 根据您的示例,我们可以将 WCF 服务更改为 Restful 样式,然后我们可以通过直接发送 http 请求来调用它。接口。

        [ServiceContract]
        public interface IService1
        
            [OperationContract]
            [WebGet(RequestFormat =WebMessageFormat.Json,ResponseFormat =WebMessageFormat.Json)]                    
            string GetData(int value);

    

服务。

public class Service1 : IService1


    public string GetData(int value)
    
        return "<a href='www.test.com.br'>test</a>";
    

Web.config

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpsGetEnabled="true" httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior>
          <webHttp />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <protocolMapping>
      <add scheme="http" binding="webHttpBinding"/>
    </protocolMapping>
  </system.serviceModel>

结果(在浏览器中输入地址访问URL是Http Get请求)。 或者,我们通过发送 Ajax 请求来调用它。

$.ajax(
    method:"Get",
    url: "http://10.157.13.69:11000/Service1.svc/GetData?value=34",
    contentType:"application/json"
).done(function(data)
    console.log(data);
)

如果有什么我可以帮忙的,请随时告诉我。

【讨论】:

非常感谢@Abraham Qian。这解决了我的问题。

以上是关于如何通过 Jquery 调用 C# WCF 服务来修复“ERR_ABORTED 400 (Bad Request)”错误?的主要内容,如果未能解决你的问题,请参考以下文章

通过C#代码调用WCF服务中的一个方法。不依赖配置文件等。求完整代码!!

如何使用 Jquery Ajax 发送自定义标头并使用 C# 在 WCF 服务中检索相同的标头值?

如何在 jQuery 中使用 WCF 方法

如何从 javascript 调用 WCF 服务?

我们可以在跨域中使用 Jquery $.ajax() 调用通过 https 访问 WCF 服务吗?

从 jQuery 调用 WCF 服务库的问题