V
V
Voucik2014-05-06 09:53:16
JavaScript
Voucik, 2014-05-06 09:53:16

How to send data to RestFul service using ajax?

Hello. I'm not very good with the web. Therefore, please explain in more detail.
There is a WCF restful service (i.e. accepting http requests). So, I get data from the service without problems (using ajax), but I can’t send it to it, a 405 error pops up, I don’t know, maybe I’m not making the right request. Through the console, by the way, everything is fine, I send data, I receive it, everything is ok.

here is the service config

The code

<configuration>
  <system.web>
    <compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
    <customErrors mode="Off"/>
  </system.web>
  <system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="CORSWebHttpBinding" crossDomainScriptAccessEnabled="True" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647">
          <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
          <security mode="None">
            <transport clientCredentialType="None"/>
          </security>
        </binding>
      </webHttpBinding>
    </bindings>
    <services>
      <service name="TZ.Host.TzService" behaviorConfiguration="CORSServiceBehavior">
        <endpoint address="" binding="webHttpBinding" bindingConfiguration="CORSWebHttpBinding" behaviorConfiguration="EndpBehavior"
          contract="TZ.Host.ITzService" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="CORSServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="EndpBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type" />
      </customHeaders>
    </httpProtocol>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>



Global.asax service (to overcome cross browser)
The code

protected void Application_BeginRequest(object sender, EventArgs e)
        {
            EnableCrossDomainAjaxCall();
        }

        private void EnableCrossDomainAjaxCall()
        {

            String corsOrigin, corsMethod, corsHeaders;

            corsOrigin = HttpContext.Current.Request.Headers["Origin"];
            corsMethod = HttpContext.Current.Request.Headers["Access-Control-Request-Method"];
            corsHeaders = HttpContext.Current.Request.Headers["Access-Control-Request-Headers"];
            if (corsOrigin == null || corsOrigin == "null")
            {
                corsOrigin = "*";
            }
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", corsOrigin);
            if (corsMethod != null)
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", corsMethod);
            if (corsHeaders != null)
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", corsHeaders);
}



Service interface
The code

[ServiceContract]
    public interface ITzService
    {
        [OperationContract()]
        [WebInvoke(Method = "GET", UriTemplate = "/GetTestData", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
        List<TZ.Data.Test> GetTestData();


        [WebInvoke(Method = "POST")]
        void AddTestData(TZ.Data.Test value);
    }



Well, the service class itself
The code

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class TzService : ITzService
    {
        private static List<TZ.Data.Test> TData = new List<Test>(){new Test(){ID = 0,Name = "a"}, new Test(){ID = 1,Name = "B"}};
        public List<TZ.Data.Test> GetTestData()
        {
            return TData;
        }

        public void AddTestData(TZ.Data.Test value)
        {
            TData.Add(value);
        }
}



Well, the data object that will be transmitted
The code

[DataContract]
    public class Test
    {
        [DataMember(Name = "id")]
        public int ID { get; set; }
        [DataMember(Name = "name")]
        public string Name { get; set; }
    }



By the way, the code of the console - the client (who cares). Everything works great here.
The code

static void Main(string[] args)
        {
            SendData();
            GetData();

            Console.ReadKey();
        }

        private static void SendData()
        {
            string url = @"http://localhost:2337/TzService.svc/AddTestData";

            WebClient client = new WebClient();
            client.Credentials = System.Net.CredentialCache.DefaultCredentials;

            client.Headers["Content-type"] = "application/json";

            TzService.Test employee = new TzService.Test() { id = 11, name = "oooooo11" };

            MemoryStream stream = new MemoryStream();
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(TzService.Test));
            serializer.WriteObject(stream, employee);

            client.UploadData(url, "POST", stream.ToArray());
        }

        private static void GetData()
        {
            string url = @"http://localhost:2337/TzService.svc/GetTestData";

            WebClient client = new WebClient();
            client.Credentials = System.Net.CredentialCache.DefaultCredentials;


            byte[] data = client.DownloadData(url);
            Stream stream = new MemoryStream(data);

            DataContractJsonSerializer obj = new DataContractJsonSerializer(typeof(List<TzService.Test>));
            List<TzService.Test> result = obj.ReadObject(stream) as List<TzService.Test>;
            foreach (var p in result)
            {
                Console.WriteLine(p.id + "||" + p.name);
            }
            
        }



And then, I created a client on MVC 3 and make requests via ajax.
Here is the request to get the data (everything works fine)
The code

function Start() {

            $.ajax({
                type: 'GET',
                url: "http://localhost:2337/TzService.svc/GetTestData",
                async: false,
                cache: false,
                dataType: 'json',
                crossDomain: true,

                success: function (data) {
                    ShowData(data);
                },
                error: function (e) {
                    console.log(e.message);
                }
            });
        };



But when sending data, the problem pops up an error (I'm not strong in ajax, maybe I'm not doing the request correctly)
The code

function SendData() {
            var Json = { 'id': 9, 'name': "z" };
            $.ajax({
                url: url,
                data: JSON.stringify(Json),
                type: "POST",
                processData: false,
                async: false,
                contentType: "application/json",
                dataType: "text",
                success:
                    function (response) {
                        
                    },
                error: function (er) {

                }
            });
        }


error

screen 1
b7a49b1775ca49749579052faae916a2.PNG

screen 2
a0075da43dfd4b64b84aef315cb39e64.PNG

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
mayorovp, 2014-05-06
@Voucik

The problem is that you are trying to make a cross-domain request, which is also not safe (not a GET or a simple POST). It's probably because you specified the Content-Type.
In order for such a request to be made by the browser, the server must be able to process the OPTIONS request by responding with the correct Access-Control-Allow-Headers header (and Access-Control-Allow-Origin, of course).
On the request "wcf rest options request" in Google, the very first link leads to this one . Not the neatest solution (I'd rather hang the processing of the OPTIONS request and the issuance of CORS headers on some class-level attribute) - but it will do.
PS be careful with this solution - in fact, it turns off the protection against CORS. You should not keep a private API and "regular" web pages in the same project as a public API.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question