asp.net 自定义的模板方法接口通用类型

本来想写这个帖子已经很久了,但是公司事情多,做着做着就忘记了。公司因为需要做接口,而且用的还是asp.net的老框架,使用Handler来做,没得办法,自己照着MVC写了一个通过的接口操作模板。

上送json数据,返回的也是json数据。可以像MVC一样自动绑定并可以进行DataAnnotations验证。尽量达到在业务逻辑处理区域不用对上送参数做过多的获取和判断,能一次搞定就一次搞定。

话不多说,上代码!!!

BaseClass:用作接口参数的基类。接口参数类型可以继承该类,也可以不继承,或自己定义其他基类。

public abstract class BaseClass { }

EmptyClass:一个空类。当做一个参数类型传入到接口中,占用地方而已。

public class EmptyClass : BaseClass { }

ModelError:错误消息载体类型。

    [Serializable]
    public class ModelError {
        public ModelError(Exception exception) : this(exception, null) { }

        public ModelError(string errorMessage) {
            this.ErrorMessage = errorMessage ?? string.Empty;
        }

        public ModelError(Exception exception, string errorMessage) : this(errorMessage) {
            if (exception == null)
                throw new ArgumentNullException("exception");
            this.Exception = exception;
        }

        public Exception Exception { get; private set; }
        public string ErrorMessage { get; private set; }
    }  

ModelErrorCollection:错误消息载体集合。

    [Serializable]
    public class ModelErrorCollection : Collection<ModelError> {
        public void Add(string errorMessage) {
            base.Add(new ModelError(errorMessage));
        }

        public void Add(Exception exception) {
            base.Add(new ModelError(exception));
        }
    }

ModelState:模型绑定状态。

    /// <summary>
    /// 模型绑定状态
    /// </summary>
    [Serializable]
    public class ModelState {
        private ModelErrorCollection _errors = new ModelErrorCollection();
        public bool IsValid {
            get {
                return _errors.Count == 0;
            }
        }
        public ModelErrorCollection Errors {
            get {
                return _errors;
            }
        }
    }

ModelBinder:模型绑定抽象类,需要继承此抽象类。用来绑定上送参数并验证的基类。

    /// <summary>
    /// 模型绑定抽象类,需要继承此抽象类。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class ModelBinder<T> where T : class {
        protected ModelState _modelState;

        /// <summary>
        /// 模型绑定状态
        /// </summary>
        public ModelState ModelState {
            get {
                if (_modelState == null)
                    _modelState = new ModelState();
                return _modelState;
            }
        }

        /// <summary>
        /// 绑定操作
        /// </summary>
        /// <returns></returns>
        public abstract T Binder();

        /// <summary>
        /// 验证实体数据合法性。如果有错误,请在ModelState参数中获取。
        /// </summary>
        /// <param name="entity"></param>
        protected void Valide(object entity) {
            if (entity == null)
                return;
            //获取T类型的所有公共属性
            Type type = entity.GetType();
            PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);

            if (properties != null && properties.Count() > 0) {
                //针对每一个公共属性,获取其特性
                foreach (var property in properties) {
                    //如果当前属性为一个自定义类型
                    if (property.PropertyType != typeof(object) && Type.GetTypeCode(property.PropertyType) == TypeCode.Object) {
                        this.Valide(property.GetValue(entity, null));
                    }
                    else
                        ValideProperty(entity, property);

                    if (!_modelState.IsValid)
                        break;
                }
            }
        }

        /// <summary>
        /// 验证属性的每一个特性约束
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="property"></param>
        private void ValideProperty(object entity, PropertyInfo property) {
            if (entity != null && property != null) {
                var attributes = property.GetCustomAttributes(typeof(ValidationAttribute), false);
                foreach (ValidationAttribute attribute in attributes)
                    ValidatePropertyAttribute(entity, property, attribute);
            }
        }

        /// <summary>
        /// 使用特性对属性进行验证
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="property"></param>
        /// <param name="attribute"></param>
        private void ValidatePropertyAttribute(object entity, PropertyInfo property, ValidationAttribute attribute) {
            if (entity != null && property != null && attribute != null) {
                //找到该属性
                //注明:每一个函数都应当具有独立性.
                PropertyInfo currentProperty = entity.GetType().GetProperties().Where(p => p.Name == property.Name).FirstOrDefault();

                //判断当前特性是否有IsRequiredInstance字段,这是自定义的特性,用于验证同一个实例中两个不同共有属性的值
                PropertyInfo[] pros = attribute.GetType().GetProperties();
                if (pros.Where(it => it.Name == "IsRequiredInstance" && it.PropertyType == typeof(bool)).FirstOrDefault() != null)
                    attribute.GetType().GetProperty("Instance").SetValue(attribute, entity, null);

                if (currentProperty != null) {
                    var value = currentProperty.GetValue(entity, null);
                    if (!attribute.IsValid(value))
                        _modelState.Errors.Add(attribute.ErrorMessage);
                }
            }
        }

    }

