1. 程式人生 > >Ajax呼叫RESTful WCF

Ajax呼叫RESTful WCF

這幾天在學習RESTful WCF 感覺呼叫起來比較舒服,就是不能在vs裡面直接生成類了。。。
首先是RESTful WCF的構建

.svc 後面要加上

Factory="System.ServiceModel.Activation.WebServiceHostFactory

先是介面檔案:

[ServiceContract]
public interface ITestWCF
{
    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "DoWork")]
    bool DoWork();
[OperationContract] [WebInvoke(ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "WebInvokeWithNoArgs", Method = "POST")] ReturnObj WebInvokeWithNoArgs(); [OperationContract] [WebInvoke(ResponseFormat = WebMessageFormat.Json, RequestFormat =WebMessageFormat.Json
,BodyStyle =WebMessageBodyStyle.WrappedRequest, UriTemplate = "WebInvokeWithArgs", Method = "POST")] ReturnObj WebInvokeWithArgs(string str); [OperationContract] [WebGet(ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, UriTemplate = "WebGetWithNoArgs")] ReturnObj WebGetWithNoArgs();
[OperationContract] [WebGet(ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, UriTemplate = "WebGetWithArgs/{str}")] ReturnObj WebGetWithArgs(string str); }

然後是實現檔案

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class TestWCF : ITestWCF
{
    public bool DoWork()
    {
        return true;
    }

    public ReturnObj WebGetWithArgs(string str)
    {
        return new ReturnObj(str);
    }

    public ReturnObj WebGetWithNoArgs()
    {
        return new ReturnObj("Get Success!");
    }

    public ReturnObj WebInvokeWithArgs(string str)
    {
        return new ReturnObj(str);
    }

    public ReturnObj WebInvokeWithNoArgs()
    {
        return new ReturnObj("Invoke Success!");
    }
}

解釋一下
WebInvoke 跟WebGet的區別可以理解為 一個是POST,一個是GET。但是WebInvoke的Method也可以為GET,WebGet只能是Get
ResponseFormat = WebMessageFormat.Json 這個就是Response的時候採用Json的方式
UriTemplate 這個可以理解一個地址 比如 UriTemplate = “WebInvokeWithNoArgs” 你可以用 http://xxx.xxx.xxx/xxx.svc/WebInvokeWithNoArgs 來進行訪問。
當Method為GET,且有引數的時候,可以採用UriTemplate =“方法地址/{引數}/{引數}”的方式來向WCF傳遞引數。當然,POST還是老老實實寫Json吧~
BodyStyle =WebMessageBodyStyle.WrappedRequest 這個為包裝Request,這個筆者也沒有弄清具體的功能,只是沒有這句話的時候 ajax返回的 status為200 加上就好了。。。
BodyStyle = WebMessageBodyStyle.WrappedResponse 這個為包裝Response,就是在ajax得到Json的時候會有{“WebInvokeWithNoArgsResult”:{“str”:”Invoke Success!”}}(有) {“str”:”Invoke Success!”}(無)
WebMessageBodyStyle還有兩個就是Bare和Wrapped。Bare是全不包裝,Wrapped是兩個都包裝。

然後是傳送的類:

[DataContract]
public class ReturnObj
{
    [DataMember(Order = 0)]
    public string str;
    public ReturnObj(string args)
    {
        str = args;
    }
}

如果想要在json中加入一個欄位 就用 DataMember 來標記。如果不加DataMember,json中是看不見這個欄位的!而且是否可見跟private public無關。
Order為轉換為json的時候,欄位的順序。當有Order的時候,小的在前面

    [DataMember(Order = 0)]
    private string str;
    [DataMember(Order = 1)]
    public int num;
    [DataMember(Order = 2)]
    public bool ok;

結果就是{“str”:”Invoke Success!”,”num”:1,”ok”:true}
然後貌似不加Order的在加Order的前面(這個不確定,做了幾次試驗貌似是這樣)

如果是基本型別(比如bool什麼的)而且沒有選擇包裝Response的時候就是單純的值,並沒有json格式

