使用WCF實現SOA面向服務編程——使用AJAX+WCF服務頁面開發

作者: 風塵浪子  來源: 博客園  發布時間: 2011-04-06 11:23  閱讀: 3092 次  推薦: 0   原文鏈接   [收藏]  

  在上一篇講到,如果將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程序集:

 
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); //通過自定義的GetType(Communicate o)方法加載類

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); //將結果轉化為JSON
else
return null;
}

else
return null;
}


return null;
}


//因為結果供于Ajax頁面使用,所以將結果轉化為Json形式
//其實當項目已經啟動AJAX,在默認情況下結果會自動轉化為JSON,但因為不能事先預知返回的類型,所以把返回類型定為String
//此處手動將結果轉換成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進行客戶端與服務器端的通訊,自此之后,每逢你進行簡單的頁面開發時都可使用此方式。好處在于頁面無 需了解數據是從何處獲取的,因為數據存取和頁面可以處于不同的線程池,所以這樣做可以把服務器壓力降到最低。同時你可以使用異步的服務,來進一步提高數據 站點的線程池效率。(異步服務可參考ASP.NET服務器端多線程設計

 

0
0
 
標簽:WCF SOA AJAX
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()