Mvc第一遍结束综合练习:带权限的学生管理系统
程序的设计应该根据功能来进行。先来设想一下本练习的程序功能:学生信息管理、登录用户区分权限、出错应该给出提示。
由此可以设想,完成以后的程序是下图的样子:
主界面:

点击右上角的“登录”,出现登录界面:

任何错误,都在错误页面处理:

以上是整个程序的界面部分。整个练习不做任何美工方面的考虑。
基于这样的程序功能,接下来进行程序设计。
数据库设计:
库中至少应该包含学生信息表和用户表。做最简单的设计如下:
学生表:

用户表:

以此为基础,完成数据库
用户表内容:

学生表内容:

根据前面的功能界面,设计视图、控制器、业务逻辑层、模型层如下:

注意:控制器、业务逻辑和模型之间,没有表中必然的对应关系。这么列表就是为了看着方便。
有了这样的分工概念,接下来创建对应的文件夹和文件

然后可以按照你喜欢的顺序完成这九个部分(views里面的三个视图忘记展开了)。
这里采用表中从右到左的顺序作为项目的完成顺序。
Student.cs:
对照数据库,考虑到学生基本信息,可以完成类的属性编写。结合操作(增删改查),确定完成四项基本功能。补上构造函数,文件内容如下:

  1. class Student
  2. {
  3. string id,xm, nl, zy,sql;//sql是某条记录准备执行的操作语句
  4. public Student(string input_id)//构造函数1,只初始化编号,显然准备删除自己
  5. {
  6. id = input_id;
  7. }
  8. public Student(string input_xm,string input_nl,string input_zy)//构造函数2,没有编号,看样子要把自己插入表中
  9. {
  10. xm=input_xm;
  11. nl = input_nl;
  12. zy = input_zy;
  13. }
  14. public Student(string input_id,string input_xm, string input_nl, string input_zy)//构造函数3,啥都有,用于更新
  15. {
  16. id = input_id;
  17. xm = input_xm;
  18. nl = input_nl;
  19. zy = input_zy;
  20. }
  21. public void insert_it()//插入方法
  22. {
  23. sql = "insert into xs(xm,nl,zy) values('"+xm+"',"+nl+",'"+zy+"')";
  24. Hc_db.do_nonquery(sql);
  25. }
  26. public void modify_it()//修改方法
  27. {
  28. sql = "update xs set xm='"+xm+"',nl="+nl+",zy='"+zy+"' where id="+id;
  29. Hc_db.do_nonquery(sql);
  30. }
  31. public void delete_it()//删除方法
  32. {
  33. sql = "delete from xs where id=" + id;
  34. Hc_db.do_nonquery(sql);
  35. }
  36. public DataTable select_it()
  37. {
  38. sql= "select * from xs where id=" + id;
  39. return Hc_db.get_datatable(sql);
  40. }
  41. }

  

接下来,开始写学生管理的业务逻辑。由于“查”分为按学号查和全查,所以它一共有五个操作。可以看到,在模型的支持下,它变得很简单。Bll.cs代码如下:

  1. class Bll
  2. {
  3. public static DataTable get_All()
  4. {
  5. DataTable dt1;
  6. dt1 = Hc_db.get_datatable("select id as 学号,xm as 姓名,nl as 年龄,zy as 专业 from xs");
  7. return dt1;
  8. }
  9. public static void delet_Student(string id)
  10. {
  11. Student s1 = new Student(id);
  12. s1.delete_it();
  13. }
  14. public static void add_Student(string xm,string nl,string zy)
  15. {
  16. Student s1 = new Student(xm,nl,zy);
  17. s1.insert_it();
  18. }
  19. public static void modi_Student(string id, string xm, string nl, string zy)
  20. {
  21. Student s1 = new Student(id,xm,nl,zy);
  22. s1.modify_it();
  23. }
  24. public static DataTable get_Student(string id)
  25. {
  26. Student s1 = new Student(id);
  27. return s1.select_it();
  28. }
  29. }

  

练习里的用户逻辑很简单,只需要根据用户名密码判断是否能登录,登录之后给出具体权限就好。User_Manage.cs代码如下:

  1. public class User_Manage
  2. {
  3. public static void user_Login(string u,string pass,out bool result,out int power)
  4. {
  5. string sql = $"select * from user1 where user_name='{u}' and password='{pass}'";
  6. DataTable dt1;
  7. dt1 = Hc_db.get_datatable(sql);
  8. if(dt1.Rows.Count>0)
  9. {
  10. result = true;
  11. power = int.Parse(dt1.Rows[0][3].ToString());
  12. }
  13. else
  14. {
  15. result = false;
  16. power = 0;
  17. }
  18. }
  19. }

  

