1

I wrote a web service, which I would like to call from JavaScript. The problem is that I receive a 404 error, and not sure what I did wrong.

There are many articles on how to achieve the task. The one that I used is here.

Here is the code behind and yes, I did read the comment and did add the [ScriptService]:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Services;
using System.Web.Script.Serialization;
using System.Web.Script.Services;
using BvCommonControls;

namespace MyProject.MyWebService
{
    [WebService(Namespace = "http://microsoft.com/webservices/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    [ScriptService]
    public class svcSignin : WebService
    {
        [WebMethod]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public String GetStockName(String argEncrypted)
        {
            return js.Serialize("HelloWorld!");
        }
    }
}

The JavaScript code is:

// Create the URL.
var serviceUrl = "http://mywebsiteaddress.whatever/Folder/myservice.asmx";
var serviceOperation = "/GetStockName";
var serviceData = "myencodedargs";

$.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    url: serviceUrl + serviceOperation,
    data: JSON.stringify(serviceData),
    dataType: "json",
    async: true,
    success: ajaxSigninSuccess,
    error: ajaxSigninError
});

function ajaxSuccess(response)
{
    alert(response.d);
}

function ajaxError(response)
{
    alert(response.status + " " + response.statusText);
}

readyState is 4 with status is 404 (page not found).

If I enter the url into a web browser using a copy and paste, I get the standard page with the comment:

The following operations are supported. For a formal definition, please review the Service Description.

* GetStockName

The problem seems to be something with one of the class or method declarations.

UPDATE (Web Services)

According to MSDN, here is where the WebServices section goes.

<configuration>
 <system.web>
    <webServices>
      <conformanceWarnings>
        <remove name='BasicProfile1_1'/>
      </conformanceWarnings>
    </webServices>
  </system.web>
</configuration>

This CodeProject article shows where the System.Web.Handlers.ScriptModule goes.

<configuration>
  <system.web>
    <httpModules>
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, 
    System.Web.Extensions, Version=3.5.0.0, Culture=neutral, 
    PublicKeyToken=31BF3856AD364E35"/>
    </httpModules>
  </system.web>
</configuration>

UPDATE 2 (Requested RESTful update)

I updated the Ajax section in my JavaScript code to conform to the requested format. Basically, if I go to that page in a browser and click on the GetStockName link, then I get to a page that shows various SOAP formats and at the bottom an HTTP POST format.

HTTP POST

The following is a sample HTTP POST request and response. The placeholders shown need to be replaced with actual values.

POST /Folder/myservice.asmx/GetStockName HTTP/1.1
Host: www.mywebsiteaddress.whatever
Content-Type: application/x-www-form-urlencoded
Content-Length: length

argEncrypted=string

I had to hard code the URL as shown. Simply placing a variable like "$.ajax(serviceUrl{" did not work and interestingly enough adding "url: serviceUrl," as one of the ajax attributes also did not work. Only the construct of "$.ajax(''{" worked.

$.ajax('http://mywebsiteaddress.whatever/Folder/myservice.asmx/GetStockName'{
    type: 'POST',
    contentType: 'application/json',
    headers: { 'Access-Control-Allow-Origin': '*' },
    crossDomain: true,
    data: '{argEncrypted: "' + serviceData + '"}',
    dataType: "json",
    async: true,
    success: ajaxSuccess,
    error: ajaxError
});

UPDATE 3 (CORS)

The problem is definitely one of cross domain or cross-origin resource sharing or CORS. The old code used jsonp, which works nicely, but does not support ASMX pages.

As mentioned in my comment part of the problem was Visual Studio too. VS2013 running IE11 in debug mode does not allow CORS operations. I had to launch IE11 outside of Visual Studio to get things to work along with the other changes.

Here are some links that I saw: link 1, link 2, and more importantly link 3.

Additions/changes call for in web.config:

<configuration>
 <system.webServer>
  <httpProtocol>
   <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="Content-Type" />
   </customHeaders>
  </httpProtocol>
 </system.webServer>
<configuration>

and the $.ajax changes include adding:

type: 'POST',
contentType: 'application/json',
headers: { 'Access-Control-Allow-Origin': '*' },
crossDomain: true,

Note the section

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

adds the header to the service that indicates that the call is HTTP 1.1 compliant, per links and the discussion in SO chat. This header is equivalent to the PHP header.

Testing done on Win7-64 using IE11. IE11 supports CORS, as noted in one link.

(Question updated to reflect answer.)

Community
  • 1
  • 1
Sarah Weinberger
  • 15,041
  • 25
  • 83
  • 130

2 Answers2

1

I got the code to work!

I am not sure when the code started to work, as I was not testing all the time through IE11, but rather through a JavaScript enabled page running through VS2013 in debug mode talking to a CORS page. Evidently, Visual Studio disables CORS operations to ASMX pages. One has to go outside of VS debugger mode.

All the other changes are probably required as well.

Sarah Weinberger
  • 15,041
  • 25
  • 83
  • 130
  • Is it possible, and if so how, to do CORS operations to an asmx page inside the VS debug environment, basically through an IE11 page launched by Visual Studio 2013? – Sarah Weinberger Apr 01 '14 at 23:32
0

Try the following:

add the following to your web.config

<webServices>
 <protocols>
  <add name="HttpPost"/>
 </protocols>
</webServices>

Also, in your AJAX request, change this line

data: JSON.stringify(serviceData)

to

data: '{argEncrypted: "' + serviceData + '"}'

Also ensure you have the following web.config entry:

<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
Raja Nadar
  • 9,409
  • 2
  • 32
  • 41
  • He doesn't need that entry in web.config if it already exists in machine.config. – mason Apr 01 '14 at 00:25
  • See update 2 for placement information of WebServices. I was curious, where it went, and researched the topic. – Sarah Weinberger Apr 01 '14 at 14:10
  • The problem is one of cross-domain. In changing the $.ajax JavaScript section to conform a bit more to the requested format, see UPDATE 2 above, I get response.statusText to indicate an actual error, namely that it cannot find the URL. – Sarah Weinberger Apr 01 '14 at 15:15