2011-06-29 15 views
6

(अंत में अद्यतन)

मेरे पास एक सुझाव अपरिचित प्रौद्योगिकी के प्रयोग पर काम कर रहा हूँ। मैंने कुछ डब्ल्यूसीएफ सेवाओं को लिखा है, लेकिन मैंने कभी भी कोई उन्नत कॉन्फ़िगरेशन नहीं किया है। यह jQuery में मेरा पहला गोता है। आधार है कि मैं 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()" /> 

आप मैं ध्यान दें जाएगा मैं jQuery 1.6.1 का उपयोग कर, 1.3 एफ नहीं ओम ट्यूटोरियल। ट्यूटोरियल मेरे बॉक्स पर ठीक चलाता है और जैसा कि अपेक्षित सब कुछ करता है। दुर्भाग्य से, मेरा कोड नहीं है। मैं जो भी मदद कर सकता हूं उसकी सराहना करता हूं।

ओह, और यहाँ फ़िडलर से अनुरोध की एक प्रति है:

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: सामग्री प्रकार एप्लिकेशन/जेसन; charset = utf-8 को टेक्स्ट/xml की अपेक्षा रखने वाली सेवा में भेजा गया था; charset = utf-8।

+0

तो बस परीक्षण के लिए, मैंने अपने GetBranches विधि, बूल टेस्ट में एक पैरामीटर जोड़ा। मैंने डेटा में पास करने के लिए अपना $ .ajax कॉल अपडेट किया: '{"test": "true"}' और अब मुझे ट्रेस में कोई त्रुटि मिलती है: सामग्री प्रकार एप्लिकेशन/जेसन; charset = utf-8 को टेक्स्ट/xml की अपेक्षा रखने वाली सेवा में भेजा गया था; charset = utf-8। मैंने ReceiveFormat = Json जोड़ा, लेकिन अभी भी त्रुटि प्राप्त करें। क्या web.config में कुछ है जो मुझे बदलने की जरूरत है? साथ ही, क्या उस विधि को शून्य करने का कोई सही तरीका है जिसमें कोई पैरामीटर नहीं है (मेरा मूल GetBranches)? –

+0

क्या आप जांच सकते हैं कि web.config में सेवा का नाम GeoDataService.svc फ़ाइल में सेवा नाम से मेल खाता है या नहीं? उन्हें बिल्कुल वही होना चाहिए (यानी, नामस्थान के साथ कक्षा का नाम) – carlosfigueira

+0

इस विचार के लिए धन्यवाद, कार्लोस। मेरा नेमस्पेस GeoDataServices है, और मेरा सेवा नाम GeoDataService है। जब मैं web.config में सेवा नाम को GeoDataServices.IGeoDataService में बदलता हूं तो यह वही त्रुटि फेंकता है (जब मैंने इसे GeoDataServices.GeoDataService में बदल दिया, तो उसने मुझे ट्रेस में इंटरफ़ेस का उपयोग करने के लिए कहा)। तो, या तो कॉन्फ़िगरेशन एक ही नया प्रोटोकॉल अपवाद देता है। –

उत्तर

7

स्वयं द्वारा कॉल में कोई समस्या नहीं प्रतीत होती है - आपको यह देखने के लिए enable tracing पर प्रयास करना चाहिए कि क्यों डब्ल्यूसीएफ आने वाले अनुरोध को खराब होने पर विचार कर रहा है। मैंने आपके जैसा एक जैसा कोड देखा है (नीचे देखें) और यह ठीक काम करता है। साथ ही, चूंकि सेवा उसी डोमेन (लोकलहोस्ट: 16062) से सेवा के रूप में आ रही है, इसलिए आपके पास कोई क्रॉस-डोमेन समस्या नहीं है।

अद्यतन: समाधान प्रश्न पर टिप्पणी थ्रेड के आधार पर

"नाम" web.config में < सेवा > तत्व की विशेषता पूरी तरह से योग्य नाम से मेल खाना चाहिए (यानी, नेमस्पेस + नाम) सेवा वर्ग (यानी, समान मूल्य .svc फ़ाइल में उपयोग किया जाता है)। अन्यथा आपको डिफ़ॉल्ट एंडपॉइंट आपकी सेवा के लिए जोड़ा जाएगा जो आप चाहते हैं कि हो सकता है या नहीं भी हो सकता है - डिफ़ॉल्ट रूप से आपको एक BasicHttp बाइंडिंग एंडपॉइंट मिलता है, जो कि आप अपने मामले में नहीं चाहते थे।

यह समस्या .NET Framework 4.0: Simplified Configuration में जोड़े गए फीचर का दुर्भाग्यपूर्ण दुष्प्रभाव है। .NET 3.5 तक, प्रत्येक सेवा को इसे कॉन्फ़िगर करने के लिए web.config पर एक प्रविष्टि की आवश्यकता होती है, और सबसे सरल अनुप्रयोगों (यानी, हैलो वर्ल्ड) के लिए कॉन्फ़िगरेशन फ़ाइलें बड़ी थीं। तो क्या हुआ कि, 4.0 के बाद से, यदि डब्ल्यूसीएफ को ऐसे नाम के साथ सेवा तत्व नहीं मिलता है जो सेवा के पूर्ण-योग्य नाम से मेल खाता है, तो यह खुशी से सोचता है कि आप डिफ़ॉल्ट कॉन्फ़िगरेशन का उपयोग करना चाहते हैं।यही कारण है कि पहले 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: संदेश का मुख्य भाग पढ़ा नहीं जा सकता क्योंकि यह खाली है। अब, मैं "कच्चे" वेब सेवा कॉल (आमतौर पर मैं नेट के लिए नेट जा रहा हूँ) के साथ बहुत अनुभव नहीं है, इसलिए यदि यह भी सामान्य एक अपवाद मदद करने के लिए है मैं नहीं जानता। –

+0

स्पष्टीकरण के लिए धन्यवाद, कार्लोस। डब्ल्यूसीएफ 4.0 बनाम 3.5 के बारे में नहीं पता था। फिर, वास्तव में आपकी मदद की सराहना करते हैं! –

संबंधित मुद्दे