可以看到,缺乏模型的支持,业务逻辑写起来稍微显得复杂了一点。
后方稳固,老板上场。Home控制器主要根据送入的参数来调动手头资源,再把需要呈现的东西送给视图。Index方法,在送入的参数方面,要考虑的问题主要有:1、用户操作增删改查时,送入哪些参数,根据参数决定操作。这一部分考虑由Action的参数来表达;2、如何确定用户的权限,这一部分考虑用session来表达;3、在第一次访问这个页面(参数和session都为空)的时候,程序应该如何处理。无论如何,它都应该带回一个在数据库中查询的结果。基于这些考虑,HomeController.cs的Index方法代码如下:

  1. public ActionResult Index(string id="0",string xm="0", string nl = "0", string zy = "0")
  2. {
  3. string s;
  4. if(Session["u"]==null)
  5. {
  6. Session["u"] = "guest";
  7. Session["p"] = 0;
  8. }
  9. if(id!="0")
  10. {
  11. s = Request["s"];
  12. if (s == "添加")
  13. {
  14. if (int.Parse(Session["p"].ToString()) < 40)
  15. {
  16. Response.Redirect("/wrong/index?msg=Power Low!");
  17. }
  18. else
  19. {
  20. Bll.add_Student(xm, nl, zy);
  21. }
  22. }
  23. else if (s == "删除")
  24. {
  25. if (int.Parse(Session["p"].ToString()) < 90)
  26. {
  27. Response.Redirect("/wrong/index?msg=Power Low!");
  28. }
  29. else
  30. {
  31. Bll.delet_Student(id);
  32. }
  33. }
  34. else if (s == "修改")
  35. {
  36. if (int.Parse(Session["p"].ToString()) < 40)
  37. {
  38. Response.Redirect("/wrong/index?msg=Power Low!");
  39. }
  40. else
  41. {
  42. Bll.modi_Student(id, xm, nl, zy);
  43. }
  44. }
  45. else
  46. {
  47. ViewData["mydata"] = Bll.get_Student(id);
  48. }
  49. }
  50. if (ViewData["mydata"] == null)
  51. {
  52. ViewData["mydata"] = Bll.get_All();
  53. }
  54. return View();
  55. }

  

相比之下,Login方法相对简单。它只需要考虑1、请求这个页面时,呈现什么;2、接受到用户提交的用户名密码时,做些什么;3、登录成功和失败,分别返回什么。代码如下:

  1. public ActionResult Login(string un = "0",string pw="0")
  2. {
  3. bool ok;
  4. int qx;
  5. if (un == "0")
  6. {
  7. return View();
  8. }
  9. else
  10. {
  11. User_Manage.user_Login(un, pw,out ok,out qx);
  12. if(ok)
  13. {
  14. Session["u"] = un;
  15. Session["p"] = qx;
  16. Response.Redirect("/home/index");
  17. }
  18. else
  19. {
  20. Response.Redirect("/wrong/index?msg=login wrong");
  21. }
  22. }
  23. return View();
  24. }

  

出错控制器很简单,给个错误页面就好。如果想要呈现不同的错误信息,最简单的方法是在重定向到它的时候,把错误信息传过去。这里通过查询字符串传递进来,viewdata传递给视图,代码如下:

  1. public class WrongController : Controller
  2. {
  3. // GET: Wrong
  4. public ActionResult Index(string msg="")
  5. {
  6. if(msg!="")
  7. {
  8. ViewData["mydata"] = msg;
  9. }
  10. return View();
  11. }
  12. }

  

调用方式就可以是这个样子:
Response.Redirect("/wrong/index?msg=xxx");
有了控制器送过来的内容,接下来界面就很好做了。按照前面程序效果的设想,Index.cshtml主要分为三部分。最上面显示用户信息,中间显示学生信息,下面进行操作。其中用户信息主要由session控制,学生信息主要由dataview呈现,操作部分主要由表单完成。代码如下:

  1. @using System.Data;
  2. @{
  3. Layout = null;
  4. }
  5.  
  6. <!DOCTYPE html>
  7.  
  8. <html>
  9. <head>
  10. <meta name="viewport" content="width=device-width" />
  11. <title>Index</title>
  12. </head>
  13. <body>
  14. <div>
  15. <div style="text-align:right;">
  16. 用户:@Session["u"].ToString()
  17. 权限:@Session["p"].ToString()
  18. @{
  19. if(Session["p"].ToString()=="")
  20. {
  21. <a href="/home/login">登录</a>
  22. }
  23. }
  24. </div>
  25. <hr />
  26. <div>
  27. @if (ViewData["mydata"] != null)
  28. {
  29. <table style="width: 100%; border-color:black; padding:0px; border-collapse:collapse;" border=''>
  30. @{
  31. DataTable a = (DataTable)ViewData["mydata"];
  32. <tr>
  33. @for (int j = ; j < a.Columns.Count; j++)
  34. {
  35. <td>@(a.Columns[j].ColumnName)</td>
  36. }
  37. </tr>
  38. for (int i = ; i < a.Rows.Count; i++)
  39. {
  40. <tr>
  41. @for (int j = ; j < a.Columns.Count; j++)
  42. {
  43. <td>@(a.Rows[i][j].ToString())</td>
  44. }
  45. </tr>
  46. }
  47. }
  48. </table>
  49. }
  50. </div>
  51. <hr />
  52. <div>
  53. <form>
  54. 学号:<input type="text" name="id" />
  55. 姓名:<input type="text" name="xm" />
  56. 年龄:<input type="text" name="nl" />
  57. 专业:<input type="text" name="zy" /><br />
  58. <input type="submit" name="s" value="添加" />
  59. <input type="submit" name="s" value="删除" />
  60. <input type="submit" name="s" value="修改" />
  61. <input type="submit" name="s" value="查询" />
  62. </form>
  63. </div>
  64. </div>
  65. </body>
  66. </html>

