zoukankan      html  css  js  c++  java
  • ASP.NET MVC学习笔记(一) 从路由开始创建mvc

      之前一篇写一半发现版本太老了,是基于mvc2的。

      两本参考书编写的顺序各方面都不太一样。决定重新写一篇。

      我这篇文章基于mvc5,vs2015

    参考书:Will保哥的ASP.NET MVC4开发指南

    一、创建一个项目

      

    目录图解

    1.从路由开始

     

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Routing;
    
    namespace MvcGuestbook
    {
        public class RouteConfig
        {
            public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
                routes.MapRoute(
                    name: "Default",
                    url: "{controller}/{action}/{id}",
                    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
                );
            }
        }
    }

     IgnoreRoute:目的是设定 *.axd等格式的文件不要通过ASP.NET运行,意义在于让webform和mvc文件可以在同一个平台独立运行互不干扰。

     MapRoute:MapRoute方法是定义mvc网址路由的最主要方式。

                      这一条路由定义了三个参数:

                      name:路由名称

                      uri:设置网址路径如何对应到控制器、动作与路由值

                      default:设置了{Controller}{Action}{Id}这三个路由参数的默认值

    如下图网址

    其中{controller}是home,{action}是About。ASP.NET MVC会先进入Controllers目录找home控制器(homeController.cs文档),再找About公开方法,这个公开方法就是MVC的action,也是实际运行网页程序的公开入口。

    如在浏览器中输入 http://localhost/ 想取得首页,由于网址路径部分没有任何属性,就会使用MapRoute的第三个参数(defaults)所设置的默认值来代替。因此网站会从Controllers目录查找Home控制器再查找Index这个公开方法,再进一步运行ASP.NET MVC。

    我们来看一下HomeController的属性:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace MvcGuestbook.Controllers
    {
        public class HomeController : Controller
        {
            public ActionResult Index()
            {
                return View();
            }
    
            public ActionResult About()
            {
                ViewBag.Message = "Your application description page.";
    
                return View();
            }
    
            public ActionResult Contact()
            {
                ViewBag.Message = "Your contact page.";
    
                return View();
            }
        }
    }

      顺带补充controller类的规范:

    1)必须用“Controller”结尾。

    2)继承Controller基类(或实现IController接口)。

    3)类中必须包含数个返回值为“ActionResult”的公开方法,这些方法在ASP.NET MVC中被称为Action。

      可以看到,在上述代码Index行为中,第一行的ViewBag.Message是一个动态型(daynamic)的对象,因此可以放进任意型别的数据进去,这些属性和值都可以在ASP.NET MVC的View中读取。

      ViewBag.Message = "Your application description page.";

    我们查看HomeController中Index的视图

         

    我们会发现Index.cshtml并不是一个完整的HTML页面,我们来看看主版面设置在哪里。

    打开项目目录,我们会发现Views目录下有一个_ViewStart.cshtml文件

                                      

      打开这个文件后里面只有三行代码。其中定义了Layout属性,并指向了"~/Views/Shared/_Layout.cshtml",默认所有View文件都会被装入该主板页面。打开_Layout.cshtml文件,我们不难发现里面的代码才是完整的HTML结构。

      至于我们在之前的Controller中看到ViewBag.Message被设置了一串字符串,到了Index.cshtml检视(View)就可以通过以下语法读出并显示于网页属性中。

    @ViewBag.message
    

    另外Index.cshtml页最上方设置了一组ViewBag.Title属性,这里定义的属性值也会被自动传入同一个View和以及默认的_Layout.cshtml主版页面

            

    2.创建数据模型

    step1

    step2

    step3 定义出一个留言板所需的数据模型

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace MvcGuestbook.Models
    {
        public class Guestbook
        {
            public int Id { get; set; }
            public string 姓名 { get; set; }
            public string Email { get; set; }
            public string 内容 { get; set; }
        }
    }

    step4 生成一次解决方案确定没有问题

    3.创建控制器、动作与检视

    step1 我们这里不选择直接建空的控制器,我们选择利用基架(Scaffold)

           

     

    step2

     

     

    step3

    其实此时已经完成,我们只需要按f5开始调试就可以了。

    输入网址,进行试验

      我们这个网站的页面功能还请大佬们自行测试一下,虽然我们没自行写代码但是程序确实已经完成了,mvc5的功能很是强大。

    4.查看数据库属性

      上述网站调试中我输入过一组数据,这组数据肯定是被存到哪里了,那么我们来看下这些数据被放到哪里去了。

      我们点击解决方案资源管理器下面的显示所有文件按钮,就会显示出隐藏的文件,如下图。

                                                   

      我们点击那个按键后,App_Data下出现了一个 .mdf文件,这是一个数据库文档。

      其中,项目模板会先在web.config文档中创建一个DefaultConnection连接字符串。

      能在web.config中看到连接字符串演示

      <connectionStrings>
        <add name="DefaultConnection" connectionString="Data Source=(LocalDb)MSSQLLocalDB;AttachDbFilename=|DataDirectory|aspnet-MvcGuestbook-20170327110627.mdf;Initial Catalog=aspnet-MvcGuestbook-20170327110627;Integrated Security=True"
          providerName="System.Data.SqlClient" />
        <add name="MvcGuestbookContext" connectionString="Data Source=(localdb)MSSQLLocalDB; Initial Catalog=MvcGuestbookContext-20170327151548; Integrated Security=True; MultipleActiveResultSets=True; AttachDbFilename=|DataDirectory|MvcGuestbookContext-20170327151548.mdf"
          providerName="System.Data.SqlClient" />
      </connectionStrings>

      vs2015中,我们可以直接选择 MvcGuestbookContext-(日期).mdf 个文档,打开后可以自由的浏览或变更数据库架构。

     二、认识自动生成的代码

       之前代码均由mvc5自动生成,接下来让我们来了解下这些通过工具自动帮我们逐步生成的代码。

      1.了解列表Index()动作

      打开Controller目录下的GuestbookController.cs。

      其中第一行定义了MvcGuestbookContext类的私有变量,也就是我们的数据内容类。这整个Controller类都会用db这个变量对数据库进行访问

     private MvcGuestbookContext db = new MvcGuestbookContext();

      Index的公开程序代码很简单,只有一行。

      其中View()是来自Controller基类的一个辅助方法,该辅助方法有8个重载,其中第3个多载是传入一个model参数,此参数的对象数据会传给View使用。

                               

      这里我们传入了db.Guestbooks.ToList(),代表着把所有Guestbooks回传的所有数据全部传入View中,让View里的程序去使用。接着,我们切换到Index动作方法(Action Method)对应的视图的检视页面(View Page)。

                               

    2.了解列表页面的Index检视

      在Views/Guestbook/Index.cshtml 检视页面的第一行,里面有一个@model声明,后面便是一个IEnumerable类,IEnumerable是Guestbook的集合对象。表示View会以用@model声明的类别为“主要模板”,在View里面的程序代码也会参考到该类别使用

    @model IEnumerable<MvcGuestbook.Models.Guestbook>

     

      接下来这段 ViewBag.Title的设置在本页中没有用到,而是要传给主版页面(Layout Page)用的,显示在HTML的Title卷标中

    @{
        ViewBag.Title = "Index";
    }

      下面一段代码是用来创建ASP.NET MVC链接的,链接显示为"Create New",而该链接将会链接到这页控制器的Create动作(Action),超链接的输出则由ASP.NET MVC负责。

    <p>
        @Html.ActionLink("Create New", "Create")
    </p>

       由于是列表页面,有<table>标签,会将页面输出成表格

        <tr>
            <th>
                @Html.DisplayNameFor(model => model.姓名)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Email)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.内容)
            </th>
            <th></th>
        </tr>

      @Html.DisplayNameFor()的主要用途是输出特定字段的显示名称,传入的参数是一个Lambda Expression表示法,该表示法里传入的model变量代表的正是我们在View里第一页设置的@model型别,所以我们可以在挑选字段的时候利用vs的Intellisense来帮助选择。@Html.DisplayNameFor()会默认直接输出属性名称。最后输出html页面如下:

    <tr>
      <th>
           姓名
      </th>
      <th>
           Email
      </th>
      <th>
           内容
      </th>
      <th></th>
    </tr>

      若要输出的显示名称和属性名称不同,则必须更改Guestbook模型类别的定义,在特定一个属性(Property)上加上一个System.ComponentModel命名空间下的DisplayName属性(Attribute),在我们这里将Email字段显示名称更改成“电子邮件地址”,如下:

      修改完就可以直接f5运行网站。可以看到Email字段所输出的域名直接变成了“电子邮件地址”。显示的html代码如下:

    <tr>
      <th>
           姓名
      </th>
      <th>
           Email
      </th>
      <th>
           电子邮件地址
      </th>
      <th></th>
    </tr>

      View最后一段Code是一个数据来自Model对象的foreach循环。这里的Model对象是每个View都有的属性,代表的就是从Controller传过来的数据,而这个Model对象本身就是泛型类,也就是说这个Model对象的类会完全等同于你在View最上方用@model声明的类。

      代码如下,我们通过循环取出Model里的每条数据,每条数据的类型刚好是MvcGuestbook.Models.Guestbook的模型类型。

    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.姓名)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Email)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.内容)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
                @Html.ActionLink("Details", "Details", new { id=item.Id }) |
                @Html.ActionLink("Delete", "Delete", new { id=item.Id })
            </td>
        </tr>
    }

      刚刚是@Html.DisplayNameFor辅助方法,现在看到的是@Html.DisplayFor辅助方法,这段code被包含在@foreach循环中,所以传入@Html.DisplayFor的模型数据将会是循环内单条MvcGuestbook.Models.Guestbook模型的数据。

      上述代码最后三行是edit,details,delete的链接,@Html.ActionLink()的用途是用来输出超链接的。

      @Html.ActionLink("Edit", "Edit", new { id=item.Id }),第一个"Edit"是链接显示的文字,第二个"Edit"是链接的目的Action名称,第三个是代表路由参数名称id。第三个代表路由参数名称的id会在mvc在输出超链接时,加上要传给下一页的路由参数,方便ASP.NET MVC知道你除了传入{Controller},与{Action}路由参数外,顺便给予{id}路由值。这里的{id}稍后将提及,在Edit动作时会提及。

      我们来了解下创建窗体窗口的Create动作。

      切回到GuestbookControllers类里观察创建信息功能的动作的Action。控制器里有两个同名的Create方法,一个是给Http Get用的一个是给Http Post用的。

      值得一提的是,第二个Create有特别套用的一个HttpPost属性(Attribute),该属性告知ASP.NET框架此Action只接受Http Post过来的信息,这个属性又有另一个专有名词叫动作过滤器(Action Filter)或者动作选择器(Action Selector)

    // GET: Guestbooks/Create
            public ActionResult Create()
            {
                return View();
            }
    // POST: Guestbooks/Create
            // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
            // 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598
            [HttpPost]
            [ValidateAntiForgeryToken]
            public ActionResult Create([Bind(Include = "Id,姓名,Email,内容")] Guestbook guestbook)
            {
                if (ModelState.IsValid)
                {
                    db.Guestbooks.Add(guestbook);
                    db.SaveChanges();
                    return RedirectToAction("Index");
                }
    
                return View(guestbook);
            }

      首先我们进入http://localhost:63471/Guestbooks/Index页面之后首先Http执行的方法一定是Get,因此第一个Create()动作会首先被ASP.NET MVC选中运行,并显示默认的Create检视页面(View Page)。

      切换至Create检视页面。

      了解创建窗体的Create 检视页面

    @model MvcGuestbook.Models.Guestbook

      开头依旧来了个@model声明,声明此页面以MvcGuestbook.Models.Guestbook为主要模型

      接着出现了一个ASP.NET MVC的窗体声明与窗体内Html声明,代码如下:

    @using (Html.BeginForm()) 
    {
        @Html.AntiForgeryToken()
        <div class="form-horizontal">
            <h4>Guestbook</h4>
            <hr />
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            <div class="form-group">
                @Html.LabelFor(model => model.姓名, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.姓名, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.姓名, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                @Html.LabelFor(model => model.内容, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.内容, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.内容, "", new { @class = "text-danger" })
                </div>
            </div>
    
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Create" class="btn btn-default" />
                </div>
            </div>
        </div>
    }

      这里我们使用的是Html.BeginForm()辅助方法,该方法会输出<form>标签,而且用using包裹起来,如此便可以在using代码结束时让ASP.NET帮你补上<form>标签,而且必须以using包起来,这样就可以在using结束代码最后退出的时候让ASP.NET MVC帮补上</form>,以本页为例,最后输出的代码就是:

    <form action="/Guestbook/Create" method="post">
      ...
    
    </form>

     @Html.ValidationSummary(true, "", new { @class = "text-danger" })是用来显示表单域发生验证失败时,显示的错误消息。

    在这个创建信息的窗体中一共有三个字段,你会发现这三个字段的定义都差不多。

    <div class="form-group">
                @Html.LabelFor(model => model.姓名, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.姓名, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.姓名, "", new { @class = "text-danger" })
                </div>
            </div>

    @Html.LabelFor()用来显示特定字段的显示名称。和@Html.DisplayNameFor()类似,而用@Html.DisplayNameFor()只会输出域名,使用@Html.LabelFor()会输出包含<label>标签的域名。

    @Html.LabelFor()和@Html.DisplayNameFor()的输出比较

    Razor语法 Html显示结果
    @Html.DisplayNameFor(Model=>model.Email) 电子邮件地址
    @Html.LabelFor(Model=>model.Email) <Label for="Email">电子邮件地址<Label>

      ASP.NET中主要使用@Html.EditorFor来输出表单域,以此字段为例,输出的Html代码如下,这里出现的class属性是默认输出的,可以设计css样式来改变该输出字段的样式:

    <input class="text-box single-line" name="姓名" type="text" value="" />

      最后一个@Html.ValidationMessageFor是用来显示字段验证的错误消息,不过到目前为止我们没有对Create页面进行任何字段验证的设置。

      

  • 相关阅读:
    Free DIY Tour_DP
    找出直系亲属_floyd
    Constructing Roads In JGShining's Kingdom_最长上升子序列
    买卖股票_线性dp
    Common Subsequence_公共子序列
    Doing Homework_状态压缩&&位运算
    猴子选大王
    卡片游戏
    Java 2
    Java 1
  • 原文地址:https://www.cnblogs.com/Pinapple/p/6627022.html
Copyright © 2011-2022 走看看