扩展webservice

描述:

最近一个winform项目刚开发完成。采用c/s架构。闲来把一些技术点整理下了。

做项目之前调研了客户的电脑 .客户端机子性能一般,而且都是基于xp。

这些客观存在的问题,注定了实现过程中必须考虑客户端性能,frmaework版本等因素。

基于这些原因 我选择了2.0版本的 webservice。没有选择3.5版本的wcf,原因主要还是担心客户端环境的复杂度。使用2.0会保险点。(妈蛋,2.0写的各种蛋疼,没有语法糖很不爽)

 

细节:

1.首先肯定是要通过工具生成WSProxy.

2.webservice是基于请求request 和 返回 response来交互的。我将传输对象封装成实体,

RequestHead 对象是请求头,存放基础信息。
XObject 是传输的对象。原先是直接用object代替的。但是我们项目数据量比较大,所以对ojbect进行封装了,XObject在传输过程中主要是负责解析的。目前解析有三种形式:XML(ws标准), Json ,字节,目前我们采用的是json。
   /// <summary>
    /// 请求参数
    /// </summary>
    [GeneratedCode("System.Xml", "4.0.30319.18408")]
    [Serializable]
    [DebuggerStepThrough]
    [DesignerCategory("code")]
    [XmlType(Namespace = "http://tempuri.org/")]
    public class Request
    {
        private readonly RequestHead headField = new RequestHead();
        private readonly XObject xbodyField = new XObject();

        /// <summary>
        /// 请求的 头信息
        /// </summary>
        public RequestHead Head
        {
            get { return headField; }
            set { headField.CopyFrom(value); }
        }

        /// <summary>
        /// 请求的 具体值
        /// </summary>
        [XmlIgnore, SoapIgnore, JsonIgnore]
        public object Body
        {
            get { return xbodyField.Value; }
            set { xbodyField.Value = value; }
        }

        /// <summary>
        ////// </summary>
        public XObject XBody
        {
            get { return xbodyField; }
            set { xbodyField.CopyFrom(value); }
        }
    }

    /// <summary>
    /// 请求 头信息
    /// </summary>
    [GeneratedCode("System.Xml", "4.0.30319.18408")]
    [Serializable]
    [DebuggerStepThrough]
    [DesignerCategory("code")]
    [XmlTypeAttribute(Namespace = "http://tempuri.org/")]
    public class RequestHead
    {
        public RequestHead()
        {
            RequestID = Guid.NewGuid().ToString().ToUpper();
        }

 
        /// <summary>
        /// 用户ID
        /// </summary>
        //[XmlAttribute]
        public UserInfo User { get; set; }
        /// <summary>
        /// 请求GUID
        /// </summary>
        //[XmlAttribute]
        public string RequestID { get; set; }



        /// <summary>
        /// 请求的函数
        /// </summary>
        //[XmlAttribute]
        public string Method { get; set; }
        /// <summary>
        /// 异步请求
        /// </summary>
        //[XmlAttribute]
        public bool IsAsync { get; set; }




        /// <summary>
        /// 从 另外的对象 复制属性值
        /// </summary>
        public void CopyFrom(RequestHead head)
        {
            //UserID = head == null ? string.Empty : head.UserID;
            RequestID = head == null ? string.Empty : head.RequestID;
            //ClientIP = head == null ? string.Empty : head.ClientIP;
            Method = head == null ? string.Empty : head.Method;
            IsAsync = head == null ? false : head.IsAsync;
            User = head == null ? null : head.User;
        }

    }
  /// <summary>
    /// 响应结果
    /// </summary>
    [GeneratedCode("System.Xml", "4.0.30319.18408")]
    [Serializable]
    [DebuggerStepThrough]
    [DesignerCategory("code")]
    [XmlTypeAttribute(Namespace = "http://tempuri.org/")]
    public class Response
    {
        private readonly ResponseHead headField = new ResponseHead();
        private readonly XObject xbodyField = new XObject();

        /// <summary>
        /// 响应的 头信息
        /// </summary>
        public ResponseHead Head
        {
            get { return headField; }
            set { headField.CopyFrom(value); }
        }

        /// <summary>
        /// 响应的 具体值
        /// </summary>
        [XmlIgnore, SoapIgnore, JsonIgnore]
        public object Body
        {
            get { return xbodyField.Value; }
            set { xbodyField.Value = value; }
        }

        /// <summary>
        ////// </summary>
        public XObject XBody
        {
            get { return xbodyField; }
            set { xbodyField.CopyFrom(value); }
        }


        public Response(){ }
        public Response(RequestHead requestHead)
        {
            this.Head.UserID = requestHead.User.UserID;
            this.Head.RequestID = requestHead.RequestID;
        }
    }

    /// <summary>
    /// 响应 头信息
    /// </summary>
    [GeneratedCode("System.Xml", "4.0.30319.18408")]
    [Serializable]
