热门话题:使用WCF实现SOA面向服务编程(三)—— 使用AJAX+WCF实现页面开发

来源:互联网 发布:windows nt 6.2 编辑:程序博客网 时间:2024/05/20 15:11

在上一篇讲到,如果将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)

 

原创粉丝点击