BaseHandler:一般处理逻辑的基类。

    /// <summary>
    /// 一般处理逻辑的基类。
    /// </summary>
    /// <typeparam name="T">请求参数模型</typeparam>
    /// <typeparam name="R">返回参数模型</typeparam>
    public abstract class BaseHandler<T, R> : ModelBinder<T> where T : class where R : class {
        protected readonly ILog log;
        public BaseHandler() {
            log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        }
        public BaseHandler(string typeName) {
            if ((typeName ?? "").Trim() != "")
                log = LogManager.GetLogger(typeName);
            else
                log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        }

        /// <summary>
        /// 处理接口API消息
        /// </summary>
        /// <returns></returns>
        public abstract R Process();

        /// <summary>
        /// 真正需要处理的接口逻辑
        /// </summary>
        /// <param name="param">客户端传过来的请求参数</param>
        /// <returns></returns>
        protected abstract R DoWork(T param);
    }

IndexHandler:一般业务接口的模板方法处理器。该接口是基础性接口,如果有其他业务需求,请自行另外自定义或继承该接口。

    /// <summary>
    /// 一般业务接口的模板方法处理器。
    /// 该接口是基础性接口,如果有其他业务需求,请自行另外自定义或继承该接口。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class IndexHandler<T> : BaseHandler<T, BaseResponseResult> where T : class {
        public IndexHandler() : base() { }
        public IndexHandler(string typeName) : base(typeName) { }

        /// <summary>
        /// 对实体模型进行绑定和参数的特性验证
        /// </summary>
        /// <returns></returns>
        public override T Binder() {
            //初始化模型
            T rc = default(T);

            try {
                //初始化ModelState
                if (_modelState == null)
                    _modelState = new ModelState();
                else
                    _modelState.Errors.Clear();

                //获取数据
                Stream stream = HttpContext.Current.Request.InputStream;
                stream.Seek(0, SeekOrigin.Begin);
                byte[] buffer = new byte[stream.Length];
                int count = stream.Read(buffer, 0, buffer.Length);
                if (count > 0) {
                    string requestParam = Encoding.UTF8.GetString(buffer);
                    //绑定数据
                    rc = new JavaScriptSerializer().Deserialize<T>(requestParam);
                    if (rc != null) {
                        //验证数据合法性
                        base.Valide(rc);
                    }
                    else
                        _modelState.Errors.Add("绑定数据失败!");
                }
                else
                    _modelState.Errors.Add("请求参数为空!");
            }
            catch (Exception ex) {
                _modelState.Errors.Add("绑定数据出现错误!");
            }

            return rc;
        }

        /// <summary>
        /// 处理接口API消息
        /// </summary>
        /// <returns></returns>
        public override BaseResponseResult Process() {
            BaseResponseResult rc = new BaseResponseResult(ErrorCode.OperationError);

            try {
                //绑定请求参数
                T requestParam = Binder();
                //开启逻辑操作
                if (_modelState.IsValid)
                    rc = DoWork(requestParam);
                else {
                    StringBuilder sbuilder = new StringBuilder();
                    foreach (var error in _modelState.Errors)
                        sbuilder.Append(error.ErrorMessage);

                    rc.SetResult(ErrorCode.InvalideParameter, sbuilder.ToString());
                }
            }
            catch (Exception ex) {
                rc.SetResult(ErrorCode.SystemError);
                rc.returnData = null;
                log.Error("Process", ex);
            }

            return rc;
        }
    }

