• net项目总结一(1)


    中小型新闻发布系统

    代码结构:分为实体层,数据层与接口,数据工厂层,业务逻辑层,公共层,UI层(由于图片上传实在麻烦,所以只上传少量而已),项目中用到了工厂模式,解耦BLL层和DLL层

     

    1、登录功能,记住三天功能,basepage中统一验证

             1、做验证码,利用自定义一般处理程序类来实现

             2、利用cookie实现记住三天状态的功能,实现免登录功能(如果在公共环境不建议使用)

             3、统一登录验证

             4、实现统一错误页面处理 ,全局应用程序文件中的Application_Error()中实现

    2、引入必要的js

     

    3、                  

    登陆页面中取消按钮的制作:

           <td>

                            <input type="button" value="登录" onclick="login()" />

                            <input type="button" value="取消" onclick="resetfm()" />

                        </td>

    //4.0 负责清除当前表单中的所有带有name属性的控件值

     function resetfm() {

                document.getElementById("form1").reset();

       }

    4、建立验证码

     

    4.1实现验证码逻辑:

    /// <summary>

        /// 实现验证码生成的一般处理程序类,记得在web.config中按照iis集成和经典模式做相应的配置

        /// 由于此类中要使用session,所以必须实现接口IRequiresSessionState

        /// </summary>

        public class Vcode : IHttpHandler, System.Web.SessionState.IRequiresSessionState

        {

            public bool IsReusable

            {

                get { return false; }

            }

     

            public void ProcessRequest(HttpContext context)

            {

                //实现验证码功能

                //1.0 产生验证码字符串

                string vcode = GetVcode(4);

                //2.0 将验证码字符串存入session

                context.Session[Keys.Vcode] = vcode;

                //3.0 将验证码字符串以图片的形式响应给浏览器

                using (Image img = new Bitmap(65, 25))

                {

                    //3.0.1 定义一个画家

                    using (Graphics g = Graphics.FromImage(img))

                    {

                        //3.0.2 利用画家对象在图片上将验证码字符串画上去

                        g.Clear(Color.White);

                        g.DrawRectangle(Pens.Red, 0, 0, img.Width - 1, img.Height - 1);

                        g.DrawString(vcode, new Font("黑体", 16, FontStyle.Bold | FontStyle.Strikeout), new SolidBrush(Color.Blue), 4, 4);

                    }

     

                    //3.0.3 利用图片的save方法将图片流保存到outputstream中

                    img.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);

                }

            }

            Random r = new Random();

            private string GetVcode(int num)

            {

                string[] arrcode = { "a", "b", "c", "d", "4", "2", "3" };

                int arrLeng = arrcode.Length;

                string res = string.Empty;

                for (int i = 0; i < num; i++)

                {

                    res += arrcode[r.Next(arrLeng)];

                }

     

                return res;

            }

        }

         4.2写好了验证码的类,那么需要在配置文件中添加配置

    <system.webServer>

        <handlers>

          <add  name="vcode" path="*.vcode" verb="*" type="EMS12.Site.admin.Vcode" />

        </handlers>

      </system.webServer>

         4.3验证码调用示例

    <td>

    <input type="text" id="vcode" name="vcode" />

    <img id="imgvcode" style="cursor: pointer" src="vcode.vcode" alt="验证码" height="25px" width="65px" />

    </td>

    4.4验证码点击替换(注意此时的math.random的用法)

    //2.0 点击验证码图片的时候进行新的请求

    $("#imgvcode").click(function () {

    reflushvcode();

    });

    function reflushvcode() {

    //this.src = "vcode.vcode?rid=" + Math.random(); //js的写法

    $("#imgvcode").attr("src", "vcode.vcode?rid=" + Math.random()); //JQ的写法

    }

    5、利用ajax进行登陆验证。

             5.1  //3.0 利用jquery ajax实现登录处理过程

    function login() {

    //1.0 获取表单form1中的所有带有name属性的参数的键值对

    var parms = $("#form1").serialize();  //uname=?&pwd=?&vcode=?

    //2.0 利用$.post方法将parms参数提交给 /actions/admin/login.ashx

    $.post("/actions/admin/login.ashx", parms, function (ajaxobj) {

    if (ajaxobj.status == "1") {

    msgbox.showMsgErr(ajaxobj.msg, function () {

    // 刷新页面

    //window.location = window.location;

    //刷新验证码

    reflushvcode();

    });

    } else {

    //登录成功

    msgbox.showMsgOk(ajaxobj.msg, function () {

    window.location = "index.aspx";

    });

    }

    }, "json")

    }

             5.2接着开始撰写登陆验证一般处理程序(处理步骤是什么?)

    using EMS12.BusinessLogicLayer;

        using EMS12.Entity;

        using EMS12.Common;//需要的是里面的key,一段加密验证

     

        /// <summary>

        /// login 的摘要说明

        /// </summary>

        public class login : BaseHandler, System.Web.SessionState.IRequiresSessionState  //继承两个接口,第二个接口来实现session

        {

            public override void SubPR()

            {

                Response.ContentType = "text/plain";

                try

                {

                    //开始登录逻辑编写

                    //1.0 接收参数

                    string uname = Request.Form["uname"];

                    string pwd = Request.Form["pwd"];

                    string vcode = Request.Form["vcode"];

     

                    //2.0 验证码的合法性验证

                    string vcodeFromSession = string.Empty;

                    if (Session[Keys.Vcode] != null)

                    {

                        vcodeFromSession = Session[Keys.Vcode].ToString();

                    }

                    if (string.IsNullOrEmpty(vcode)

                        || vcode.Equals(vcodeFromSession, StringComparison.OrdinalIgnoreCase) == false)

                    {

                        WriteError("验证码错误");

                        // Response.End(); //此时会将当前处理现场强制终止,一定会抛出一个异常

                        return;

                    }

                    //3.0 验证用户名和密码的合法性

                    if (string.IsNullOrEmpty(uname) || string.IsNullOrEmpty(pwd))

                    {

                        WriteError("用户名或者密码不能为空");

                        return;

                    }

     

                    string md5pwd = Kits.MD5Entry(pwd);

                    UserInfoEntity entity = UserInfo_BLLSub.Login(uname, md5pwd);

                    if (entity == null)

                    {

                        WriteError("用户名或者密码错误");

                        return;

                    }

                    //4.0 将用户实体存入session[uinfo]

                    Session[Keys.uinfo] = entity;

     

                    //5.0 将ajaxobj对象序列化成json字符串返回

                    WriteSuncess("登录成功,正在跳转到首页....");

                }

                catch (Exception ex)

                {

                    WriteError(ex.Message);

                }

            }

        }

    6.附加的kits。就是common下的加密验证

      using System.Text.RegularExpressions;

        /// <summary>

        /// 帮助类

        /// </summary>

        public class Kits

        {

            /// <summary>

            /// 判断当前字符串是否为一个数字

            /// </summary>

            /// <param name="str"></param>

            /// <returns></returns>

            public static bool IsInt(string str)

            {

                int res = 0;

                return int.TryParse(str, out res);

            }

     

            /// <summary>

            /// 判断当前字符串是否为一个数字

            /// </summary>

            /// <param name="str"></param>

            /// <returns></returns>

            public static bool IsNumber(string str)

            {

                //Regex reg = new Regex("^[0-9]+$");

                Regex reg = new Regex("^\d+$");

                return reg.IsMatch(str);

            }

     

            /// <summary>

            /// 将明文加密成md5格式的密文

            /// </summary>

            /// <param name="str"></param>

            /// <returns></returns>

            public static string MD5Entry(string str)

            {

                return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "md5");

            }

     

            /// <summary>

            /// 负责将对象序列化成json字符串

            /// </summary>

            /// <param name="obj"></param>

            /// <returns></returns>

            public static string ToJsonString(object obj)

            {

                System.Web.Script.Serialization.JavaScriptSerializer jsor = new System.Web.Script.Serialization.JavaScriptSerializer();

                return jsor.Serialize(obj);

            }

     

            /// <summary>

            /// 负责将json字符串反序列化成对象

            /// </summary>

            /// <typeparam name="T"></typeparam>

            /// <param name="jsonstr"></param>

            /// <returns></returns>

            public static T DeserializeFromJsonString<T>(string jsonstr)

            {

                System.Web.Script.Serialization.JavaScriptSerializer jsor = new System.Web.Script.Serialization.JavaScriptSerializer();

                return jsor.Deserialize<T>(jsonstr);

            }

     

        }

    7.附加的BaseHandler,相当于父类

    using EMS12.Common;

     

        /// <summary>

        /// 负责封装上下文中的相关属性

        /// </summary>

        public abstract class BaseHandler : IHttpHandler

        {

            #region 1.0 封装上下文中的相关属性

            protected HttpContext Context

            {

                get

                {

                    return HttpContext.Current;

                }

            }

            protected HttpRequest Request

            {

                get

                {

                    return this.Context.Request;

                }

            }

            protected HttpResponse Response

            {

                get

                {

                    return this.Context.Response;

                }

            }

            protected HttpSessionState Session

            {

                get

                {

                    return Context.Session;

                }

            }

            #endregion

            #region 2.0 封装ajax相关请求的方法和对象

            AjaxObj obj = new AjaxObj();

            /// <summary>

            /// 成功返回统一调用

            /// </summary>

            /// <param name="msg"></param>

            protected void WriteSuncess(string msg)

            {

                obj.status = Estatus.suncess;

                obj.msg = msg;

                Response.Write(Kits.ToJsonString(obj));

            }

            /// <summary>

            /// 成功返回统一调用

            /// </summary>

            /// <param name="msg"></param>

            /// <param name="data"></param>

            protected void WriteSuncess(string msg, object data)

            {

                obj.status = Estatus.suncess;

                obj.msg = msg;

                obj.datas = data;

     

                Response.Write(Kits.ToJsonString(obj));

            }

            /// <summary>

            /// 统一进行错误异常信息的返回

            /// </summary>

            /// <param name="msg"></param>

            protected void WriteError(string msg)

            {

                obj.status = Estatus.error;

                obj.msg = msg;

     

                Response.Write(Kits.ToJsonString(obj));

            }

            #endregion

            public bool IsReusable

            {

                get { return false; }

            }

            public void ProcessRequest(HttpContext context)

            {

                // 什么都不做,只是调用一下子类中实现的抽象方法

                SubPR();

            }

            public abstract void SubPR();

        }

    8.分析用户名和密码验证中,生成代码并没有那么应该怎么去做的逻辑。首先,我们想到去用new出BLL来。找到UserInfoBLLSub.cs,里面并没有提供任何函数,但是他继承于父类UserInfo_BLLSub : UserInfoBLLBase,在BusinessLogicLayerBase每个都有对应的父类。里面实现了全部的基本方法

    看到方法:

       /// <summary>

             /// 得到 userinfo 数据实体

             /// </summary>

             /// <param name="user_id">user_id</param>

             /// <returns>userinfo 数据实体</returns>

             public static UserInfoEntity Get_UserInfoEntity(int user_id)

             {

                  // Validate input

                  if(user_id<0)

                       return null;

     

                  // Use the dal to get a record

                  return _dal.Get_UserInfoEntity(user_id);

             }

             这里面只有通过id来获得实体而已。所以我们需要自己去写这个方法

             步骤1:去接口层(IUserInfoDALSub.cs)定义一个接口:

     

    那么我们先来看到接口层IUserInfoDALSub.cs

     

      /// <summary>

        /// 数据层 dbo.UserInfo 接口。

        /// </summary>

        public interface IUserInfoDataAccessLayer:IUserInfoDataAccessLayerBase

    {

         //发现还是继承了父类,接着我们去查看父类

    }

    父类:IUserInfoDAL(这个只是文件名,但是定义的接口名称是随意的,所以不要看错了

    接口约定了我们基本的增删查改的方法

    public interface IUserInfoDataAccessLayerBase

        {

             #region 基本方法

             /// <summary>

             /// 向数据库中插入一条新记录。

             /// </summary>                 

              /// <param name="_UserInfoModel">UserInfo实体</param>

             /// <returns>新插入记录的编号</returns>

             int Create_UserInfoInsert(UserInfoEntity _UserInfoModel);

     

             /// <summary>

             /// 向数据库中插入一条新记录。带事务

             /// </summary>

             /// <param name="sp">事务对象</param>

             /// <param name="_UserInfoModel">UserInfo实体</param>

             /// <returns>新插入记录的编号</returns>

             int Create_UserInfoInsert(SqlTransaction sp,UserInfoEntity _UserInfoModel);

            

             /// <summary>

             /// 向数据表UserInfo更新一条记录。

             /// </summary>

             /// <param name="_UserInfoModel">_UserInfoModel</param>

             /// <returns>影响的行数</returns>

             int Create_UserInfoUpdate(UserInfoEntity _UserInfoModel);

            

             /// <summary>

             /// 向数据表UserInfo更新一条记录。带事务

             /// </summary>

             /// <param name="sp">事务对象</param>

             /// <param name="_UserInfoModel">_UserInfoModel</param>

             /// <returns>影响的行数</returns>

             int Create_UserInfoUpdate(SqlTransaction sp,UserInfoEntity _UserInfoModel);

            

             /// <summary>

             /// 删除数据表UserInfo中的一条记录

             /// </summary>

             /// <param name="user_id">user_id</param>

             /// <returns>影响的行数</returns>

             int Create_UserInfoDelete(int user_id);

            

             /// <summary>

             /// 删除数据表UserInfo中的一条记录,带事务

             /// </summary>

             /// <param name="sp">事务对象</param>

             /// <param name="user_id">user_id</param>

             /// <returns>影响的行数</returns>

             int Create_UserInfoDelete(SqlTransaction sp,int user_id);

            

            

             /// <summary>

             /// 根据UserInfo返回的查询DataRow创建一个UserInfoEntity对象

             /// </summary>

             /// <param name="row">row</param>

             /// <returns>UserInfo对象</returns>

             UserInfoEntity Populate_UserInfoEntity_FromDr(DataRow row);

            

            /// <summary>

             /// 得到 userinfo 数据实体

             /// </summary>

             /// <param name="user_id">user_id</param>

             /// <returns>userinfo 数据实体</returns>

             UserInfoEntity Get_UserInfoEntity(int user_id);

            

            

             /// <summary>

             /// 得到数据表UserInfo所有记录

             /// </summary>

             /// <returns>数据实体</returns>

             IList< UserInfoEntity> Get_UserInfoAll();

            

             /// <summary>

            /// 检测是否存在根据主键

            /// </summary>

            /// <param name="user_id">user_id</param>

            /// <returns>是/否</returns>

             bool IsExistUserInfo(int user_id);

            #endregion

        }

    于是,我们开始定义验证用户名和密码的接口:

    /// <summary>

        /// 数据层 dbo.UserInfo 接口。

        /// </summary>

        public interface IUserInfoDataAccessLayer:IUserInfoDataAccessLayerBase

        {

            UserInfoEntity GetUserInfo(string uname, string md5pwd);

        }

    步骤2:定义好接口之后,那么这个接口由谁去实现呢?其实,接口的父类,已经由DAL去实现了,可以查看UserInfoDAL.CS

    我们查看的是EMS12.DataAccessLayer下的DataAccessLayer下的UserInfoDAL.CS,就是父类了

    /// <summary>

        /// 数据层实例化接口类 dbo.UserInfo.

        /// </summary>

        public partial class UserInfoDataAccessLayer : IUserInfoDataAccessLayer

    {

         里面实现了所有接口定义的方法

    }

    同时,我们要知道这里的DAL跟BLL不同,BLL中的之类是直接去继承父类的,   public class UserInfo_BLLSub : UserInfoBLLBase,

    但是,DAL不是用之类去做的,而是用partial来形成共同代码,只是分开而已。public partial class UserInfoDataAccessLayer : IUserInfoDataAccessLayer,因为它是实现接口的。

    于是我们在DAL中去实现这个接口:

    /// <summary>

        /// 数据层实例化接口类  dbo.UserInfo.

        /// </summary>

        public partial class UserInfoDataAccessLayer : IUserInfoDataAccessLayer

        {

            public UserInfoEntity GetUserInfo(string uname, string md5pwd)

            {

                UserInfoEntity _obj = null;

                SqlParameter[] _param ={

                  new SqlParameter("@uname",SqlDbType.VarChar),

                new SqlParameter("@md5pwd",SqlDbType.VarChar)

                  };

                _param[0].Value = uname;

                _param[1].Value = md5pwd;

                string sqlStr = "select top 1 * from UserInfo where u_name =@uname and u_pwd = @md5pwd ";

                using (SqlDataReader dr = SqlHelper.ExecuteReader(Conn.SqlConn, CommandType.Text, sqlStr, _param))

                {

                    while (dr.Read())

                    {

                        _obj = Populate_UserInfoEntity_FromDr(dr);

                    }

                }

                return _obj;

            }

        }

    步骤3:那么DAL实现了之后呢,开始BLL的实现,那么要实现什么呢?

    /// <summary>

            /// 登录方法

            /// </summary>

            /// <param name="uname"></param>

            /// <param name="md5pwd"></param>

            /// <returns></returns>

            public static UserInfoEntity Login(string uname, string md5pwd)

            {

                return _dal.GetUserInfo(uname, md5pwd);

            }

            #endregion

    步骤4:开始校验

      UserInfoEntity entity = UserInfo_BLLSub.Login(uname, md5pwd);

                    if (entity == null)

                    {

                        WriteError("用户名或者密码错误");

                        return;

                    }

    步骤五:由于受到工厂模式的作用,反射等,所以全部归结到UI层中被调用

     

    怎么限制到的呢?是在web.config配置的

    <configuration>

      <connectionStrings>

        <add name="conn" connectionString="server=.;database=kyprint;uid=sa;pwd=master;"/>

      </connectionStrings>

      <appSettings>

        <!--表示在工厂中要通过此配置获取DAL层程序集并且反射出其中的类的对象-->

        <add key="Dal" value="EMS12.DataAccessLayer" />

      </appSettings>

      <system.web>

        <compilation debug="true" targetFramework="4.5" />

        <httpRuntime targetFramework="4.5" />

      </system.web>

      <system.webServer>

        <handlers>

          <add  name="vcode" path="*.vcode" verb="*" type="EMS12.Site.admin.Vcode" />

        </handlers>

      </system.webServer>

     

    </configuration>

    9、后台管理中心首页菜单的制作

    <%=menus %>

    直接用上定义好的字符串,再在后台处理这个字符串

       /// <summary>

            /// 负责存放从menus表中查询出数据以后动态拼装成li标签代码

            /// </summary>

            public System.Text.StringBuilder menus = new System.Text.StringBuilder(200);

    protected void Page_Load(object sender, EventArgs e)

            {

                InitMenus();

            }

    private void InitMenus()

            {

                //1.0 查询数据表menus以集合的形式返回

                IList<MenusEntity> list = Menus_BLLSub.Get_MenusAll();

                //2.0 遍历 集合,生成1级菜单

                if (list.Any())   //判断集合有没有数据的方法

                {

                    foreach (MenusEntity item in list)

                    {

                        //判断当前数据是否是一级菜单并且状态为正常

                        if (item.m_parent_mid < 0 && item.m_status == (int)ENums.EState.Normal)

                        {

                            menus.AppendLine("<li class="level1">" + item.m_name + "</li>");

                            //3.0 遍历 集合,生成2级菜单

                            GenSubMenus(item.m_id, list);

                        }

                    }

                }

            }

  • 相关阅读:
    nodejs学习笔记
    php操作mysql数据库
    HTML5 新特性总结
    万恶的浏览器兼容问题
    图标字体使用方法
    托管代码
    进程间通信,把字符串指针作为参数通过SendMessage传递给另一个进程,不起作用
    利用自定义消息处理函数的WPARAM或LPARAM参数传递指针
    自定义消息中如果需要定义WPARAM和LPARAM,该怎么使用和分配?
    提高VS2010运行速度的技巧+关闭拼写检查
  • 原文地址:https://www.cnblogs.com/zhenghongxin/p/4321610.html
Copyright © 2020-2023  润新知