JQuery $ .ajax WCF service call returns 400 Bad Request

(Update at the end)

I am working on an idea using an unfamiliar technology. I wrote several WCF services, but I never made any additional settings. This is my first dive into jQuery. The premise is that I create a WCF service to get the branch information that jQuery will get.

My first search yielded this page: http://www.codeproject.com/KB/aspnet/WCF_JQUERY_ASMX.aspx#2 , which I use as the basis for my code. At first, I started working as a cross-site installation, and I got rid of this to see if I could just get this work to work. I was looking for a stack overflow and none of the messages resolved my 400 error issue.

Code from my web.config:

<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="GeoDataBehavior"> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior> <behavior name=""> <serviceMetadata httpGetEnabled="true" /> </behavior> </serviceBehaviors> <endpointBehaviors> <behavior name="GDEPBehavior"> <webHttp /> </behavior> </endpointBehaviors> </behaviors> <bindings> <webHttpBinding> <binding name="GDBinding" crossDomainScriptAccessEnabled="true"/> </webHttpBinding> </bindings> <services> <service behaviorConfiguration="GeoDataBehavior" name="GeoDataService"> <endpoint address="" binding="webHttpBinding" contract="IGeoDataService" behaviorConfiguration="GDEPBehavior"/> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> 

Code from my interface:

 [ServiceContract] public interface IGeoDataService { [OperationContract] [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)] List<BranchData> GetBranches(); } // Use a data contract as illustrated in the sample below to add composite types to service operations. [DataContract] public class BranchData { [DataMember] public string BranchNumber { get; set; } [DataMember] public string BranchName { get; set; } [DataMember] public string StreetAddress { get; set; } [DataMember] public string City { get; set; } [DataMember] public string Zip { get; set; } [DataMember] public string State { get; set; } [DataMember] public string Phone { get; set; } [DataMember] public string County { get; set; } } 

jQuery script:

  <script type="text/javascript" language="javascript" src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.6.1.js"> </script> <script type="text/javascript" language="javascript"> /* help from http://www.codeproject.com/KB/aspnet/WCF_JQUERY_ASMX.aspx */ var varType; var varUrl; var varData; var varContentType; var varDataType; var varProcessData; function CallService() { // Thank you Bing: http://blueonionsoftware.com/blog.aspx?p=03aff202-4198-4606-b9d6-686fd13697ee jQuery.support.cors = true; $.ajax({ type: varType, url: varUrl, data: null, crossDomain: true, contentType: varContentType, dataType: varDataType, processdata: varProcessData, success: function (msg) { ServiceSucceeded(msg); }, error: ServiceFailed }); /* $.getJSON(varUrl, null, function (msg) { ServiceSucceeded(msg); }); */ } function GetBranchDataJson() { varType = "POST"; varUrl = "GeoDataService.svc/GetBranches"; varData = ""; varContentType = "application/json; charset=utf-8"; varDataType = "json"; varProcessData = true; CallService(); } function ServiceSucceeded(result) { var ddlResult = document.getElementById("ddlResult"); for (var j = ddlResult.options.length - 1; j >= 0; j--) { ddlResult.remove(j); } for (var i = 0; i < result.length; i++) { var opt = document.createElement("option"); opt.text = result[i].BranchName; ddlResult.options.add(opt); } } function ServiceFailed(jqXHR, errorType, errorThrown) { alert('error!\n' + jqXHR + '\n' + errorType + '\n' + errorThrown); } </script> <input name="WTF" type="button" onclick="GetBranchDataJson()" /> 

You will notice that I am using jQuery 1.6.1, not 1.3 from the tutorial. The tutorial works fine on my inbox and does everything as expected. Unfortunately, my code does not. I appreciate any help you can provide.

Oh, and here is a copy of the request from Fiddler:

 POST http://localhost:16062/GeoDataService.svc/GetBranches HTTP/1.1 Accept: application/json, text/javascript, */*; q=0.01 Content-Type: application/json; charset=utf-8 Referer: http://localhost:16062/Default.aspx Accept-Language: en-us Accept-Encoding: gzip, deflate User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) Host: localhost:16062 Content-Length: 0 Connection: Keep-Alive Pragma: no-cache 

Update: Well, I passed "{}" as a data request (apparently this is the right way to pass anything to a method that does not accept parameters), and now I get the Unsupported Media Type. Trace Exception: System.ServiceModel.ProtocolException: Application Type application / json; charset = utf-8 was sent to a service waiting for text / xml; encoding = UTF-8.

+6
source share
1 answer

The call itself does not seem to have a problem - you should try to turn on tracing to find out why WCF considers the incoming request to be bad. I tried the same code as the one you have (see below) and it worked perfectly. Also, since the request comes from the same domain (localhost: 16062) as a service, you have no problem between the domains.

Update: solution based on the topic of comments on the question

The β€œname” attribute for the <service> element in the web.config file must correspond to the fully qualified name (ie namespace + name) of the service class (that is, the same value used in the .svc file). Otherwise, you will get a default endpoint added for your service, which may or may not be what you want - by default you get a BasicHttpBinding endpoint, which you did not want in your case.

This issue is a bad side effect of a feature added in the .NET Framework 4.0: Simplified configuration . Prior to .NET 3.5, each service had to have an entry in web.config to configure it, and the configuration files for even the simplest applications (i.e. Hello World) were large. It so happened that since 4.0, if WCF does not find a service element with a name that matches the fully qualified service name, it will be happy to think that you want to use the default configuration. This is why the β€œwork” with WcfTestClient first occurs.

 public class StackOverflow_6526659 { [ServiceContract] public interface IGeoDataService { [OperationContract] [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)] List<BranchData> GetBranches(); } public class Service : IGeoDataService { public List<BranchData> GetBranches() { return new List<BranchData>(); } } // Use a data contract as illustrated in the sample below to add composite types to service operations. [DataContract] public class BranchData { [DataMember] public string BranchNumber { get; set; } [DataMember] public string BranchName { get; set; } [DataMember] public string StreetAddress { get; set; } [DataMember] public string City { get; set; } [DataMember] public string Zip { get; set; } [DataMember] public string State { get; set; } [DataMember] public string Phone { get; set; } [DataMember] public string County { get; set; } } public static void Test() { string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); WebHttpBinding binding = new WebHttpBinding { CrossDomainScriptAccessEnabled = true }; WebHttpBehavior behavior = new WebHttpBehavior(); host.AddServiceEndpoint(typeof(IGeoDataService), binding, "").Behaviors.Add(behavior); host.Open(); Console.WriteLine("Host opened"); HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(baseAddress + "/GetBranches"); req.Method = "POST"; req.GetRequestStream().Close(); HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription); foreach (var header in resp.Headers.AllKeys) { Console.WriteLine("{0}: {1}", header, resp.Headers[header]); } if (resp.ContentLength > 0) { Console.WriteLine(new StreamReader(resp.GetResponseStream()).ReadToEnd()); } Console.Write("Press ENTER to close the host"); Console.ReadLine(); host.Close(); } } 
+7
source

Source: https://habr.com/ru/post/891675/


All Articles