BaseResponseResult:返回结果。

    /// <summary>
    /// 返回结果
    /// </summary>
    public class BaseResponseResult {
        public BaseResponseResult() { }

        public BaseResponseResult(int returnValue, string returnMsg) {
            _code = returnValue;
            _message = returnMsg;
        }

        public BaseResponseResult(ErrorCode code, string returnMsg="") {
            SetResult(code, returnMsg);
        }

        private int _code = 0;
        private string _message = "";
        private string _contentType = "application/json";
        /// <summary>
        /// 错误码,0表示成功,其他表示失败
        /// </summary>
        public virtual int returnValue { get { return _code; } }
        /// <summary>
        /// 错误码,0表示成功,其他表示失败
        /// </summary>
        public virtual string returnMsg { get { return _message; } }
        /// <summary>
        /// 返回的数据,json格式
        /// </summary>
        public virtual object returnData { get; set; }

        /// <summary>
        /// 设置返回状态码
        /// </summary>
        /// <param name="code"></param>
        public virtual void SetCode(int code) {
            _code = code;
        }

        /// <summary>
        /// 设置返回状态码
        /// </summary>
        /// <param name="code"></param>
        public virtual void SetCode(ErrorCode code) {
            SetResult(code);
        }

        /// <summary>
        /// 设置返回消息
        /// </summary>
        /// <param name="message"></param>
        public virtual void SetMessage(string message) {
            _message = message;
        }
        /// <summary>
        /// 设置返回状态码和消息
        /// </summary>
        /// <param name="returnValue"></param>
        /// <param name="returnMsg"></param>
        public virtual void SetResult(int returnValue, string returnMsg) {
            _code = returnValue;
            _message = returnMsg;
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="code">ErrorCode代码</param>
        /// <param name="returnMsg">返回消息。如果此项不输入值,则自动设置默认值!</param>
        public virtual void SetResult(ErrorCode code, string returnMsg="") {
            this._code = (int)code;
            this._message = (returnMsg??"").Trim()!=""?returnMsg:ErrorMsg.ErrorMessage[code];
        }
        /// <summary>
        /// 设置返回消息体
        /// </summary>
        /// <param name="obj"></param>
        public virtual void SetReturnData(params object[] obj) {
            if (obj != null && obj.Length > 0) {
                this.returnData = obj.ToList();
            }
        }

        public virtual void SetReturnData(object obj) {
            this.returnData = obj;
        }

        public virtual void SetContentType(string contentType) {
            this._contentType = contentType;
        }

        /// <summary>
        /// 将当前结果转化为JSON字符串
        /// </summary>
        /// <returns></returns>
        public virtual string ToJson() {
            return new JavaScriptSerializer().Serialize(this);
        }

        public virtual void Response(bool isEnd = true) {
            HttpContext.Current.Response.ContentType = _contentType;
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
            HttpContext.Current.Response.Write(this.ToJson());
            if (isEnd)
                HttpContext.Current.Response.End();
        }
    }

ErrorCode:返回状态码枚举。

 public enum ErrorCode {
        /// <summary>
        /// 操作错误
        /// </summary>
        OperationError = -1,
        /// <summary>
        /// 成功
        /// </summary>
        Success = 0,
        /// <summary>
        /// 失败
        /// </summary>
        Failed = 1,
        /// <summary>
        /// 无数据
        /// </summary>
        NoData=2,
        /// <summary>
        /// 不存在此页面
        /// </summary>
        NotExistPage=3,
        /// <summary>
        /// 无权限
        /// </summary>
        NoPermission=4,
        /// <summary>
        /// 未登录
        /// </summary>
        NoLogin=5,
        /// <summary>
        /// 被禁止
        /// </summary>
        Forbidden=6,
        /// <summary>
        /// 请求参数格式不符合要求
        /// </summary>
        InvalideParameter = 98,
        /// <summary>
        /// 无此接口
        /// </summary>
        NoAction = 99,
        /// <summary>
        /// 系统错误
        /// </summary>
        SystemError = 100,
    }

    public class ErrorMsg {
        public static Dictionary<ErrorCode, string> ErrorMessage = new Dictionary<ErrorCode, string> {
            { ErrorCode.OperationError,"服务器响应错误!"},
            { ErrorCode.Success,"成功!"},
            { ErrorCode.Failed, "失败!"},
            { ErrorCode.NoData, "查无数据!"},
            { ErrorCode.NotExistPage,"此页码不存在!"},
            { ErrorCode.InvalideParameter,"请求参数非法!"},
            { ErrorCode.NoAction,"无此接口!"},
            { ErrorCode.SystemError,"系统错误!"},
            { ErrorCode.NoPermission,"无权限操作此功能!" },
            { ErrorCode.NoLogin,"未登录!"},
            { ErrorCode.Forbidden,"操作被禁止!"},
        };
    }

接下来介绍使用方法:

IndexHandler_Base64:定义一个接收base64字符串参数的接口处理器。代码如下:

    /// <summary>
    /// 一般业务接口的模板方法处理器,适用于参数为base64字符串的请求
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class IndexHandler_Base64<T> : IndexHandler<T> where T:class {
        //当前接口是否需要登录后才能操作
        protected bool _isLoginRequired = false;

        /// <summary>
        /// 实例化一个只接收base64字符串的接口操作
        /// </summary>
        /// <param name="isLoginRequired">当前接口是否需要登录。true:需要 false:不需要(默认)</param>
        public IndexHandler_Base64(bool isLoginRequired = false) : base() { _isLoginRequired = isLoginRequired; }
        /// <summary>
        /// 实例化一个只接收base64字符串的接口操作
        /// </summary>
        /// <param name="typeName">发起日志记录的类名</param>
        /// <param name="isLoginRequired">当前接口是否需要登录。true:需要 false:不需要(默认)</param>
        public IndexHandler_Base64(string typeName,bool isLoginRequired=false) : base(typeName) { _isLoginRequired = isLoginRequired; }

        /// <summary>
        /// 对实体模型进行绑定和参数的特性验证
        /// </summary>
        /// <returns></returns>
        public override T Binder() {
            //初始化模型
            T rc = default(T);

            try {
                //初始化ModelState
                if (_modelState == null)
                    _modelState = new ModelState();
                else
                    _modelState.Errors.Clear();

                //获取数据
                Stream stream = HttpContext.Current.Request.InputStream;
                stream.Seek(0, SeekOrigin.Begin);
                byte[] buffer = new byte[stream.Length];
                int count = stream.Read(buffer, 0, buffer.Length);
                if (count > 0) {
                    string requestParam = Encoding.UTF8.GetString(buffer);
                    requestParam = Encoding.UTF8.GetString(Convert.FromBase64String(requestParam));
                    //绑定数据
                    rc = new JavaScriptSerializer().Deserialize<T>(requestParam);
                    if (rc != null) {
                        //验证数据合法性
                        base.Valide(rc);
                    }
                    else
                        _modelState.Errors.Add("绑定数据失败!");
                }
                else
                    _modelState.Errors.Add("请求参数为空!");
            }
            catch (Exception ex) {
                _modelState.Errors.Add("绑定数据出现错误!");
            }

            return rc;
        }

        public override BaseResponseResult Process() {
            //如果该接口需要登录后才能操作,则检查当前用户是否登录
            if (_isLoginRequired) {
                int userId = 0;
                try {
                    userId = Login.GetSession("UserID");
                }
                catch { }
                if (userId <= 0)
                    return new BaseResponseResult(ErrorCode.NoLogin);
            }

            return base.Process();
        }
    }

接下来定义一个Index.ashx文件,开始使用模板接口。

    /// <summary>
    /// index 的摘要说明
    /// </summary>
    public class Index : IHttpHandler {
        private readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        //当前登录的用户
        public static int _thisUserId {
            get {
                return Login.GetSession("UserID");
            }
        }
        public void ProcessRequest(HttpContext context) {
            BaseResponseResult rc = new BaseResponseResult(ErrorCode.OperationError, "获取数据失败!");

            try {
                string action = GetAction();

                switch (action) {
                    //获取 xxx列表
                    case "1001":
                        rc = new ListHandler().Process();
                        break;
                    //获取 xxx信息
                    case "1002":
                        rc = new ItemHandler().Process();
                        break;                    default:
                        rc.SetResult(ErrorCode.NoAction);
                        break;
                }

            }
            catch (Exception ex) {
                log.Error("ProcessRequest", ex);
                rc.SetResult(ErrorCode.SystemError);
            }

            rc.Response();
        }

        public bool IsReusable {
            get {
                return false;
            }
        }

        /// <summary>
        /// 获取Action接口名称
        /// </summary>
        /// <returns></returns>
        private string GetAction() {
            string rc = "";

            try {
                rc = HttpContext.Current.Request["action"] ?? "";
                if ((rc ?? "").Trim() == "") {
                    Stream stream = HttpContext.Current.Request.InputStream;
                    if (stream != null) {
                        byte[] buffer = new byte[stream.Length];
                        int count = stream.Read(buffer, 0, buffer.Length);
                        if (count > 0) {
                            try {
                                string requestParam = Encoding.UTF8.GetString(buffer);
                                requestParam = Encoding.UTF8.GetString(Convert.FromBase64String(requestParam));
                                JsonData jd = JsonMapper.ToObject(requestParam);
                                if (jd != null && jd.Keys.Contains("action"))
                                    rc = jd["action"].ToString();
                            }
                            catch { }
                        }
                    }
                }
            }
            catch (Exception ex) {
                log.Error("GetAction", ex);
            }

            return rc;
        }

    }

    #region 接口处理区

    #region 1001 获取 xxx列表
    public class ListReqModel {

        [Required(ErrorMessage = "请上送需要类型!")]
        [Range(0,5, ErrorMessage = "type参数值有误!")]
        public int type { get; set; }
       /// <summary>
        /// 页码索引,从0开始
        /// </summary>
        [Required(ErrorMessage = "请上送页码索引!")]
        [Min(0, ErrorMessage = "pageIndex参数值有误!")]
        public int pageIndex { get; set; }

        /// <summary>
        /// 每页个数
        /// </summary>
        [Required(ErrorMessage = "请上送每页的个数!")]
        [Min(1, ErrorMessage = "pageSize参数值有误!")]
        public int pageSize { get; set; }

    }
    public class ListHandler : IndexHandler_Base64<ListReqModel> {       public ListHandler() : base("ListHandler") { }
        protected override BaseResponseResult DoWork(ListReqModel param) {
            BaseResponseResult rc = new BaseResponseResult(ErrorCode.OperationError);
            int totalCount = 0;
            ProjectBLL biz = new ProjectBLL();
            DataTable table = biz.GetList(param.type ,Index._thisUserId, out totalCount, param.pageIndex, param.pageSize);

            if (table != null && table.Rows.Count > 0) {
                rc.SetReturnData(new
                    {
                        //总个数
                        totalCount = totalCount,
                        list = table.AsEnumerable().Select(it => new
                        {
                            id = it["ID"].ToInt64(),
                            title = it["Title"].ToNormalString(),
                            frontCover = it["FrontCover"].ToNormalString()
                        }).ToList()
                    });
                rc.SetResult(ErrorCode.Success, "成功!");
            }
            else if (totalCount > 0)
                rc.SetResult(ErrorCode.NotExistPage, "当前页码不存在!");
            else
                rc.SetResult(ErrorCode.NoData, "没有数据哟!");

            return rc;
        }
    }
    #endregion

    #region 1002 获取xxx信息

    public class ItemReqModel {
        [Required(ErrorMessage = "请上送项目标识!")]
        [Min(1, ErrorMessage = "id参数值有误!")]
        public long id { get; set; }
    }

    public class ItemHandler : IndexHandler_Base64<ItemReqModel> {
        public ItemHandler() : base("ItemHandler") { }

        protected override BaseResponseResult DoWork(ItemReqModel param) {
            BaseResponseResult rc = new BaseResponseResult(ErrorCode.OperationError);return rc;
        }
    }

    #endregion#endregion

ajax的使用方式:

//接入说明:
//1、请使用POST方式上传;
//2、请将参数组装为Json字符串,如:{‘action‘:‘xxx‘,‘xx‘:‘xx‘};
//3、Json字符串组装好以后,将其变为Base64字符串后上传。

//上送数据案例如下所示:
$.ajax({
        type: "POST",
        dataType: "json",
        url: GetHost() + ‘Index.ashx‘,
        data: Base.encode(‘{"action":"1001","type":"‘ + type + ‘","pgIndex":‘ + pageIndex + ‘,"pgSize":‘ + pageSize + ‘}‘),
        contentType:"application/json",
        success: function (data) {
                //获取数据
                if (data) {
                    //成功获取数据
                    if (data.returnValue == 0) {
                        //处理数据
                    }
                }
             }
     });

至此,完毕!以上的通用接口处理器采用了模板方法设计模式,尽量减少重复工作量。

说明:本篇文章为作者原创,如需转载,请说明来源及出处!

时间: 2024-10-08 20:10:16

asp.net 自定义的模板方法接口通用类型的相关文章

《连载 | 物联网框架ServerSuperIO教程》- 13.自定义视图显示接口开发,满足不同的显示需求

1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架ServerSuperIO教程>2.服务实例的配置参数说明 <连载 | 物联网框架ServerSuperIO教程>- 3.设备驱动介绍 <连载 | 物联网框架ServerSuperIO教程>-4.如开发一套设备驱动,同时支持串口和网络通讯. <连载 | 物联网框架ServerSupe

ABAP基本数据类型、通用类型

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4292785.html ABAP基本数据类型 更多的类型请参考ABAP数据类型继承图 类型 允许最大长度(字符数) 默认长度(省略时采用) 说明 初始值 C 1~262143个字符 1 字符 如果未在 DATA 语句中指定参数<length>

微信公众平台新增获取自动回复和自定义菜单配置接口

微信公众平台自动回复功能可以为运营者减少了重复回复消息的次数,但如果自动回复的数量多的话管理就比较麻烦:自定义菜单相当于你这个公众号的导航,但有些公众号会限制不能添加外部链接.现在好了,公众平台开发者接口更新,新增获取自动回复和自定义菜单配置接口,对所有公众号开放. 新增的接口具体是: 1. 获取自动回复规则接口 该接口可以获取公众号设置的自动回复规则,包括关注后自动回复.消息自动回复和关键词自动回复. 开发者可以通过该接口,获取公众号当前使用的自动回复规则,包括关注后自动回复.消息自动回复(6

ASP.NET中共有哪几种类型的控件?其中,HTML控件、HTML服务器控件和WEB服务器控件之间有什么区别

ASP.NET的控件包括WEB服务器控件.WEB用户控件.WEB自定义控件.HTML服务器控件和HTML控件.HTML控件.HTML服务器控件和WEB服务器控件之间的区别如下所示.q      HTML控件:这完全是浏览器端的HTML标签控件,例如HTML中常见的单选框表单控件,其HTML代码如以下代码所示.<input type="radio" id="Radio1" value="select1" checked="check

asp.net自定义错误页面

ASP.NET 提供三种用于在出现错误时捕获和响应错误的主要方法:Page_Error 事件.Application_Error 事件以及应用程序配置文件 (Web.config). 如果您不调用 Server.ClearError 或者捕获 Page_Error 或 Application_Error 事件中的错误,则将根据 Web.config 文件的 <customErrors> 部分中的设置处理错误.在 <customErrors> 部分,可将重定向页指定为默认的错误页 (

自定义菜单查询接口

使用接口创建自定义菜单后,开发者还可使用接口查询自定义菜单的结构.另外请注意,在设置了个性化菜单后,使用本自定义菜单查询接口可以获取默认菜单和全部个性化菜单信息. 请求说明 http请求方式:GET https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN 返回说明(无个性化菜单时) 对应创建接口,正确的Json返回结果: {     "menu": {         "button"

Asp.net MVC 中Controller返回值类型ActionResult

内容转自 http://blog.csdn.net/pasic/article/details/7110134 Asp.net MVC中Controller返回值类型 在mvc中所有的controller类都必须使用"Controller"后缀来命名并且对Action也有一定的要求: 必须是一个public方法 必须是实例方法 没有标志NonActionAttribute特性的(NoAction) 不能被重载 必须返回ActionResult类型 如: [csharp] view pl

从头认识java-12.6 接口与类型信息(怎么绕过接口直接调用类的所有方法)

这一章节我们来讨论一下接口与类型信息. 在之前的章节里面我们提到接口,父类引用子类对象,然后把方法给缩窄了,但是我们这一章节学习到反射,这个约束就变得没有那么严格. 我们来看看下面的例子: package com.ray.ch11; public class Test { public static void main(String[] args) { Person man = new Man(); man.sleep(); man.run(); // man.say();//error } }

ASP.NET MVC – 关于Action返回结果类型的事儿(上)

原文:ASP.NET MVC – 关于Action返回结果类型的事儿(上) 本文转自:博客园-文超的技术博客 一.         ASP.NET MVC 1.0 Result 几何? Action的返回值类型到底有几个?咱们来数数看. ASP.NET MVC 1.0 目前一共提供了以下十几种Action返回结果类型: 1.       ActionResult(base) 2.       ContentResult 3.       EmptyResult 4.       HttpUnau