0

I have created a WCF service, and am communicating with it using ajax/json 'get' commands. It's working fine on Edge, Chrome (Windows desktop), Firefox (Windows desktop). But with IE10 I'm getting

XMLHttpRequest: Network Error 0x80070005, Access is denied.

and with Chrome on my Android phone I'm getting

error 405 (Method not allowed). 

It's also failing with Firefox on the phone (just reports 'web error'), but I haven't any debugger for that so can't check the underlying error. On an iPad (using Safari), the browser just crashes with no message.

The method being accessed first is 'Login', but if I comment that out, hardcode my login details and try another method (GetLocations) I'm getting the same error.

The site is quilkin.co.uk, if anyone feels like having a look. If it's working correctly, you should get an 'invalid user' or 'invalid password' if you try to log in. Yes, I know it's not secure! I'll sort that later.

The web.config is as follows (sorry about the bad formatting):

<?xml version="1.0"?>
<configuration>

<appSettings>
  <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
</appSettings>
<system.web>
   <customErrors mode="Off"/>
   <compilation debug="true" targetFramework="4.5.2"/>
   <httpRuntime targetFramework="4.5.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="false"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
  <protocolMapping>
    <add binding="basicHttpsBinding" scheme="https"/>
  </protocolMapping>    
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
 <handlers>
        <remove name="WebDAV"/>
     </handlers>
 <httpProtocol>
     <customHeaders>
      <clear />
      <add name="Access-Control-Allow-Origin" value="*" />
      <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept,Authorization" />
      <add name="Access-Control-Allow-Methods" value="GET, PUT, POST, ORIGIN" />
     </customHeaders>
   </httpProtocol>
   <modules runAllManagedModulesForAllRequests="true">
        <remove name="WebDAVModule"/>
   </modules>

   <directoryBrowse enabled="true"/>
   <validation validateIntegratedModeConfiguration="false"/>
 </system.webServer>

</configuration>

The 'WebDAV' removal lines were added as a result of looking at other posts, but appeared to make no difference. I also tried adding a new 'global.asax' as described here but that didn't help either.

Community
  • 1
  • 1
quilkin
  • 874
  • 11
  • 31

2 Answers2

0

i guess i now the problem. please use * in [ServiceContract]. like this:

[WebInvoke(Method = "*"

this way you allow your method receive options request. example of options request in Fiddler4

Enabling CORS for non-GET requests requires more than just setting the Access-Control-Allow-Origin header - it also needs to deal with preflight requests, which are OPTIONS requests which ask the server whether it's safe to perform operations which can potentially change data (e.g., POST, PUT, DELETE) before the actual request is sent. I've written a blog post about adding CORS support for WCF. It's not the simplest of the implementations, but hopefully the code in the post can be simply copied / pasted into your project. The post can be found at http://blogs.msdn.com/b/carlosfigueira/archive/2012/05/15/implementing-cors-support-in-wcf.aspx.

Mohammad
  • 2,724
  • 6
  • 29
  • 55
  • I tried that but no success; thanks for looking anyway – quilkin May 05 '17 at 09:26
  • dear @quilkin. do you know what happens in optional requests? please make sure your service doesn't throw exceptions(return 200) in optional requests. in order to check this you can use Fiddler4. just change the method to optional an call your web service. every thing else looks good. hope this solve your problem. – Mohammad May 05 '17 at 12:29
  • I don't know what you mean by 'optional requests' - I googled that but didn't find any useful hits. Installed Fiddler4; that shows nothing useful but maybe I don't know how to use it best. Just looked at the server logs and found that calls to the Login method from IE10 (and from Android chrome) are responding with 400, whereas calls from Firefox give 200. 400 sounds like bad json format but why should it be different for different browsers? – quilkin May 05 '17 at 14:37
  • my bad dear @quilkin. by optional request i meant:This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval. i also edited my answer. – Mohammad May 05 '17 at 14:55
  • Enabling CORS for non-GET requests requires more than just setting the Access-Control-Allow-Origin header - it also needs to deal with preflight requests, which are OPTIONS requests which ask the server whether it's safe to perform operations which can potentially change data (e.g., POST, PUT, DELETE) before the actual request is sent. – Mohammad May 05 '17 at 15:01
  • From the server logs I also see that from firefox the response is "200 POST /WebMap.svc/Login" but from IE it is "400 OPTIONS /WebMap.svc/Login" so yes, it is something to do with OPTIONS. I looked at your post about CORS but there's too much stuff to learn there. Maybe I should forget WCF and start again with web API – quilkin May 05 '17 at 15:13
  • dear @quilkin. been there about 2 years ago. i solved this problem by adding simple condition. if (HttpContext.Current.Request.HttpMethod.Equals("OPTIONS", StringComparison.OrdinalIgnoreCase)) return; – Mohammad May 05 '17 at 15:50
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/143537/discussion-between-quilkin-and-david). – quilkin May 05 '17 at 19:42
0

At last I have found the solution (or a solution). This thread's second answer was the key. Basically I had to add an extra (empty) method for each POST method, to deal with the OPTIONS request that some browsers are sending, e.g.:

    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "/Login", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    Login Login(Login login);

    [OperationContract]
    [WebInvoke(Method = "OPTIONS", UriTemplate = "/Login", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    Login LoginOptions(Login login);
quilkin
  • 874
  • 11
  • 31