[英]jQuery $.ajax call to WCF service returns 400 Bad Request
(最后更新)
我正在使用不熟悉的技術研究一個想法。 我已經寫了一些 WCF 服務,但我從未做過任何高級配置。 這是我第一次深入了解 jQuery。 前提是我創建了一個 WCF 服務來獲取分支信息,由 jQuery 檢索。
我的第一次搜索產生了這個頁面: http://www.codeproject.com/KB/aspnet/WCF_JQUERY_ASMX.aspx#2 ,我將其用作代碼的基礎。 我最初是作為一個跨站點設置開始的,我擺脫了它,看看我是否能讓這個東西正常工作。 我搜索了堆棧溢出,但沒有一篇文章解決了我的 400 Bad Request 問題。
我的 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>
我的界面中的代碼:
[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 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()" />
您會注意到我使用的是 jQuery 1.6.1,而不是教程中的 1.3。 該教程在我的盒子上運行良好,並且按預期完成了所有工作。 不幸的是,我的代碼沒有。 我很感激你們能提供的任何幫助。
哦,這是 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
更新:好的,我將“{}”作為數據查詢傳遞(顯然這是向不帶參數的方法傳遞任何內容的正確方法),現在我得到了不受支持的媒體類型。 並且跟蹤異常是: System.ServiceModel.ProtocolException: Content Type application/json; charset=utf-8 被發送到需要 text/xml 的服務; 字符集=utf-8。
調用本身似乎沒有任何問題 - 您應該嘗試啟用跟蹤以查看為什么 WCF 認為傳入請求是錯誤的。 我嘗試了一個與您所擁有的代碼類似的代碼(見下文),它工作得很好。 此外,由於請求來自與服務相同的域 (localhost:16062),因此您不會遇到任何跨域問題。
更新:基於問題評論線程的解決方案
web.config 中 <service> 元素的“name”屬性必須與服務 class 的完全限定名稱(即命名空間 + 名稱)匹配(即與 .svc 文件中使用的值相同)。 否則,您將獲得為您的服務添加的默認端點,這可能是您想要的,也可能不是您想要的 - 默認情況下,您會獲得一個 BasicHttpBinding 端點,這不是您想要的。
這個問題是 .NET Framework 4.0: Simplified Configuration中添加的功能的不幸副作用。 在 .NET 3.5 之前,每個服務都需要在 web.config 上有一個條目來配置它,即使是最簡單的應用程序(即 hello world)的配置文件也很大。 所以發生的事情是,從 4.0 開始,如果 WCF 沒有找到名稱與服務的完全限定名稱匹配的服務元素,它會很高興地認為您要使用默認配置。 這就是為什么它一開始碰巧與 WcfTestClient 一起“工作”的原因。
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();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.