熱門話題:使用WCF實現SOA面向服務編程(三)—— 使用AJAX+WCF實現頁面開發

在上一篇講到,如果將BLL層的每一個類都轉化爲*.svc,這是一個不實在的想法。它會使服務變化複雜,難於管理。

這時候,我們第一時間想到的是23個簡單開發模式中的Factory,在這裏,Factory正好派上用場。我們把這個Factory稱之爲管道(pipeline) ,通過這個管道客戶端可以隨意調用服務器BLL層裏面的類。

 

(關於管道的概念,建議參考Cory Isaacson的傑作《多核應用架構關鍵技術—軟件管道與soa》)

 

當你使用B/S方式開發UI層時,只要瞭解此開發模式,使用Ajax加上WCF裏面的WebHttpBinding綁定和WebHttpBehavior行爲,可以說是天衣無縫的組合。

 

首先,開發一個數據契約,其中包括程序集名稱,類名,構造函數的參數,方法名,方法中的參數

[DataContract]
public class Communication
{
    [DataMember]
    public string Assembly
    {
        get;
        set;
    }

    [DataMember]
    public string Class
    {
        get;
        set;
    }

    [DataMember]
    public object[] ConstructedParameters
    {
        get;
        set;
    }

    [DataMember]
    public string Method
    {
        get;
        set;
    }

    [DataMember]
    public object[] Parameters
    {
        get;
        set;
    }
}

 

爲了證明客戶端可以通過Ajax能夠直接調用服務器WCF,我們先在MyAssembly程序集裏面開發一個User類,然後生成MyAssembly.dll程序集作爲測試。

namespace MyAssembly
{

    [DataContract]
    public class User
    {
        [DataMember]
        public int ID
        { get; set; }

        [DataMember]
        public string Name
        { get; set; }

        [DataMember]
        public int Age
        { get; set; }
    }


    public class UserManager
    {
        public List<User> GetList()
        {
            List<User> entities = new List<User>();
            User user = new User();
            user.ID = 0;
            user.Age = 26;
            user.Name = "Leslie";
            entities.Add(user);
            return entities;
        }
    }
}

 

好,現在已經做好準備,現在我們新建一個“啓動了AJAX的WCF服務”

 

 

 

[ServiceContract(Namespace = "myNamespace")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]   

//注意必須將RequirementsMode設置爲AspNetCompatibilityRequirementsMode.Allowed

public class Service
{
    private static Hashtable assemblies = new Hashtable();
    private static Hashtable types = new Hashtable();

    [OperationContract]
    [WebGet]

    // 要使用 HTTP GET,請添加 [WebGet] 特性。
    public string DoWork(Communication communication)
    {
        Type classType = GetType(communication);
       
        if (classType != null)
        {
            object reflectedObject;
            if (communication.ConstructedParameters != null)
                reflectedObject = Activator.CreateInstance(classType, communication.ConstructedParameters);
            else
                reflectedObject = Activator.CreateInstance(classType);

            MethodInfo methodInfo = classType.GetMethod(communication.Method);

            if (methodInfo != null)
            {
                object data = methodInfo.Invoke(reflectedObject, communication.Parameters);
                if (data != null)
                    return Formate(data, methodInfo.ReturnType);
                else
                    return null;
            }
            else
                return null;
        }

        return null;
    }

 

    //因爲結果供於Ajax頁面使用,所以將結果轉化爲Json形式

    //其實本項目已經是啓動了AJAX,所以在默認情況下結果會自己轉化爲JSON,但因爲不能事先實現返回的類型,所以

   //此處手動將結果轉換成JSON字符串

    public string Formate(object data,Type type)
    {
        using (Stream stream = new MemoryStream())
        {
            DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(type);
            jsonSerializer.WriteObject(stream, data);

            byte[] byteData = new byte[stream.Length];
            stream.Seek(0,0);
            stream.Read(byteData, 0, (int)stream.Length);
            stream.Close();
            return Encoding.UTF8.GetString(byteData);
        }
    }

 

    //加載程序集

    private Assembly GetAssembly(Communication communication)

    {
        if (!assemblies.ContainsKey(communication.Assembly))
        {
            Assembly myAssembly = Assembly.Load(communication.Assembly);
            assemblies.Add(communication.Assembly, myAssembly);
        }
        return (Assembly)assemblies[communication.Assembly];
    }

 

