zoukankan      html  css  js  c++  java
  • ASP.NET MVC学习---(五)MVC初体验

    经过之前n多的铺垫

    我们已经大概了解了这个姓m名vc的家伙了

    那么今天我们就来体验一把

    怎么体验呢?

    就来做一个小例子吧~

    mvc增删改查的例子


    数据库还是之前我们的老朋友

    关系图:

    表中的数据已填好

    T_Users

    将就着用着吧,哈哈

    现在要求对T_Users表进行增删改查

    开搞~


    回到之前新建的mvc项目

    在Controllers文件夹下新建一个名为Home的空控制器


    当浏览器请求Home下面的Index方法的时候返回什么?

    当然是主页面啦

    这里我们的主页面就是显示T_Users数据列表

    代码如下:

    //首先我们需要一个EF上下文实例,这是必须的
            private Entities dbEntities = new Entities();
    
            //通过数据上下文将T_Users的数据查询出来并展示
            public ActionResult Index()
            {
                //将T_Users表的数据都取出来
                var users = dbEntities.T_Users.Where(u => true).ToList();
                //并交给ViewData.Model
                ViewData.Model = users;
                return View();
            }
    这个ViewData.Model是个啥飞机?

    别急~

    我们先接着往下走

    在Index方面上右键->添加视图

    注意先不要使用母版页哦~

    Index.cshtml代码如下:

    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
    </head>
    <body>
        <div>
            
        </div>
    </body>
    </html>

    很正规的一个html页面

    等等

    头部的Layout=null又是个啥飞机?

    Layout就是一个布局的意思

    我们可以看到Layout=null是被包在一个@{ }里面的

    前面我们说过

    这是一种razor视图引擎的语法,那么久很明显这是一行C#代码

    其实它的作用就是将本页面的布局页(也可以说是母版页)清空

    因为我们新建视图的时候没有选择嘛~

    如果你选择了使用母版页,Layout就会指向一个母版页文件


    那么我们继续往下走~

    在这个html页中

    用一个table标签来展示T_Users的数据

    <table id="tbList">
                <tr>
                    <td>Id
                    </td>
                    <td>UserName
                    </td>
                    <td colspan="2">操作
                    </td>
                </tr>
                @foreach (var u in Model)
                {
                    <tr>
                        <td>@u.Id
                        </td>
                        <td>@u.UserName
                        </td>
                        <td>
                            <a href="/Home/Modify/@u.Id">Modify</a>
                        </td>
                        <td>
                            <a href="/Home/Delete/@u.Id">Delete</a>
                        </td>
                    </tr>
                }
            </table>

    这段代码没啥难度吧~

    但是foreach循环的那个Model是哪里来的,为什么它会有我们需要的数据?

    回头想想

    之前我们是不是把users都交给了ViewData的一个Model属性?

    没错,ViewData的Model属性在前台可以直接通过Model访问

    在后台,你甚至可以这样做:

    public ActionResult Index()
            {
                //将T_Users表的数据都取出来
                var users = dbEntities.T_Users.Where(u => true).ToList();
                //并交给ViewData.Model
                //ViewData.Model = users;
                return View(users);//直接将users当做参数传入View,可以直接在前台用过Model属性来获得数据
            }
    这两种方式效果是一样的

    不信你试试~我会骗你?

    试试又不用钱~


    那么这时可能会有一个问题

    如果我要传两个数据给前台怎么办?

    都用Model吗

    那不就覆盖了?

    这时候ViewBag就要登场了

    我们在将代码改成这个样子

    //通过数据上下文将T_Users的数据查询出来
            public ActionResult Index()
            {
                //将T_Users表的数据都取出来
                var users = dbEntities.T_Users.Where(u => true).ToList();
                //并交给ViewData.Model
                //ViewData.Model = users;
    
                //通过ViewBag传递数据给前台
                ViewBag.Users = users;
                return View();
            }

    注意!

    ViewBag后面的Users属性并不是固定的

    也就是说

    你可以根据你的爱好,随便你怎么取名ViewBag的属性,然后只要将数据交给它就ok!

    爽不爽?~

    当然,在前台现在就不能用Model属性了

    @foreach (var u in ViewBag.Users)
                {
                    <tr>
                        <td>@u.Id
                        </td>
                        <td>@u.UserName
                        </td>
                        <td>
                            <a href="/Home/Modify/@u.Id">Modify</a>
                        </td>
                        <td>
                            <a href="/Home/Delete/@u.Id">Delete</a>
                        </td>
                    </tr>
                }
    在后台,你用ViewBag点了什么属性赋值了数据,在前台同样通过这个属性取数据
    这样一来我们就可以通过ViewBag随意的传递n多数据了

    很方便吧~

    现在先来瞧瞧网站运行起来的样子(在mvc项目上右键浏览器中查看)

    数据是出来了

    但是..

    这也太丑了吧

    加点样式~

    <head>
        <meta name="viewport" content="width=device-width" />
        <style type="text/css">
            #tbList
            {
                border: 1px solid #0094ff;
                 400px;
                margin: 20px auto;
                border-collapse: collapse;
            }
    
                #tbList td, #tbList th
                {
                    border: 1px solid #0094ff;
                    padding: 20px;
                }
        </style>
        <title>Index</title>
    </head>

    保存,刷新

    是不是好看了一点= =

    将就着用吧~


    好了,查询搞定

    那接下来就先做新增

    <tr>
                <td>Id
                </td>
                <td>UserName
                </td>
                <td>操作
                </td>
                <td>
                    <a href="/Home/Create">新增</a>
                </td>
            </tr>

    原谅我随便找了一个地方插进去一个超链接....

    在后台的Home控制器中就要添加一个对应的Create方法

    //返回新增的页面
            public ActionResult Create()
            {
                return View();
            }

    还是右键添加视图

    显示一个新增的页面

    <body>
        <form action="/Home/Create" method="POST">
            <input type="text" name="txtUserName"/>
            <input type="submit" value="添加"/>
        </form>
    </body>

    看到这个form的action指向Home的Create方法有同学就会有疑问了

    前面展示新增页面也是指向Create方法,现在提交数据表单也指向Create方法

    那怎么搞?

    上代码:

     //用HttpPost来标记本方法只有post请求的时候才会被执行
            [HttpPost]
            public ActionResult Create(T_Users user)
            {
                string userName = Request.Form["txtUserName"];
                user = new T_Users() {UserName = userName};
                dbEntities.T_Users.Add(user);
                dbEntities.SaveChanges();
                //重定向到Index方法,作用相当于webform的Response.Redirect
                return Redirect("/Home/Index");
            }


    现在明白了吧~

    我们只需要在方法之前加个[HttpPost]标记就ok

    反之[HttpGet]当然是只有get请求才会被执行的咯~

    好的

    代码完成,重新生成,然后刷新页面

    点击新增超链接,出现新增页面

    是不是有点简单...

    随便啦~

    点击添加按钮提交表单

    成功添加~


    接下来在后台在添加一个Modify修改方法

    //显示修改页面
            public ActionResult Modify(int id)
            {
                //根据id取出数据库中对应的数据
                var user = dbEntities.T_Users.Where(u => u.Id == id).FirstOrDefault();
                return View(user);
            }
    添加视图,html代码:

    <body>
        <form action="/Home/Modify/@Model.Id" method="POST">
            <input type="text" name="UserName" value="@Model.UserName"/>
            <input type="submit" value="保存修改"/>
        </form>
    </body>
    这里需要注意一个问题,文本框标签的name属性的取值最好为对应实体的属性名

    什么意思呢?

    就那上面的例子来说

    T_Users有一个UserName属性,那么这个文本框是针对该属性设置的,所以name="UserName"

    如果有一个文本框是针对Id属性的,那么这个文本框的name最好等于Id

    为什么要这么做?

    因为如果name=具体的实体属性的话

    表单提交到后台的时候Modify方法用一个T_Users参数接收,系统会将表单中 name值 和 T_Users属性同名 的标签 值 自动填充到 T_Users对象对应的属性中

    如:

    //接收post请求的修改方法
            [HttpPost]
            public ActionResult Modify(T_Users user)//如果表单中的标签 name值 等于 user的属性名 系统会自动将表单中的值填充到此user实体中
            {
                //附加实体到数据上下文,并设置属性的修改状态
                var entry = dbEntities.Entry(user);
                entry.State = EntityState.Unchanged;
                entry.Property("UserName").IsModified = true;
                dbEntities.SaveChanges();
                return Redirect("/Home/Index");
            }

    这叫做模型绑定

    当然你也可以不按照这个规定来

    只是需要另外接收表单的参数而已~

    这时候我们重新生成并刷新页面

    点击Modify超链接

    这时有可能会出现一个错误,如下图:

    别着急,不要一看到异常就慌~

    这是一个mvc实体验证的设置

    我们为Home控制器类添加一个构造函数,并在构造函数中关闭实体验证即可

    public HomeController()
            {
                //关闭实体验证
                dbEntities.Configuration.ValidateOnSaveEnabled = false;
            }

    现在在来重新生成并刷新~

    点击保存


    成功修改~


    最后的删除方法就简单了

    //删除方法
            public ActionResult Delete(int id)
            {
                T_Users user = new T_Users() {Id = id};
                dbEntities.T_Users.Attach(user);
                dbEntities.T_Users.Remove(user);
                dbEntities.SaveChanges();
                return Redirect("/Home/Index");
            }

    这里直接点击删除超链接就执行删除方法

    如果有需要你也可以添加一个视图先展示一下要删除的数据,然后在点击确定删除~


    最后提一个关于生成下拉框的小小的问题

    如果在展示修改页面的时候要求将该user实体关联的T_Products实体用下拉框显示出来

    T_Products表如下:

    第一种做法:

    在后台取出相应的T_Products数据

    //显示修改页面
            public ActionResult Modify(int id)
            {
                //根据id取出数据库中对应的数据
                var user = dbEntities.T_Users.Where(u => u.Id == id).FirstOrDefault();
                //查询出T_Products表中属于该对象的数据
                var products = dbEntities.T_Products.Where(p => p.Uid == id).ToList();
                //并将其传入ViewBag
                ViewBag.Products = products;
                return View(user);
            }

    前台展示:

    <body>
        <form action="/Home/Modify/@Model.Id" method="POST">
            <input type="text" name="UserName" value="@Model.UserName"/>
            <select name="T_Products">
                @foreach (var p in ViewBag.Products)
                {
                    <option value="@p.Id">@p.ProName</option>
                }
            </select>
            <input type="submit" value="保存修改"/>
        </form>
    </body>

    页面效果:

    这是正常使用htmlselect标签的方法

    但是在mvc中还提供Lee另外一种方式


    第二种做法:

    先来看前台代码

    <body>
        <form action="/Home/Modify/@Model.Id" method="POST">
            <input type="text" name="UserName" value="@Model.UserName"/>
            @*第一种做法:
            <select name="T_Products">
                @foreach (var p in ViewBag.Products)
                {
                    <option value="@p.Id">@p.ProName</option>
                }
            </select>*@
            
            @*第二种做法,使用HtmlHelper类*@
            @Html.DropDownList("T_Products",ViewBag.Products as IEnumerable<SelectListItem>)
            <input type="submit" value="保存修改"/>
        </form>
    </body>

    HtmlHelper类时mvc内置的一个帮助程序员快速生成html代码的类,可以简写成Html

    例如本例中的Html.DropDownList最终就是生成一个下拉框

    其第一个参数是下拉框的name属性,第二个参数是一个IEnumerable<SelectListItem>类型的集合(就是要展示的数据,但是要先转成IEnumerable<SelectListItem>才行)

    所以在后台

    我们先拿到要展示的数据

    //显示修改页面
            public ActionResult Modify(int id)
            {
                //根据id取出数据库中对应的数据
                var user = dbEntities.T_Users.Where(u => u.Id == id).FirstOrDefault();
    
                //第一种做法
                //查询出T_Products表中属于该对象的数据
                //var products = dbEntities.T_Products.Where(p => p.Uid == id).ToList();
                //并将其传入ViewBag
                //ViewBag.Products = products;
    
    
                //第二种做法
                List<SelectListItem> products =
                    dbEntities.T_Products.Where(p => p.Uid == id)
                        .ToList()//查询出T_Products集合
                        .Select(p => new SelectListItem { Text = p.ProName, Value = p.Id.ToString() })//将实体集合转换成SelectListItem类型
                        .ToList();//在转换成List<SelectListItem>集合
                //传入ViewBag
                ViewBag.Products = products;
                return View(user);
            }

    重新生成并刷新

    两种方式的效果是一样的

    第二种是mvc特有的

    现在可能使用起来很不习惯

    但是HtmlHelper是mvc开发经常使用的类

    以后我们会在详细说明


    好了,现在一套mvc的基本增删改查已经完成

    多多少少还是有点收获的是吧~


  • 相关阅读:
    【BZOJ 1598】 牛跑步
    【SDOI 2010】 魔法猪学院
    【POJ 2449】 Remmarguts' Date
    【HDU 3085】 Nightmare Ⅱ
    【POJ 3635】 Full Tank
    【POJ 2230】 Watchcow
    USB设备驱动总结
    经典SQL语句大全
    float型数据与字节数组的转化
    linux下dmesg命令详解
  • 原文地址:https://www.cnblogs.com/jchubby/p/4429719.html
Copyright © 2011-2022 走看看