2011-06-29 148 views
6

(在年底更新)

我正在使用不熟悉的技术的想法。我已经写了几个WCF服务,但我从来没有做过任何高级配置。这是我第一次深入jQuery。前提是我创建了一个WCF服务来获取分支信息,以便通过jQuery进行检索。

我的第一次搜索结果显示此页:http://www.codeproject.com/KB/aspnet/WCF_JQUERY_ASMX.aspx#2我正在使用它作为我的代码的基础。我最初是作为一个跨站点设置开始的,我摆脱了这个设置,看看我是否可以让这个工作正常工作。我搜索堆栈溢出,并没有任何帖子解决我的400错误的请求问题。从我的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()" /> 

你会注意到我m使用jQuery 1.6.1,而不是1.3 fr om教程。该教程在我的盒子上运行良好,并按预期做一切。不幸的是,我的代码没有。我感谢你们可以提供的任何帮助。

哦,这里是从提琴手的请求的副本:

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 

更新:好吧,我通过“{}”的数据查询(显然这是通过什么来的正确方法一种不带参数的方法),现在我得到了Unsupported Media Type。跟踪异常是:System.ServiceModel.ProtocolException:Content Type application/json; charset = utf-8被发送到期望text/xml的服务;字符集= UTF-8。

+0

因此,只是为了测试,我添加了一个参数给我的GetBranches方法,布尔测试。我更新了我的$ .ajax调用以传入数据:'{“Test”:“true”}',现在我在跟踪中出现错误:Content Type application/json; charset = utf-8被发送到期望text/xml的服务;字符集= UTF-8。我添加了ReceiveFormat = Json,但仍然出现错误。我需要改变web.config中的某些东西吗?另外,是否有一个正确的方法将null传递给没有参数的方法(我的原始GetBranches)? –

+0

您可以检查web.config中的服务名称是否与GeoDataService.svc文件中的服务名称匹配?他们必须是完全一样的(即,带名称空间的类名) – carlosfigueira

+0

感谢您的想法,卡洛斯。我的命名空间是GeoDataServices,我的服务名称是GeoDataService。当我将web.config中的服务名称更改为GeoDataServices.IGeoDataService时,它会引发同样的错误(当我将其更改为GeoDataServices.GeoDataService时,它告诉我使用跟踪中的接口)。所以,任一配置都会返回相同的新ProtocolException。 –

回答

7

调用本身似乎没有任何问题 - 您应该尝试使用enable tracing来了解WCF为什么将传入请求视为错误。我尝试了一个类似的代码(见下文),它工作得很好。此外,由于请求来自与服务相同的域(localhost:16062),因此您没有任何跨域问题。

更新:根据问题的评论线程解决方案

的“名”在web.config 的<服务>元素的属性必须完全合格的名称相匹配(即命名空间+名称)(即.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(); 
    } 
} 
+0

感谢指针,卡洛斯。使用跟踪日志,出现以下错误:System.Xml.XmlException:由于消息正文为空,因此无法读取正文。现在,我没有太多的“原始”web服务调用经验(通常我将.NET转换为.NET),所以我不知道这是否是过于通用的例外。 –

+0

感谢您的澄清,卡洛斯。不知道关于WCF 4.0 vs 3.5。再一次,非常感谢你的帮助! –

相关问题