中小型新闻发布系统

代码结构:分为实体层,数据层与接口,数据工厂层,业务逻辑层,公共层,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);

}

}

}

}

net项目总结一(1)的更多相关文章

  1. Fis3前端工程化之项目实战

    Fis3项目 项目目录结构: E:. │ .gitignore │ fis-conf.js │ index.html │ package.json │ README.md │ ├─material │ ...

  2. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  3. 最近帮客户实施的基于SQL Server AlwaysOn跨机房切换项目

    最近帮客户实施的基于SQL Server AlwaysOn跨机房切换项目 最近一个来自重庆的客户找到走起君,客户的业务是做移动互联网支付,是微信支付收单渠道合作伙伴,数据库里存储的是支付流水和交易流水 ...

  4. Hangfire项目实践分享

    Hangfire项目实践分享 目录 Hangfire项目实践分享 目录 什么是Hangfire Hangfire基础 基于队列的任务处理(Fire-and-forget jobs) 延迟任务执行(De ...

  5. Travis CI用来持续集成你的项目

    这里持续集成基于GitHub搭建的博客为项目 工具: zqz@ubuntu:~$ node --version v4.2.6 zqz@ubuntu:~$ git --version git versi ...

  6. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  7. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  8. Angular企业级开发(5)-项目框架搭建

    1.AngularJS Seed项目目录结构 AngularJS官方网站提供了一个angular-phonecat项目,另外一个就是Angular-Seed项目.所以大多数团队会基于Angular-S ...

  9. 【分享】标准springMVC+mybatis项目maven搭建最精简教程

    文章由来:公司有个实习同学需要做毕业设计,不会搭建环境,我就代劳了,顺便分享给刚入门的小伙伴,我是自学的JAVA,所以我懂的.... (大图直接观看显示很模糊,请在图片上点击右键然后在新窗口打开看) ...

  10. ABP入门系列(2)——通过模板创建MAP版本项目

    一.从官网创建模板项目 进入官网下载模板项目 依次按下图选择: 输入验证码开始下载 下载提示: 二.启动项目 使用VS2015打开项目,还原Nuget包: 设置以Web结尾的项目,设置为启动项目: 打 ...

随机推荐

  1. 2.ehcache.xml简介

    转自:https://www.cnblogs.com/crazylqy/p/4238148.html ehcache.xml文件是用来定义Ehcache的配置信息的,更准确的来说它是定义CacheMa ...

  2. TNS:no listener error in Oracle XE after changing computer name

    This morning at work when trying to log on to my computer I noticed not my username on login screen ...

  3. jQuery load() 判断 iframe 是否加载完毕

    判断 iframe 是否加载完毕  方法.jQuery load() var frm = document.getElementById('myiframe'); $(frm).load(functi ...

  4. mongoTemplate.aggregate()聚合查询

    一.概述 1. 聚合的表达式 MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果.有点类似sql语句中的 count(*). 下表展示了一些聚 ...

  5. LevelDB 读取记录

    [LevelDB 读取记录] LevelDb是针对大规模Key/Value数据的单机存储库,从应用的角度来看,LevelDb就是一个存储工具.而作为称职的存储工具,常见的调用接口无非是新增KV,删除K ...

  6. java普通类如何调用Spring的Service层?

    首先在Service层上面添加 @Service("myService") 然后,在main方法中调用,String[]中为配置文件,如下所示: ApplicationContex ...

  7. 40. Combination Sum II (Back-Track)

    Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in ...

  8. C# \/date(1498820611133+0800)\/ 转DateTime

    开发中经常遇到日期转换问题,特别是做接口的时候,现在整理了下时间戳转为C#格式时间的方法: /// <summary> /// 时间戳转为C#格式时间 /// </summary&g ...

  9. C++中public、protected以及private的使用

    相比C语言,C++中通过class/struct来定义既包含数据,又包含行为的结构,从而支持了“对象”.现实世界中,一个人(一个对象)通常 拥有一些资产(数据),并且掌握某些技能(行为),并且这些资产 ...

  10. .net分布在指定文件夹的web.confgi或者app.config

    .Net里面,ConfigurationManager默认读取的是Web.config或者App.config但是,什么都放在这两个文件里面,感觉太多了,也不好管理配置.于是参考了下别人的资料,自己写 ...