• 扩展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。

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

  • 相关阅读:
    由DataSet导出生成excel的几种方法
    linq日期查询
    上传文件
    C#获取文件的MD5值
    设置图层透明度
    highcharts中的x轴如何显示时分秒时间格式
    axios中文文档
    如何在 Highcharts 图中当所占百分比为 0 时不显示0%
    一个简易的选择小时(时分秒)的插件
    三分钟上手Highcharts简易甘特图
  • 原文地址:https://www.cnblogs.com/yuanhuaming/p/4105115.html
Copyright © 2020-2023  润新知