2

I have two apps. The first is WCF Service, the second is asp.net MVC 3 app.
In the WCF app I have a interface:

    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string HelloWorld(string personName);
    }

And a class:

public class Service1 : IService1
    {
        public string HelloWorld(string personName)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            return serializer.Serialize("Hello " + personName);
        }
    }

Now, in the asp.net mvc app I want call this method via Ajax:

<script type="text/javascript">
    var personName = "John";
    var dataIn = '{' + '"input":"' + personName + '"}';
    $.ajax({
        url: "http://localhost:7215/Service1.svc/HelloWorld",
        type: "POST",
        contentType: "application/json; charset=utf-8",
        data: dataIn,
        dataType: "json",
        success: function (data) {
            var object = JSON.parse(data.d);
            if (object.Error == '') {
                $("#response").html(object);
            }
        },
        error: function (error) {
            alert("Error: " + error);
        }
    });
    </script>

But in the Firebug I get error: 400 Bad Request.
How to call HelloWorld method properly? Thanks.

2 Answers 2

12

So you are trying to consume a WCF service from JavaScript?

The first problem I see is, your service is not yet ready to be consumed from JavaScript :(. You have to make the following changes..

  1. Configure the Service1 class with the AspNetCompatibilityRequirements behavior.

  2. Mark the service method HelloWorld in interface with WebGet attribute. [You need reference to System.SericeModel.Web assembly]

After making the two changes..

[ServiceContract]
public interface IService1
{
  [OperationContract]
  [WebGet(ResponseFormat = WebMessageFormat.Json)]
  string HelloWorld(string personName);
}

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1 : IService1
{
  public string HelloWorld(string personName)
  {
    JavaScriptSerializer serializer = new JavaScriptSerializer();

    // you are not returning data in proper JSON format, wrap the text in
    // an anonymous object before serializing.
    return serializer.Serialize(new { text = "Hello " + personName });
  }
}

Next..

  1. Configure webHttpBinding for the service (Make sure you change the service and contract names!).

    <system.serviceModel>
      <behaviors>
        <endpointBehaviors>
          <behavior name="webHttpBehavior">
            <webHttp />
          </behavior>
        </endpointBehaviors>
      </behaviors>
      <bindings>
        <webHttpBinding>
          <binding name="webHttpBindingWithJsonP" />
        </webHttpBinding>
      </bindings>
      <services>
        <service name="MvcApplication3.Service1">
          <endpoint address="" binding="webHttpBinding"
                    bindingConfiguration="webHttpBindingWithJsonP"
                    contract="MvcApplication3.IService1"
                    behaviorConfiguration="webHttpBehavior"/>
        </service>
      </services>
    </system.serviceModel>
    

So now the service is ready!

Lets do the changes in the client-side (You are getting some data from the service so why POST?)

  <script type="text/javascript">
      var personName = "John";
      var dataIn = '{' + '"input":"' + personName + '"}';
      $.ajax({
         url: "http://localhost:50623/Service1.svc/HelloWorld",
         type: "GET",
         contentType: "application/json; charset=utf-8",
         data: dataIn,
         dataType: "json",
         success: function (data) {
           var jsonData = JSON.parse(data);
           $("#response").html(jsonData.text);
         },
         error: function (error) {
           alert("Error: " + error);
         }
      });
   </script>

Till now I've assumed that both the WCF service and the MVC app are running in the same domain.

But if that's not the case then you will gete a 405(Method Not Allowed) error due to CROSS-DOMAIN BARRIER.

There are different ways to overcome this problem!

1. Use JSONP

In this case you have to set the crossDomainScriptAccessEnabled property to true in the binding and you have to make JSONP calls from jQuery.

<binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true" />

Then change the dataType from "json" to "jsonp" in the $.ajax method.

  <script type="text/javascript">
      var personName = "John";
      var dataIn = '{' + '"input":"' + personName + '"}';
      $.ajax({
         ...
         dataType: "jsonp",
         ...
      });
   </script>

2. Using CORS

Refer this..

http://www.w3.org/TR/cors/

https://developer.mozilla.org/en/http_access_control

Sign up to request clarification or add additional context in comments.

4 Comments

Wow, great answer. Big thanks. I have one more question. I have the several methods in ASP.NET MVC application which retrieve data from external win(not mine) application (by tcp/ip). And now I want to move this methods to WCF service, also other methods( send email messages and other proccesses which now runing in separate thread). This is my first experience with web services/wcf. And, what is the better way to do that: wcf, web service, win service? Thanks
I would suggest to post this as a separate question
Found this answer helpful in getting myself rolling with JavaScript+WCF. One thing though: the dataIn JSON value didn't work for me. I needed to replace it with var dataIn = "input=" + personName; and take out the contentType:.... This got it to a point where it returned JSON but still required querystring input.
Hi @Mark I am facing the same issue but only when I am throwing an exception. I am unable to see the actual exception that is being thrown from WCF service.stackoverflow.com/questions/34260982/…
3

The first thing that you need to ensure is that you are not violating the same origin policy that's built in browsers. This policy prevents you from sending cross domain AJAX request. Since you mentioned that you have 2 applications I suspect that you are hitting this limitation because you have for example the first application hosted on http://localhost:1234/ (the one that contains the javascript file) and you are attempting to send an AJAX request to http://localhost:7215/ (same domain, different port => same origin policy is violated).

There are several workarounds. One of them consists into configuring the service to send a JSONP response instead of JSON. Here's a sample WCF service application on MSDN which illustrates how you could configure it. Basically you need to enable the crossDomainScriptAccessEnabled switch as shown in this blog post.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.