2:MVC学习——用户登录,Ajax.BeginForm使用
自我学习计划2,运用上一篇MVC三层架构,做一个用户登录功能;
1,验证码验证,不刷新页面提示;
2,登录成功跳转;
首先看下整个项目的框架:
我的想法是这样的,MODEL层存放跟数据表结构一样的MODEL,而MVC的Models存放页面所需要的内容MODEL;
如MODEL——AdminInfo.cs:
public class AdminInfo { public int AdminId { get; set; } public string AdminName { get; set; } public string AdminPwd { get; set; } public AdminInfo(int adminId, string adminName, string adminPwd) { AdminId = adminId; AdminName = adminName; AdminPwd = adminPwd; } public AdminInfo() { } }
MVC——Models——AdminModel:
public class AdminModel { public int AdminId { get; set; } [Display(Name="用户名")] [Required(ErrorMessage ="请输入{0}")] public string AdminName { get; set; } [Display(Name = "密码")] [Required(ErrorMessage = "请输入{0}")] public string AdminPwd { get; set; } [Display(Name = "验证码")] [Required(ErrorMessage = "请输入{0}")] public string ViewCode { get; set; } }
数据处理层
DAL——SQLHelper:
public class SQLHelper { private readonly static string sqlconn = ConfigurationManager.ConnectionStrings["StuManagerDB"].ToString(); /// <summary> /// 传入SQL获取SqlDataReader /// </summary> /// <param name="sql"></param> /// <returns></returns> public static SqlDataReader GetReader(string sql) { SqlConnection conn = new SqlConnection(sqlconn); SqlCommand cmd = new SqlCommand(sql, conn); conn.Open(); SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection); return reader; } }
DAL——AdminService:
public class AdminService { public AdminInfo AdminLogin(AdminInfo admin) { AdminInfo objAdmin = new AdminInfo(); string sql = "SELECT AdminId,AdminName,AdminPwd FROM AdminInfo WHERE AdminName='{0}' AND AdminPwd='{1}'"; sql = string.Format(sql, admin.AdminName, admin.AdminPwd); SqlDataReader reader = SQLHelper.GetReader(sql); if (reader.Read()) { objAdmin.AdminId = Convert.ToInt32(reader["AdminId"]); objAdmin.AdminName = reader["AdminName"].ToString(); objAdmin.AdminPwd = reader["AdminPwd"].ToString(); reader.Close(); } else { objAdmin = null; } return objAdmin; } }
业务逻辑层
BLL——AdminManager:
public class AdminManager { public AdminInfo AdminLogin(AdminInfo admin) { AdminInfo objAdmin = new AdminService().AdminLogin(admin); return objAdmin; } }
MVC——Controller——AdminController:
public class AdminController : Controller { [HttpGet] public ActionResult Login() { return View(); } [HttpPost] public ActionResult Login(AdminModel admin) { if (ModelState.IsValid) { if (admin.ViewCode.ToUpper() == Session["ViewCode"].ToString()) { AdminInfo objAdmin = new AdminInfo(); objAdmin.AdminName = admin.AdminName; objAdmin.AdminPwd = admin.AdminPwd; objAdmin = new AdminManager().AdminLogin(objAdmin); if (objAdmin == null) { return this.Content("用户名或密码错误!"); } else { Session["AdminName"] = objAdmin.AdminName; return this.Content("LoginSuccess"); } } else { return this.Content("验证码错误!"); } } return View(); } public ActionResult LoginOut() { Session["AdminName"] = null; return View("Login"); } }
MVC——Views——Admin——Login:
@model StudentManagerMVC.Models.AdminModel @{ Layout = null; } <!DOCTYPE html> <script src="~/Scripts/jquery-3.4.1.min.js"></script> <script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script> <script> function checkContent() { var adminName = $("#AdminName").val(); if (adminName.length < 1) { alert("请输入用户名!"); return false; } var AdminPwd = $("#AdminPwd").val(); if (AdminPwd.length < 1) { alert("请输入密码!"); return false; } var ViewCode = $("#ViewCode").val(); if (ViewCode.length < 1) { alert("请输入验证码!"); return false; } return true; } function onSuccess(data, status, xhr){ if (data == "LoginSuccess") { //alert(data); window.location = '/Student/Index'; } else { alert(data); setViewCode(document.getElementById("ViewCodeImg")); } } function setViewCode(e) { //var img = document.getElementById("ViewCodeImg"); e.src = "/ViewCode/SecurityCode?a=" + Math.random(); //alert(img.src); } </script> <html> <head> <meta name="viewport" content="width=device-width" /> <title>用户登录</title> </head> <body> @using (Ajax.BeginForm("Login","Admin", new AjaxOptions { HttpMethod="Post", OnSuccess= "onSuccess(data, status, xhr)" })) { <table> <tr> <td>@Html.LabelFor(model => model.AdminName)</td> <td>@Html.TextBoxFor(model => model.AdminName)</td> <td>@Html.ValidationMessageFor(model => model.AdminName)</td> </tr> <tr> <td>@Html.LabelFor(model => model.AdminPwd)</td> <td>@Html.PasswordFor(model => model.AdminPwd)</td> <td>@Html.ValidationMessageFor(model => model.AdminPwd)</td> </tr> <tr> <td>@Html.LabelFor(model => model.ViewCode)</td> <td> @Html.TextBoxFor(model => model.ViewCode) <img id="ViewCodeImg" src="/ViewCode/SecurityCode" onclick="setViewCode(this)" /> </td> <td>@Html.ValidationMessageFor(model => model.ViewCode)</td> </tr> <tr> <td colspan="3"> <input type="submit" id="btnSubmit" value="提交" onclick="return checkContent();" /> </td> </tr> </table> } </body> </html>
Ajax.BeginForm的用法参考文献:https://www.cnblogs.com/sheng-jie/p/6305385.html
另外,MVC——Controller——StudentController,做一个登录的身份验证:
public class StudentController : Controller { // GET: Student [AdminAuthorize] //登录验证 public ActionResult Index() { return View(); } }
代码在MVC——Controller——AdminAuthorizeAttribute:
public class AdminAuthorizeAttribute:AuthorizeAttribute { protected override bool AuthorizeCore(HttpContextBase httpContext) { if (System.Web.HttpContext.Current.Session["AdminName"] == null) { return false; } return true; } }
注意,根目录Web.config设置了身份验证不通过的跳转页面:
顺便附上MVC——Views——Student——Index.cshtml,还没完成(要成做无刷新分页查询的,做完后写在下一篇笔记里):
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>学生列表</title> </head> <body> <div> 欢迎 @Session["AdminName"].ToString() 的到来! <a href="/Admin/LoginOut">登出</a> </div> </body> </html>
最后附上验证码的生成代码,MVC——Controller——ViewCodeController:
public class ViewCodeController : Controller { #region 生成验证码图片 // [OutputCache(Location = OutputCacheLocation.None, Duration = 0, NoStore = false)] public ActionResult SecurityCode() { string oldcode = Session["ViewCode"] as string; string code = CreateRandomCode(4); Session["ViewCode"] = code; return File(CreateValidateGraphic(code), "image/Jpeg"); } private string CreateRandomCode(int codeCount) { string allChar = "1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,U,W,X,Y,Z"; string[] allCharArray = allChar.Split(','); string randomCode = ""; int temp = -1; Random rand = new Random(); for (int i = 0; i < codeCount; i++) { if (temp != -1) { rand = new Random(i * temp * ((int)DateTime.Now.Ticks)); } int t = rand.Next(32); if (temp == t) { return CreateRandomCode(codeCount); } temp = t; randomCode += allCharArray[t]; } return randomCode; } /// <summary> /// 创建验证码的图片 /// </summary> public byte[] CreateValidateGraphic(string validateCode) { Bitmap image = new Bitmap((int)Math.Ceiling(validateCode.Length * 16.0), 27); Graphics g = Graphics.FromImage(image); try { //生成随机生成器 Random random = new Random(); //清空图片背景色 g.Clear(Color.White); //画图片的干扰线 for (int i = 0; i < 25; i++) { int x1 = random.Next(image.Width); int x2 = random.Next(image.Width); int y1 = random.Next(image.Height); int y2 = random.Next(image.Height); g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2); } Font font = new Font("Arial", 13, (FontStyle.Bold | FontStyle.Italic)); LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true); g.DrawString(validateCode, font, brush, 3, 2); //画图片的前景干扰点 for (int i = 0; i < 100; i++) { int x = random.Next(image.Width); int y = random.Next(image.Height); image.SetPixel(x, y, Color.FromArgb(random.Next())); } //画图片的边框线 g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1); //保存图片数据 MemoryStream stream = new MemoryStream(); image.Save(stream, ImageFormat.Jpeg); //输出图片流 return stream.ToArray(); } finally { g.Dispose(); image.Dispose(); } } #endregion }
以上皆是个人学习笔记,如有错误地方请指正!