    //加載類

    private Type GetType(Communication communication)
    {
        if (!types.ContainsKey(communication.Class))
        {
            Assembly assembly=GetAssembly(communication);
            types.Add(communication.Class, assembly.GetType(communication.Class));
        }
        return (Type)types[communication.Class];
    }
}

 

服務器端會自動爲你配置.config文件

<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
  <behaviors>
   <endpointBehaviors>
    <behavior name="ServiceAspNetAjaxBehavior">
     <enableWebScript />               //注意啓動enableWebScript
    </behavior>
   </endpointBehaviors>
   <serviceBehaviors>
    <behavior name="ServiceBehavior">
     <serviceMetadata httpGetEnabled="true" />        //注意此處啓動了httpGetEnabled
     <serviceDebug includeExceptionDetailInFaults="false" />
    </behavior>
   </serviceBehaviors>
  </behaviors>
  <services>
   <service name="Service" behaviorConfiguration="ServiceBehavior">
    <endpoint address="" behaviorConfiguration="ServiceAspNetAjaxBehavior"
     binding="webHttpBinding " contract="Service" />       //注意綁定的是webHttpBinding
     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
   </service>
  </services>
 </system.serviceModel>
</configuration>

 

好吧,現在萬事俱備的時候,讓我們開發一個測試頁面

<body>

 <form id="form1" runat="server">
     <script type="text/javascript">
         window.onload = function () {
             myNamespace.Service.set_path("http://localhost:8080/Service.svc/");
             var communication = { "Assembly": "MyAssembly", "Class": "MyAssembly.UserManager", "ConstructedParameters":      null, "Method": "GetList", "Parameters": null };

            //把Communication參數轉化爲Json形式
             myNamespace.Service.DoWork(communication, OnSucceed, OnFail, null);
         }

         function OnSucceed(result) {
             if (result != null)
                 alert(result);
         }

         function OnFail(result) {
             alert(result);
         }
    </script>
    </form>
</body>

 

測試成功:

 

 

 

 

恭喜你終於學會如何使用Ajax+WCF進行頁面數據顯示了。

你應該初步瞭解到如何使用管道Pipeline進行客戶端與服務器端的通訊,自此之後,每逢你進行簡單的網站開發時都可使用此方式。好處在於頁面無需瞭解數據是從何處獲取的,數據存儲的Web服務跟網站可以處於不同的服務器或者不同的IIS應用程序池,所以這樣做可以把服務器壓力降到最低。同時你可以使用異步的服務,來進一步提高數據站點的線程池效率。(異步服務可參考ASP.NET服務器端多線程設計

 

即便是這樣,此開發方式只適合用於普通的頁面開發,還不算是完善,因爲SOA是面向多方面的。試想一下如果系統調用的是公司的內部管理系統的服務,其中必然會夾雜着複雜的工作流,其處理方式與返回結果也有不同,全部使用JSON作爲返回值也會造成不必要的性能損耗,這時候應該怎麼決定呢?

下面就爲大家開始講解一下使用Web服務與WF結合開發以發揮其強大功能。

 

對NET系統開發有興趣的朋友,請加入QQ羣:NET技術開發聯盟   59557329 一起討論  點擊這裏加入此羣

 

熱門話題:使用WCF實現SOA面向服務編程(一)——SOA的概念
熱門話題:使用WCF實現SOA面向服務編程(二)——實現簡單的WCF開發實例
熱門話題:使用WCF實現SOA面向服務編程(三)——使用AJAX+WCF服務頁面開發
熱門話題:使用WCF實現SOA面向服務編程(四)—— 通過Web服務調用Workflow工作流(基礎實例) 
熱門話題:使用WCF實現SOA面向服務編程(五)—— 通過Web服務調用Workflow工作流(開發持久化工作流)
熱門話題:使用WCF實現SOA面向服務編程(六)—— 通過InvokeWebServiceActivity在Workflow工作流中調用Web服務
熱門話題:使用WCF實現SOA面向服務編程(七)—— WF與WCF互相調用(利用ReceiveActivity把WF發佈爲WCF)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章