简体   繁体   中英

How to fix “ERR_ABORTED 400 (Bad Request)” error with Jquery call to C# WCF service?

I created a simple C# WCF service that returns a string with html code. When i consume this service with a simple MVC project inside the WCF solution, everythigs works fine.

  • Service code
    public class ConnectorService : IConnectorService
    {
        public string GetData()
        {
            return "<a href='www.test.com.br'>test</a>";
        }
    }
  • Interface code
    [ServiceContract]
    public interface IConnectorService
    {
        [OperationContract]
        string GetData();
    }

After this test i published this service in my local IIS and tried to consume this service with a html page that is not inside the WCF solution, but is located inside the same IIS directory of the service.

  • HTML code
    <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>

When i open this html file on the browser, I got 2 errors:

1) CORS policy - i fixed that with global.asax file like this

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) Error 400 - Bad Request I tried several solutions of stack overflow, generally with changes on my ajax call, global.asax and web.config file, but i always get a bad request error inside the chrome console.

  • web.config code
        <?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>

I believe this is a simple problem with a simple solution but, after several days of tests, i feel that i am chasing my own tail. Can someome point me with a solution for this?

Thanks in advance.

There is something wrong with the invocation. Normally, we call the typical WCF service by using client proxy class instead of directly sending an http request.

$.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);
        }

This style calling the service by directly sending http request usually applies to the Restful Style Service, please refer to the below link.
https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design
Both Asp.net WebAPI and WCF could create a Restful style service.
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
Based on your example, we could change the WCF service to Restful style, and then we could call it by directly sending an http request.
Interface.

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

    }

Service.

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>

Result (accessing the URL with typing the address in browser is Http Get request).
在此处输入图片说明
Alternatively, we call it by sending Ajax request.

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

Feel free to let me know if there is anything I can help with.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM