• mvc_第一遍_业务逻辑层和模型


    常用的动态网页对象:

      之前我们提到了,使用request对象可以获得和用户请求相关的一系列信息。这一节,我们来看看另外两个常用对象的常规用途。

      由于“控制器返回重定向”的存在(后面会讲到),下面斜体部分虽然可以使用,但已经不提倡使用。

      response对象:用于向客户回应。

        最常用的用法类似于

        “Response.Redirect("/Home/Index1");”

        它表示用户浏览器跳转到当前网站的“/Home/Index1”位置。

        常用于出现各种错误的时候,提前结束当前流程。

        现在通常由类似下面的代码完成

    return Redirect("/test/index");
    

        两者区别在于return:

          前者(比如控制器中)重定向之后,代码会继续向下执行,服务器生成视图之后还会发送给客户。但浏览器接受到重定向指令,已经不再接收和显示该内容。可后续执行的代码,也可能对程序产生影响。

          而后者,遇到return,当前方法停止并返回。这往往是程序员的本意。

      Session对象:和ViewData的用法类似,也是用字典模式存储数据。例:

        Session["hello"] = "你好啊";

        这种变量的有效期为“当前会话”,也可以理解为“本次访问网站”。一般来说,用户退出网站,或20分钟内没有任何操作,“当前会话”就结束了。

        每个用户都可以拥有一组属于自己的Session变量,互相之间并不冲突,可以跨控制器和操作来传递值。

        基于此,它通常用来保存用户横跨全站的信息。比如用户名、权限等级、头像等等。

      例题:完成一个登录程序,输入用户名、密码,登录成功进入操作页面;否则进入出错页面。页面上显示当前用户名。

        控制器代码:    

    public class HomeController : Controller
        {
            // GET: Home
            public ActionResult Index(string u="0",string p="0")
            {
                Session["user"] = u;
                if(u == "123" && p == "456")
                {
                    Response.Redirect("home/get_menu");
                }
                else if(u != "0" && p != "0")
                {
                    Response.Redirect("/home/wrong");
                }
                return View();
            }
            public ActionResult get_Menu()
            {
                return View();
            }
            public ActionResult Wrong()
            {
                return View();
            }
        }

        登录视图代码:      

    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
    </head>
    <body>
        <div> 
            <form>
                用户名:<input type="text" name="u" /><br />
                密码:<input type="password" name="p" /><br />
                <input type="submit" value="登录" />
            </form>
        </div>
    </body>
    </html>

          登录成功视图代码:

    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>get_Menu</title>
    </head>
    <body>
        <div> 
            当前用户为@(Session["user"].ToString())<br />
            已登录,这里应该出现操作菜单。。。。
        </div>
    </body>
    </html>

          登录失败视图代码:

    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Wrong</title>
    </head>
    <body>
        <div>
            当前用户为@(Session["user"].ToString())<br />
            登录失败,用户名、密码不正确。
        </div>
    </body>
    </html>

    业务逻辑层

      这一层,在很多mvc的教材里并不体现,也有很多人把它归在“控制器”一类中。我自己的理解是:控制器只管调度,而业务逻辑是介于调度和读写数据之间的操作,值得另外开一层来写。

      上一章的“杨辉三角形”的练习中,控制器负责根据输入的层数,计算杨辉三角形的内容,再返回给视图,有一点混乱。我们换个写法试试。以下内容属于我的个人习惯,给大家参考。

      在项目中,新建一个文件夹“functions”,表示厨房,完成一切业务处理。在其中新建一个类,“yanghui.cs”来完成杨辉三角形的生成,如下图:

      新建文件夹:

      

      新建类:

      

      选择类型为类,名称为yanghui:

      这个类最主要的功能就是根据输入的层数,完成杨辉三角形的计算。所以可以把这个操作写成它的静态方法(不用实例化就可以调用)

      代码如下:  

    public class Yanghui
        {
            public static int[,] get_Yanghui(int n)
            {
                int[,] a;
                a = new int[n, n];
                for (int i = 0; i < n; i++)
                {
                    a[i, 0] = 1;
                }
                for (int i = 1; i < n; i++)
                {
                    for (int j = 1; j <= i; j++)
                    {
                        a[i, j] = a[i - 1, j - 1] + a[i - 1, j];
                    }
                }
                return a;
            }
        }

      控制器简化为:

    public ActionResult Index(int n=0)
            {
                if (n == 0)
                {
                    ViewData["d1"] = null;
                }
                else
                {
                    ViewData["d1"] = Yanghui.get_Yanghui(n);
                }
                return View();
            }

      别忘了在控制器文件的头部引入业务逻辑所在的名称空间:

    using WebApplication1.functions;

      这样的控制器,看起来才像个老板的样子,仅负责调度。项目也更加清晰。

      即:根据输入的参数,决定哪些东西送厨房加工,哪些东西直接让服务员拿给客户。

      视图代码不变,程序执行的效果也不变,但整个程序更加清晰流畅了。

    模型:

      直观认识:

        上一篇控制器和视图的课程最后,给大家留了一个完成对学生数据增删改查的小作业。那个时候,我们的程序逻辑都集中在控制器中。

        现在我们可以回头想想,程序应该如何布局。由于通篇都是是对数据库的基本操作,动用“厨房”,是不是感觉也有点不太对。

        对于这种“体力活”,我们可以引入一个新的模块来处理----模型。

        那个例子中,所有的操作都是对“学生”数据完成。“学生”就成了一个频繁和数据库交互的部分。它一方面要跟数据库打交道,另一方面又需要跟程序有交集。就像一根钉子,嵌在物体里的部分要尖,被敲击的部分要平。

        模型也是如此。它负责跟数据库打交道,有了它之后,程序里就不用再去管库……甚至不用管库里的逻辑(当然,写模型的时候这些都要管);另一方面,它必须向“厨房”和“老板”提供很好的使用方法。我们通常也用类来完成模型的工作。

        以下代码可以作为模型用在那个例子当中:

    class Student
        {
            string id,xm, nl, zy,sql;//sql是某条记录准备执行的操作语句
            public Student(string input_id)//构造函数1,只初始化编号,显然准备删除自己
            {
                id = input_id;
            }
            public Student(string input_xm,string input_nl,string input_zy)//构造函数2,没有编号,看样子要把自己插入表中
            {
                xm=input_xm;
                nl = input_nl;
                zy = input_zy;
            }
            public Student(string input_id,string input_xm, string input_nl, string input_zy)//构造函数3,啥都有,用于更新
            {
                id = input_id;
                xm = input_xm;
                nl = input_nl;
                zy = input_zy;
            }
            public void insert_it()//插入方法
            {
                sql = "insert into xs(xm,nl,zy) values('"+xm+"',"+nl+",'"+zy+"')";
                Hc_db.do_nonquery(sql);
            }
            public void modify_it()//修改方法
            {
                sql = "update xs set xm='"+xm+"',nl="+nl+",zy='"+zy+"' where id="+id;
                Hc_db.do_nonquery(sql);
            }
            public void delete_it()//删除方法
            {
                sql = "delete from xs where id=" + id;
                Hc_db.do_nonquery(sql);
            }
        }

        有了Student类(模型)这个工具,控制器只需要接到数据和请求的操作后,new一个具体的“学生”对象出来,就可以直接操作了。有点像客人只点了一杯清水,老板可以直接让打水的小厮端上来就好。

        比如,处理删除的控制器代码大致是这样(不严谨,仅供参考):

    public ActionResult Index(string stu_id)
            {
                Student stu = new Student(stu_id);
                stu.delete_it();
                return View();
            }

        转书上P41

        请大家按照这种逻辑,忘掉上面的代码,自己写一套学生信息管理程序(MVC俱全)

    小综合练习:

        上例中,如果处理这些操作的业务逻辑比较复杂(比如在删除学生之前需要判断该学生成绩是否合格,操作者权限是否足够等等),则直接交给“厨房“执行。

        参考这种思想,结合之前的知识,在上面例子的基础上写一套带权限管理的学生信息管理程序。内容如下:

          1、网站起始页显示所有学生信息。

          2、网站用户分为”未登录“、”普通“、”管理员“三个级别。

          3、未登录用户仅能查看所有学生信息。

          4、普通用户可以查询指定学生信息、添加新学生。

          5、管理员可以修改、删除学生信息。

  • 相关阅读:
    微信小程序退款【证书的使用】
    生成随机位数的UUID
    弹出层-layui
    load加载层-layui
    form-layui
    table-layui
    下拉列表模仿placeholder效果
    .net core 2.0 Unable to convert MySQL date/time to System.DateTime
    .net core Include问题
    .net core 2.0 配置Session
  • 原文地址:https://www.cnblogs.com/wanjinliu/p/11519024.html
Copyright © 2020-2023  润新知