然後是配置檔案

 <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="TestWCFBehavior"></behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
        multipleSiteBindingsEnabled="true" />
    <services>
      <service name="TestWCF">
        <endpoint address="" behaviorConfiguration="TestWCFBehavior" binding="webHttpBinding" contract="ITestWCF"></endpoint>
      </service>
    </services>
  </system.serviceModel>

配置檔案一定要認真的檢查有沒有漏的,因為配置檔案寫錯了不是服務直接掛了就是訪問不到。。。

然後是如何用Ajax呼叫WCF了。。。
如果用jQuery的話,就是$.ajax()
POST:

$.ajax({
            url: "../TestWCF.svc/WebInvokeWithArgs",
            type: "POST",
            contentType: "text/json",
            asnyc: "false",
            data: '{"str":"Invoke Test"}',
            dataType: 'json',
            success: function (resultObj) {
                var resultStr = String(JSON.stringify(resultObj));
                alert(resultStr);
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert(XMLHttpRequest.status);
                alert(XMLHttpRequest.readyState);
                alert(textStatus);
            }
        });

GET

 $.ajax({
            url: "TestWCF.svc/WebGetWithArgs/Get Test",
            type: "Get",
            asnyc: false,
            dataType: 'json',
            success: function (resultObj) {
                var resultStr = String(JSON.stringify(resultObj));
                alert(resultStr);
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert(XMLHttpRequest.status);
                alert(XMLHttpRequest.readyState);
                alert(textStatus);
            }
        });

注意url這三個字母不能大寫-_-||

如果手寫ajax的話

<script type="text/javascript">
    var xmlHttp;
    //下面這個函式根據是否為IE瀏覽器來生成不同ajax物件
    function createxmlHttpRequest() {
        if (window.ActiveXObject) {
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        } else if (window.XMLHttpRequest) {
            xmlHttp = new XMLHttpRequest();
        }
    }
    //POST
    function doPost() {
        var url = "TestWCF.svc/WebInvokeWithArgs";
        var data = '{"str":"Invoke Test"}';//注意為json格式
        createxmlHttpRequest();
        xmlHttp.open("POST", url, false);//open(方法,地址,同步)
        xmlHttp.setRequestHeader("Content-Type", "text/json");
        xmlHttp.onreadystatechange = function () {
           if ((xmlHttp.readyState == 4) && (xmlHttp.status == 200)) {
                alert(xmlHttp.responseText);
            }
            else {
                alert(xmlHttp.status);
            }
        }
        xmlHttp.send(data);
        return false;
    }
    //GET
    function doGet() {
        var url = "TestWCF.svc/WebGetWithNoArgs";
        createxmlHttpRequest();
        xmlHttp.onreadystatechange = function () {
            if ((xmlHttp.readyState == 4) && (xmlHttp.status == 200)) {
                alert(xmlHttp.responseText);
            }
            else {
                alert(xmlHttp.status);
            }
        }
        xmlHttp.open("GET", url, false);
        xmlHttp.send("");
        return false;
    }
</script>

注意先設定onreadystatechange 的處理函式再send就行了~

至於在C#客戶端那面就可以用WebHttpRequest和WebHttpResponse來處理
GET

        static void Main(string[] args)
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost:65143/testwcf.svc/WebGetWithNoArgs");
            req.Method = "GET";
            HttpWebResponse res = (HttpWebResponse)req.GetResponse();
            StreamReader sr = new StreamReader(res.GetResponseStream());
            Console.WriteLine(sr.ReadToEnd());

        }

POST

        static void Main(string[] args)
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost:65143/testwcf.svc/WebInvokeWithArgs");
            req.Method = "POST";
            req.ContentType = "application/json";
            string data = @"{""str"":""From C#""}";
            byte[] SendData = Encoding.Default.GetBytes(data);
            req.ContentLength = SendData.Length;
            req.GetRequestStream().Write(SendData, 0, SendData.Length);
            req.GetRequestStream().Close();
            HttpWebResponse res = (HttpWebResponse)req.GetResponse();
            StreamReader sr = new StreamReader(res.GetResponseStream());
            Console.WriteLine(sr.ReadToEnd());

        }