• mvc_第二遍


    之前,我们学习了mvc最基本的架构和用法。

    在学习了真正的属性、委托和列表之后,我们就可以使用微软提倡的模型了。

    需要注意的是,这种模型以及它的工作方式,身上有着浓浓的微软印记。在方便的同时,也要自行考虑各种风险。这一点,以后不再提。

    把模型运用到mvc框架中,可以看到微软提供的各种高效率的写法和工具。

    关于模型

    有别于我们以前提到的模型,mvc(这里特指微软的mvc架构,下同)中的模型,属性必须是标准属性,不能是字段。否则很多情况下,无法和其他代码互动。

    对数据库的操作,可以使用EF框架,借助“数据库上下文”类来高效地完成。

    关于这些,微软都进行了很好的封装。利用vs,我们掌握起来也比较轻松。如果模型是咖啡馆负责打水的小工,数据库里的数据是井里的水,那么相比于我们以前类似绳子和桶的数据库操作方法,EF框架就像是抽水机一样方便高效。

    详情请参阅:

    在access当中使用ef框架 (学校教室的机器(vs2013,nuget版本也不够)无法做出效果,可以在自己的机器上完成)

    在sqlserver中使用ef框架

    注意:每张表和对应的模型中,必须有主Key。

    可以看到,vs帮我们写好了数据库上下文(dbcontext)类和模型。利用实体的“SaveChanges”方法,可以把各种数据库修改保存到库中。十分方便。

    具体的模型对应数据库的操作,大家可以参考着list文章里的内容自行类比学习,不难。

    学会了这些,再看看模型的一些常用操作

    模型在C和V中的使用

    按照上面的方法,配置好模型和EF框架之后,我们来看看如何用新东西完成之前的小操作。

    本例中,数据库上下文D1.CS代码如下:

    public partial class D1 : DbContext
        {
            public D1()
                : base(@"server=(localdb)mssqllocaldb;initial catalog=d1;user ID=sa;password=xxx;")
            {
            }
    
            public virtual DbSet<t1> t1 { get; set; }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
            }
        }

    实体类t1.CS代码如下:

    public partial class t1
        {
            [Key]
            [StringLength(10)]
            public string xm { get; set; }
    
            public short? nl { get; set; }
        }

    以上代码大半自动生成,很方便。

    要读出数据库中的学生信息,并且向库中添加内容。

     新建控制器,在index方法中考虑呈现数据:

    public ActionResult Index()
            {
                D1 d1 = new D1();
                return View(d1.t1.ToList());
            }

    其中“return View(d1.t1.ToList());”表示把t1表里的内容转换成List带给视图,视图里用“model”来接收。

    除了呈现,再加一个“添加”表单。对应的视图代码如下:

    @model List<WebApplication1.Models.t1>
    @*上面这一行表示接收过来的数据类型,和控制器方法中return过来的数据类型一致。*@
    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
    </head>
    <body>
        <div>@*呈现代码,简单写*@
            @foreach (var item in Model)
            {
                <text>@item.xm</text><text>@item.nl</text><br />
            }
        </div>
        <hr />
        <form action="/home/add">
            姓名:<input type="text" name="xm" />年龄:<input type="text" name="nl" /><br />
            <input type="submit" name="m" value="添加" />
        </form>
    </body>
    </html>

    注意:1、第一行的内容和注释;2、foreach中in后面的集合名称;3、表单中两个文本框的name属性和模型里的属性是对应的。

    接收提交表单的action是add,代码如下:

    public ActionResult Add(t1 student)
            {
                if(ModelState.IsValid)
                {
                    D1 d1 = new D1();
                    d1.t1.Add(student);
                    d1.SaveChanges();
                    ViewData["msg"] = "ok";
                }
                else
                {
                    ViewData["msg"] = "fail";
                }
                return View();
            }

    由于视图提交过来的是一个“属性对应”的学生信息(http://xxx/home/add?xm=zd&nl=100&m=%E6%B7%BB%E5%8A%A0),在这里,就可以用一个t1的对象student来接收参数。系统会自动试图把传递过来的name和nl两个字段的内容往student里放。

    代码部分的“ModelState.IsValid”就是用来测试这个赋值是否成功。一旦成功,就可以调用模型里的方法【d1.SaveChanges()】写入数据库。

    add对应的view很简单,主要代码为:

    <div> 
            @ViewData["msg"] <br />
            <a href="/home/index">返回操作页</a>
        </div>

    程序运行效果如下:

     填写内容“test1”,“50”,点击“添加”后:

     返回操作页:

     从上面的简单例子,能够体会到mvc模型给控制器和视图带来的简化效果。

    关于控制器

    转书上P65

    接书上P85

    关于书上控制器的返回部分,稍微讲两个地方。方便起见,这里mvc的模型全部用模拟模型

    1、关于Json

      在c#中对数据进行Json序列化和反序列化,常规方法可以参看这里

      控制器中的Json方法也可以对任意类型进行序列化。示例如下:

     public ActionResult Index()
            {
                myDatabase d1 = new myDatabase();
                return Json(d1.t1,JsonRequestBehavior.AllowGet);
            }

      效果:

      用作webapi提供数据的时候很有用。

    2、关于partialview

      mvc中的视图有一种包含关系:母版包含视图(即我们常用的view),视图包含局部视图。

      创建母版的方法如下:

     命名后可以对母版进行编辑,如下:

    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>@ViewBag.Title</title>
    </head>
    <body>
        <div>这里应该放本站所有页的标题……之类的东西</div>
        <div>
            @RenderBody()
        </div>
        <div>版权信息等等东西应该在这里</div>
    </body>
    </html>

    其中“@RenderBody()”就是各个视图的内容,其余部分相对稳定,一般不改变。

    在添加视图的时候选择布局页,就可以使用这个母版:

     视图里的内容可以很简单:

    @{
        ViewBag.Title = "Index";
        Layout = "~/Views/_LayoutPage1.cshtml";
    }
    
    <h2>这是我的Index页面</h2>

    运行效果:

    此外,可以根据需要创建局部视图。

    例如,在新建的局部视图控制器中,新建一个返回局部视图的action,设法包含在刚刚的view里。

    action代码如下:

    public class PartialController : Controller
        {
            // GET: Partial
            public ActionResult ShowData()
            {
                myDatabase d1 = new myDatabase();
                return PartialView(d1.t1.ToList());
            }
        }

    对应的视图ShowData.cshtml代码如下:

    @model List<WebApplication1.Models.Person>
    @if (Model != null)
    {
        foreach (var item in Model)
        {
            <text>@item.Xm</text><text>@item.Nl</text><br />
        }
    }
    else
    {
        <text>没有可以显示的数据</text>
    }

    在正常视图中,调用该局部页(分布视图)时,需要区分“Html.Action”和“Html.Partial”两种调用方法。前者通过控制器调用,后者直接调用视图。

    如下例:

    @{
        ViewBag.Title = "Index";
        Layout = "~/Views/_LayoutPage1.cshtml";
    }
    
    <h2>这是我的Index页面</h2>
    Html.Action直接调用视图的结果:<br />
    @Html.Action("ShowData", "Partial")<br />
    Html.Partial直接调用视图的结果:<br />
    @Html.Partial("~/Views/Partial/ShowData.cshtml")

    运行结果如下:

     和普通视图一样,分布式视图一样可以接收传递过来的模型或其他数据,一般用作“页面类的方法”。即,反复使用的小页面部分(如显示某固定类型的数据等等)

     关于视图

    刚刚为了介绍控制器的各种ActionResult返回值,提到了一部分视图的内容。它们包括1、母版、视图、分部视图;2、返回view时携带模型,及视图中应用模型。

    除此之外,微软还为视图提供了一些写法。微软说,这些写法能减轻程序员的工作量,大家在学习的时候,自行考虑成本和收益。

     转书上P103

    接书上P113

    强类型“视图/模型/控制器”联动

    以下两个例子着重表现微软自动生成代码的强大,也就是之前付出“学习成本”的“收获”。

    综合例1:创建综合控制器

    按照之前的内容,使用EF框架连接数据库之后,在添加控制器的时候,可以利用“读/写”选项自动创建一系列的Action,不用我们手动编码。如下图:

     选定名称后,出来的控制器里包含的内容如下:

     1 public class Home1Controller : Controller
     2     {
     3         // GET: Home1
     4         public ActionResult Index()
     5         {
     6             return View();
     7         }
     8 
     9         // GET: Home1/Details/5
    10         public ActionResult Details(int id)
    11         {
    12             return View();
    13         }
    14 
    15         // GET: Home1/Create
    16         public ActionResult Create()
    17         {
    18             return View();
    19         }
    20 
    21         // POST: Home1/Create
    22         [HttpPost]
    23         public ActionResult Create(FormCollection collection)
    24         {
    25             try
    26             {
    27                 // TODO: Add insert logic here
    28 
    29                 return RedirectToAction("Index");
    30             }
    31             catch
    32             {
    33                 return View();
    34             }
    35         }
    36 
    37         // GET: Home1/Edit/5
    38         public ActionResult Edit(int id)
    39         {
    40             return View();
    41         }
    42 
    43         // POST: Home1/Edit/5
    44         [HttpPost]
    45         public ActionResult Edit(int id, FormCollection collection)
    46         {
    47             try
    48             {
    49                 // TODO: Add update logic here
    50 
    51                 return RedirectToAction("Index");
    52             }
    53             catch
    54             {
    55                 return View();
    56             }
    57         }
    58 
    59         // GET: Home1/Delete/5
    60         public ActionResult Delete(int id)
    61         {
    62             return View();
    63         }
    64 
    65         // POST: Home1/Delete/5
    66         [HttpPost]
    67         public ActionResult Delete(int id, FormCollection collection)
    68         {
    69             try
    70             {
    71                 // TODO: Add delete logic here
    72 
    73                 return RedirectToAction("Index");
    74             }
    75             catch
    76             {
    77                 return View();
    78             }
    79         }
    80     }

    可以看到列表、呈现单条数据、增删改的控制器全部写好,不用我们动手。

    不过瘾?看下面。

    综合例二:

    在添加控制器的时候,选择“包含视图”。如下图:

     在弹出的对话框中选择对应内容:

      其中D1是库,t1是表(里面的记录)

    vs创建完毕后,运行,结果为下图:

     这个界面不稀奇,神奇的是……所有链接下的功能,都可以工作!!!你做了什么?你一个字的代码都没写。

    以“创建”为例,提交后自动的Action为:

     1 [HttpPost]
     2         [ValidateAntiForgeryToken]
     3         public ActionResult Create([Bind(Include = "id,nl")] t1 t1)
     4         {
     5             if (ModelState.IsValid)
     6             {
     7                 db.t1.Add(t1);
     8                 db.SaveChanges();
     9                 return RedirectToAction("Index");
    10             }
    11 
    12             return View(t1);
    13         }

    自动生成的视图为:

     1 @model WebApplication3.Models.t1
     2 
     3 @{
     4     Layout = null;
     5 }
     6 
     7 <!DOCTYPE html>
     8 
     9 <html>
    10 <head>
    11     <meta name="viewport" content="width=device-width" />
    12     <title>Create</title>
    13 </head>
    14 <body>
    15     @using (Html.BeginForm()) 
    16     {
    17         @Html.AntiForgeryToken()
    18         
    19         <div class="form-horizontal">
    20             <h4>t1</h4>
    21             <hr />
    22             @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    23             <div class="form-group">
    24                 @Html.LabelFor(model => model.id, htmlAttributes: new { @class = "control-label col-md-2" })
    25                 <div class="col-md-10">
    26                     @Html.EditorFor(model => model.id, new { htmlAttributes = new { @class = "form-control" } })
    27                     @Html.ValidationMessageFor(model => model.id, "", new { @class = "text-danger" })
    28                 </div>
    29             </div>
    30     
    31             <div class="form-group">
    32                 @Html.LabelFor(model => model.nl, htmlAttributes: new { @class = "control-label col-md-2" })
    33                 <div class="col-md-10">
    34                     @Html.EditorFor(model => model.nl, new { htmlAttributes = new { @class = "form-control" } })
    35                     @Html.ValidationMessageFor(model => model.nl, "", new { @class = "text-danger" })
    36                 </div>
    37             </div>
    38     
    39             <div class="form-group">
    40                 <div class="col-md-offset-2 col-md-10">
    41                     <input type="submit" value="Create" class="btn btn-default" />
    42                 </div>
    43             </div>
    44         </div>
    45     }
    46     
    47     <div>
    48         @Html.ActionLink("Back to List", "Index")
    49     </div>
    50 </body>
    51 </html>

    所有的一切,都很完美。所有的代码,差不多都认识。

    你现在只需要在这个程序的基础上做你需要的修改(美工、逻辑等等)就可以了。而我们前面讲的代码(辅助方法、视图、兰姆达表达式等等)都是为了让你会修改准备的。

    至此,前面的付出似乎都有回报了。

    ps:要实现这种全自动,需要全程循规蹈矩。比如,用整数id做索引,设置key等等。。。。

  • 相关阅读:
    WBS分析
    需求分析-NABCD
    电梯演讲--2048小游戏
    Git diff 算法
    2020 北京理工大学889 回忆
    抖音后台开发社招面试
    珍宝阁
    2018 北京理工大学复试上机 回忆版
    2018 北京理工大学889 回忆
    做一个博客
  • 原文地址:https://www.cnblogs.com/wanjinliu/p/11707743.html
Copyright © 2020-2023  润新知