//    [DebuggerStepThrough]
    [DesignerCategory("code")]
    [XmlTypeAttribute(Namespace = "http://tempuri.org/")]
    public class ResponseHead
    {
        public ResponseHead()
        {
            ResultCode = ResultCode.UnKown;
        }

        /// <summary>
        /// 请求版本
        /// </summary>
        [XmlAttribute]
        public string Version { get; set; }
        /// <summary>
        /// 用户ID
        /// </summary>
        [XmlAttribute]
        public string UserID { get; set; }
        /// <summary>
        /// 请求GUID
        /// </summary>
        [XmlAttribute]
        public string RequestID { get; set; }
        

        /// <summary>
        /// 结果标志
        /// </summary>
        [XmlAttribute]
        public ResultCode ResultCode { get; set; }
        /// <summary>
        /// 结果标志
        /// </summary>
        [XmlAttribute]
        public string ResultNo { get; set; }
        /// <summary>
        /// 失败信息
        /// </summary>
        [XmlAttribute]
        public string ResultMsg { get; set; }
        /// <summary>
        /// 时间戳
        /// </summary>
        [XmlAttribute]
        public string Timestamp { get; set; }


        /// <summary>
        /// 利用请求给结果的头部信息赋值
        /// </summary>
        /// <param name="header">请求头对象</param>
        public void SetHeaderInfo(RequestHead header)
        {
            this.RequestID = header.RequestID;
            this.UserID = header.User.UserID;
        }
        /// <summary>
        /// 设置结果信息
        /// </summary>
        /// <param name="resultcode">结果类型</param>
        /// <param name="resultno">失败代号</param>
        /// <param name="resultmsg">失败信息</param>
        public void SetResult(ResultCode resultcode, long resultno, string resultmsg)
        {
            this.Timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fffff");
            this.ResultCode = resultcode;
            this.ResultNo = resultno.ToString();
            if (!string.IsNullOrEmpty(resultmsg)) this.ResultMsg = resultmsg;
        }
 
        /// <summary>
        /// 设置结果信息
        /// </summary>
        /// <param name="resultcode">结果类型</param>
        /// <param name="resultno">失败代号</param>
        /// <param name="resultmsg">失败信息</param>
        public void SetFailResult(ResultCode resultcode, string resultno, string resultmsg)
        {
            this.Timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fffff");
            this.ResultCode = resultcode;
            this.ResultNo = resultno;
            if (!string.IsNullOrEmpty(resultmsg)) this.ResultMsg = resultmsg;
        }


        /// <summary>
        /// 从 另外的对象 复制属性值
        /// </summary>
        public void CopyFrom(ResponseHead head)
        {
            Version = head == null ? string.Empty : head.Version;
            UserID = head == null ? string.Empty : head.UserID;
            RequestID = head == null ? string.Empty : head.RequestID;
            ResultCode = head == null ? ResultCode.Fail : head.ResultCode;
            ResultNo = head == null ? string.Empty : head.ResultNo;
            ResultMsg = head == null ? string.Empty : head.ResultMsg;
            Timestamp = head == null ? string.Empty : head.Timestamp;
        }
    }

 

