0
votes

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.

1
Where is the controller code? Is it even being hit? Have you tried debugging?Austin T French
@Austin T French, as i said, inside my MVC code everything is ok, the problem is when i publish my service on IIS and try to access it with an html file independent from my MVC project. In this case, there is no controller to debug, since my ajax call is hardcoded inside the html code.Mark
@Mark Is this only happening on Chrome? What is the detailed error that you get on the console?Rahul Sharma
@Rahul Sharma, this error occurs also in Firefox and IE. The detailed console error is: jquery-3.3.1.min.js:2 GET localhost/ConnectorService.svc/… net::ERR_ABORTED 400 (Bad Request)Mark

1 Answers

1
votes

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).
enter image description here
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.