简体   繁体   中英

How to post data to WCF Service using jquery Ajax?

I am facing issue in consuming WCF service using JQUERY AJAX. I know this is cross domain issue and have read alot of solution about it. but none worked for me. Below is all the related code. Can anyone please help me out?

Thanks

 [OperationContract]
        [WebInvoke(Method = "POST",BodyStyle=WebMessageBodyStyle.Bare,
            RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json)]
        [return: MessageParameter(Name = "result")]


        public ServiceSearchResponse GetSearchResults(ServiceSearchParams sParams)
        {
            /// search function
        }

JQUERY:

        $.ajax({
            type: 'POST',
            url: "http://myserviceurl.com/GetSearchResults",
            data: p,
            contentType: "application/json; charset=utf-8",
            dataType: 'json',
            crossDomain: true,
            success: function (data) {

                alert(data);
            },
            failure: function (response) {
                alert('failed');
            },
            error: function (response) {
                alert(JSON.stringify(response));
            }
        });

Webconfig:

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

<system.serviceModel>
    <protocolMapping>
      <add scheme="http" binding="webHttpBinding" bindingConfiguration="" />
    </protocolMapping>
    <behaviors>
      <serviceBehaviors>
        <behavior name="DefaultServiceBehavior">
          <!--Added DefaultServiceBehavior referenced at service tag above-->
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>       
        <behavior name="myserives.services.AppServicesAspNetAjaxBehavior">

          <webHttp />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    <services>  
      <service name="mypackage.services.MyServices">
        <endpoint address="" behaviorConfiguration="myserives.services.AppServicesAspNetAjaxBehavior" binding="webHttpBinding"
           bindingConfiguration="LargeSizeMessages" contract="myContractName"  />
      </service>
    </services>
    <bindings>
      <webHttpBinding>
        <binding name="LargeSizeMessages" maxBufferSize="2147483647"
                 maxBufferPoolSize="2147483647"
                 maxReceivedMessageSize="2147483647" crossDomainScriptAccessEnabled="true">      
          <security mode="None" />
        </binding>
      </webHttpBinding>

    </bindings>

  </system.serviceModel>

This is how it looks like: http://screencast.com/t/b7tsqld6

See error : http://screencast.com/t/pWQNAlmMYS3

And nothing in post data. though im posting data.

--- UPDATE

See my Global.asax .. i am doing something wrong here:

 protected void Application_BeginRequest(object sender, EventArgs e)
        {

            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            HttpContext.Current.Response.Cache.SetNoStore();

            EnableCrossDmainAjaxCall();
        }

        private void EnableCrossDmainAjaxCall()
        {
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin",
                          "*");

            if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            {
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods",
                              "GET, POST");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials",
                             "true");
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers",
                              "Content-Type, Accept");
                HttpContext.Current.Response.AddHeader("Access-Control-Max-Age",
                              "1728000");
                HttpContext.Current.Response.End();
            }
        }

Here is a piece of working code.

Interface

[ServiceContract]
    public interface IDataService
    {
        [OperationContract]
        [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json,BodyStyle=WebMessageBodyStyle.WrappedResponse)]
        List<RequestData> GetUser(RequestData data);

        [OperationContract]
        [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "UsersList/{id}",RequestFormat=WebMessageFormat.Json,BodyStyle=WebMessageBodyStyle.WrappedResponse)]
        RequestData UsersList(string id);



    }

Class implementing interface

public class DataService : IDataService
    {

        public List<RequestData> GetUser(RequestData data)
        {
            List<RequestData> list = new List<RequestData>();
            if (data.Name.ToUpper() == "MAIRAJ")
            {
                list.Add(new RequestData
                {
                    Name = "Mairaj",
                    Age = 25,
                    Address = "Test Address"
                });
                list.Add(new RequestData
                {
                    Name = "Ahmad",
                    Age = 25,
                    Address = "Test Address"
                });

            }
            return list;
        }
        public RequestData UsersList(string userId)
        {
                return new RequestData
                {
                    Name = "Mairaj",
                    Age = 25,
                    Address = "Test Address"
                };
         }

    }

Custom Class

As i am passing object of this class as parameter to method and returning object of this so i am using this. You may not need it.

[DataContract]
    public class RequestData
    {
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public int Age { get; set; }
        [DataMember]
        public string Address { get; set; }

    }

Web.Config

<configuration>
    <configSections>
    </configSections>
    <system.web>
      <compilation debug="true" targetFramework="4.5" />
      <httpRuntime targetFramework="4.5" />
    </system.web>

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="EndpBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="ServiceBehavior" name="WCFWebApp.DataService">
        <endpoint address="" binding="webHttpBinding" contract="WCFWebApp.IDataService" behaviorConfiguration="EndpBehavior"/>
      </service>
    </services>
  </system.serviceModel>
</configuration>

And here is how you call it

var Data = {
        Name: "Mairaj",
        Age: 20,
        Address: "Test Address"
        //userId:1
    };
    $.ajax({
        type: "POST",
        url: "/DataService.svc/GetUser",
        dataType: "JSON",
        data: JSON.stringify(Data),
        contentType: "application/json; charset=utf-8",
        success: function (data) {
            alert("Data is " + data);
        },
        error: function () {
        }
    });

You need to change name of service classes in web.config and url in jquery code from where you will call it.

I would try to set Access-Control-Allow-Credentials: true i web.config. Also try setting the Access-Control-Allow-Headers to the header that match your jquery ajax call. Should be "application/json", but check with fiddler (or similar) to be sure. Finally try setting the Access-Control-Request-Method: POST

I hade similar problems and after experimenting with different settings i web.config I managed to find a combination that actually worked. Good luck :)

UPDATE

Also, I would make sure that the access-control-allow-credentials is in the same case- form as the other parameters. Ie Access-control-allow-credentials. I don't really have any source on this, but just in case :)

I would try this without using localhost. Setup your test environments on different servers with proper host names.At least Chrome has had problems handling cors on localhost.

According to http://www.html5rocks.com/en/tutorials/cors/ the Content-type of the request should be one of the following:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

UPDATE 2

More things you could try: Add:

$.support.cors = true;

before the

$.ajax({ ...

I think that the problems could be cased by incorrect content type. When I did a CORS setup to a Sharepoint 2013 server I added this and it all worked:

headers: { 
  "accept": "application/json;odata=verbose;charset=utf-8",
  "content-type":"application/json;odata=verbose;charset=utf-8"
},

That content-type might not be relevant for you, but I might be important to specify like that.

You need to add requested domain in Access-Control-Allow-Origin instead of * , * might not work in all browsers , as it a security issue - ie only requested domain should be allowed in OPTIONS request, not * should be responded in options response header. To solve this, you need to change that code to following.

HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://localhost");

Replace http://localhost with requested domain name, to do it programatically you can use this - HttpContext.Current.Request.Headers["Origin"].ToString() .

I have explained this in my blog in more detail- Blog , CodeProject

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