3.创建ws基类,利用模板模式能够很好的抽象出方法的共性。

    /// <summary>
    /// WebService基类,所有继承者必须实现Request方法
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    public abstract class WSBase : WebService
    {
        ///// <summary>
        ///// IP白名单
        ///// </summary>
       internal static string IPList = "";

        /// <summary>
        /// WebService基类构造函数
        /// </summary>
        static WSBase()
        {    if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["IPList"].ToString()))
                    IPList = ConfigurationManager.AppSettings["IPList"]; 
        }
        
        /// <summary>
        /// 接收用户请求并返回相应结果
        /// </summary>
        /// <param name="request">请求对象</param>
        [WebMethod(EnableSession = false)]
        public Response Request(Request request)
        {
            try
            {
                var response = new Response();

                if (!Auth(request.Head))
                {
                    
                }
                 
                //判断反序列化是否成功
                if (request == null)
                {
   
                }
  
                //todo:安全校验iplist


                return RequestDeal(request,response);
            }
            catch (SoaException soaExp)
            { 
                Log.Error(soaExp.Message,soaExp);

                response.Head.SetHeaderInfo(request.Head);
                response.Head.SetResult(ResultCode.Fail, soaExp.ResultNo, soaExp.Message);
                return response;
            }
            catch (Exception exp)
            {          
                Log.Error(exp.Message, exp);
                response.Head.SetHeaderInfo(request.Head);
                response.Head.SetResult(ResultCode.Fail, 500, exp.Message);
                return response;
            }
        }

        /// <summary>
        /// 请求处理方法
        /// </summary>
        protected abstract Response RequestDeal(Request request, Response response);



        /// <summary>
        ///  通过代理,获取客户端真实的IP地址
        /// </summary>
        /// <returns>返回客户端真实的IP地址</returns>
        private static string GetClientIPAddress()
        {return ip;
        }

        /// <summary>
        /// 授权
        /// </summary>
        /// <returns></returns>
        private bool Auth(RequestHead head)
        {
            return true; 
        }

    }

 

实现类中实现 RequestDeal方法

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。 
    // [System.Web.Script.Services.ScriptService]
    public class TktService : WSBase
    {
        protected override Response RequestDeal(Request request,Response response)
        {


            try
            {
                object result = null;
                switch (request.Head.Method)
                {


                    case "Np":
                        new NpService().Np((HashRequest)request.Body, ref response);
                        break;
                    //case "GetSpByGuest":
                    //    new HjdService().GetByGuestCard((HashRequest)request.Body, ref response);
                    //    break;
                    case "GetSpBy": //根据查询对象或者售票信息
                        new BuPiaoService().GetSpBy((BuPiaoQModel)request.XBody, ref response);
                        break;
       }
 
                response.Head.SetHeaderInfo(request.Head);
                response.Head.Timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fffff");

            }
   
            catch (Exception ex)
            {
                string logMsg = string.Format("ts服务出错: 函数名:{0},错误消息:{1}", request.Head.Method,ex.Message);
                response.Head.SetFailResult(ResultCode.Fail, "110", logMsg );
                Log.Error(logMsg,ex);
            }
            return response;
        }


  
    }

 

4.客户端如何调用服务端方法

2.0环境下没有泛型,只能用object代替

public  class WSClient
    {

      public static string CrsServiceURL = "CrsServiceURL";
       public static string TktServiceURL = "TktServiceURL";

 
       public static Response GetOData(string url, string method, object requestBody, UserInfo user)
       {
           WSProxy proxy = new WSProxy();
           proxy.Url = WSProxy.GetWebServiceUrl(url);

           Request request = new Request();
           request.Head.Method = method;
           request.Head.User = user;
           request.Body = requestBody;

           return proxy.Request(request);
       }
       public static object GetCrsData(string method, object requestBody, UserInfo user )
       {
           var response =GetOData(OtherServiceURL, method, requestBody,user);
           //if (response.Head.ResultCode==ResultCode.Success)
           //{
          return   response.Body;
            

       }
       public static object GetTsData(string method, object requestBody, UserInfo user )
       {

           var response = GetOData(TktServiceURL, method, requestBody,user);
        return   response.Body;
 } }

 

 

5.OK基本就是这样。目前服务大概80多个,测试服务是非常耗时的。为了实现服务的本地调试,我们写了个类,针对开发过程中不启用服务直接调用方法的class。

项目过程中,前期对技术的难点、消耗的时间最好都做个有效的评估。尽量在前期把技术问题处理掉。

转载于:https://www.cnblogs.com/yuanhuaming/p/4105115.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值