登录页面Login.cshtml很简单,一个表单即可。代码如下:

  1. @{
  2. Layout = null;
  3. }
  4.  
  5. <!DOCTYPE html>
  6.  
  7. <html>
  8. <head>
  9. <meta name="viewport" content="width=device-width" />
  10. <title>Login</title>
  11. </head>
  12. <body>
  13. <div>
  14. <form>
  15. 用户名:<input type="text" name="un" /><br />
  16. 密码:<input type="text" name="pw" /><br />
  17. <input type="submit" value="登录" />
  18. </form>
  19. </div>
  20. </body>
  21. </html>

错误页面Wrong.cshtml呈现即可,代码如下:

  1. @{
  2. Layout = null;
  3. }
  4.  
  5. <!DOCTYPE html>
  6.  
  7. <html>
  8. <head>
  9. <meta name="viewport" content="width=device-width" />
  10. <title>Index</title>
  11. </head>
  12. <body>
  13. <div>
  14. 操作失败!<br />
  15. @{
  16. if(ViewData["mydata"]!=null)
  17. {
  18. <p>@ViewData["mydata"].ToString()</p>
  19. }
  20. }
  21. </div>
  22. </body>
  23. </html>

调试。

看懂了,就把它忘掉,然后自己写一遍。对照着写和抄代码,你学不到任何东西。
至此,整个练习全部完成。正所谓“麻雀虽小五脏俱全”。我们已经能够使用mvc方式完成一个网站的编写,并且体会到这种“松耦合”方式的好处,即:每个小部分都很简单,想要改进(比如界面),其他部分基本都不用动。
回顾整个项目,看看有什么感觉。比如:
Home控制器里,Index方法做的事情是不是还是太复杂了?不像一个老板。而厨房,太清闲了吧。权限判断这样的事情,是不是应该由业务逻辑层来完成?怎么改?自己想想,试试吧。
还有,各个部分之间的跳转、数据的传递,是不是还是感觉怪怪的?写起来很麻烦?在第二遍的学习中,这些问题会有所改善。

mvc_1_ex_stu_manage的更多相关文章

随机推荐

  1. MySQL使用alter修改表的结构

    SQL语句     DLL        数据定义语言         create,drop     DML     数据操纵语言         insert,delete,select,upda ...

  2. Java错误体系

    1.Java所有的异常错误都继承与Throwable类,只有继承了Throwable类,才能在异常传递体系中进行. 2.Throwable下有两个重要的子类,Error和Exception Error ...

  3. 文件转换神器pandoc

    pandoc  :可以在各种文件之间进行相互转化.比如从md文件转为pdf,docx转为tex文件,html文件和txt文件相互转化,等等. 在终端启用命令行执行命令. 我最近要完成的任务是把有很多个 ...

  4. Springboot JackSon

    1. SpringBoot JSON工具包默认是Jackson,只需要引入spring-boot-starter-web依赖包,自动引入相应依赖包: <dependency> <gr ...

  5. 【Linux】bat文件如何执行

    绝对路径,"/home/myDir/xxx.bat" OR 所在的目录,:"./xxx.bat".

  6. Jmeter函数助手—自带方法

    1.${__time()}---->当前时间,一串数字格式 2.${__time(yyyy-MM-dd)}----->当前日期,年-月-日格式 3.${__time(yyyy-MM-dd ...

  7. 4.28(TG模拟赛)总结

    1.挖地雷 题目背景 NOIp1996提高组第三题 题目描述 在一个地图上有N个地窖(N≤20),每个地窖中埋有一定数量的地雷.同时,给出地窖之间的连接路径.当地窖及其连接的数据给出之后,某人可以从任 ...

  8. 常见的概率分布类型(二)(Probability Distribution II)

    以下是几种常见的离散型概率分布和连续型概率分布类型: 伯努利分布(Bernoulli Distribution):常称为0-1分布,即它的随机变量只取值0或者1. 伯努利试验是单次随机试验,只有&qu ...

  9. 在eclipse中新建java问题报错:The type XXX cannot be resolved. It is indirectly referenced from required .class files

    在Eclipse中遇到The type XXX cannot be resolved. It is indirectly referenced from required .class files错误 ...

  10. 三天精通Vue--ES6的常用语法

    详细学习请参考  阮一峰的ECMAScript 6 入门 let和const的使⽤ es5中使用var来声明全局变量 es5中我们学习了使用var来声明变量,但是使用var声明变量,会存在变量提升的问 ...