ASP.Net MVC开发基础学习笔记(8):新建数据页面



前言

前面解说了怎样创建一个查询页面并给查询页面加入排序、搜索及分页功能。今天我们来讲讲怎样向这个列表加入数据。

解说的顺序将依照加入数据的步骤的时间顺序来进行,方便大家理清逻辑关系。

本节将涉及前面讲到的非常多知识点,并且还有非常多新知识点。帮助大家温故知新,融会贯通。

创建页面预览例如以下:

新建链接

首先在之前创建好的查询页面上加入一个可以跳转到创建页面的链接。将这个链接加入到标题和搜索栏之间。代码例如以下:

<h2>Students</h2>

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

@using (Html.BeginForm("Index","Student", FormMethod.Get))
{
    <p>
        Find by name:@Html.TextBox("SearchString",ViewBag.CurrentFilter as string)
        <input type="submit" value="Search"/>
  </p>
}

上面代码中黄色部分就是加入的链接,这个ActionLink生成的HTML代码例如以下:

<a href="/Company/Create">Add New Worker</a>

能够看到这个链接訪问的是CompanyController下的Create Action。以下来创建这个Action。

新建页面Action

打开文件~ControllersCompanyController.cs。在这个Controller中加入一个Create Action,例如以下所看到的:

public ViewResult Create()
{
       return View();
}

这么简单?对就是这样。创建数据的页面全部信息都须要用户去填,自然不须要传递数据。也就没有什么操作。

这个Action调用了它相应的View,那么我们就来创建这个View。

新建页面View

在~ViewsCompany目录下创建Create.cshtml视图,写入例如以下代码:

@model SlarkInc.Models.Worker
@{
    ViewBag.Title = "Add New Worker";
}
<h2>Add New Worker</h2>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    <div class="form-horizontal">
        <hr />
        @Html.ValidationSummary(true)
        <div class="form-group">
            @Html.LabelFor(model => model.FirstName, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.FirstName)
                @Html.ValidationMessageFor(model => model.FirstName)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.LastName, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.LastName)
                @Html.ValidationMessageFor(model => model.LastName)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Sex, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EnumDropDownListFor(model => model.Sex)
                @Html.ValidationMessageFor(model => model.Sex)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Rating, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Rating)
                @Html.ValidationMessageFor(model => model.Rating)
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                @Html.Submit("Submit")
            </div>
        </div>
    </div>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

View的第1行代码例如以下所看到的,引入了Models目录里的Worker类。

@model SlarkInc.Models.Worker

为了更好的进行数据操作,Worker类做了修改,修改之后的代码例如以下:

隐藏代码using System.ComponentModel.DataAnnotations;
namespace SlarkInc.Models
{
    public enum Sex
    {
        Male, Female
    }
    public class Worker
    {
        public int ID { get; set; }
        [Display(Name = "Last Name")]
        [DataType(DataType.Text)]
        [Required]
        public string LastName { get; set; }
        [Display(Name = "First Name")]
        [DataType(DataType.Text)]
        [Required]
        public string FirstName { get; set; }
        [Required]
        public Sex Sex { get; set; }
        public double?

Rating { get; set; } } }

代码中第1行引入了DataAnnotations类库,这样我们就能够在Worker类中加入元数据来在View中更好的操作数据。

关于这部分内容能够点这里进一步了解。

看View的第13行代码:

@Html.LabelFor(model => model.FirstName, new { @class = "control-label col-md-2" })

这里的LabelFor函数用来显示这个数据相应的名称。它会去找Worker类的FirstName相应的数据名称,也就是Model里的第15行:

[Display(Name = "First Name")]

然后用Html把它显示出来,例如以下:

<label class="control-label col-md-2" for="FirstName">First Name</label>

View中的第15行:

@Html.EditorFor(model => model.FirstName)

会依据Model中的第16行:

[DataType(DataType.Text)]

来决定用哪种input元素来编辑数据。既然是Text类型的。那就用type="text"的input,例如以下所看到的:

<input class="text-box single-line" data-val="true" data-val-required="First Name 字段是必需的。

" id="FirstName" name="FirstName" type="text" value="" />

那上面的代码中 "data-val-required="First Name 字段是必需的。"" 这一段是哪来的呢?

这是EditorFor函数读取到Model中的第17行:

[Required]

这一行表示这个数据是必填项。假设不填则会显示信息"First Name 字段是必需的。"。

在View中的第29行用到函数Html.EnumDropDownListFor。例如以下所看到的:

@Html.EnumDropDownListFor(model => model.Sex)

这个函数能够把Enum类型的数据在页面上下面拉菜单的形式显示出来供人编辑。

只是这个函数可不是那么easy用,首先Visual Studio的版本号必须是2013或者以上的,项目必须用的是MVC5,然后在菜单中选择工具->库程序包管理器-> 管理解决方式的NuGet程序包。

例如以下所看到的选择联机。在左上角搜索MVC然后安装最新的MVC 5.2.2版。

更新好之后,这个函数就能够正常使用了。它会依据Sex这个Enum变量来生成下拉菜单。这个Enum的定义例如以下:

public enum Sex
{
     Male, Female
}

那么它生成的下拉菜单代码例如以下:

<select data-val="true" data-val-required="Sex 字段是必需的。

" id="Sex" name="Sex"> <option selected="selected" value="0">Male</option> <option value="1">Female</option> </select>

View的第16行代码:

@Html.ValidationMessageFor(model => model.FirstName)

当中ValidationMessageFor函数用来验证数据的有效性。

它依据在Model中这个属性的类型来验证输入的值是否符合要求。

比方Rating这个属性是Double类型的。那么在输入数据时,假设数据不是数字则会有对应提示,而且不能提交。

View的第6、7、46行是例如以下所看到的的不带參数的Form函数结构:

@using (Html.BeginForm()){}

这种结构假设不带不论什么參数,则Form会以Post方法提交给本页面相应的Controller和Action。因此其生成的HTML代码就是例如以下形式:

<form action="/Company/Create" method="post"></form>

在View中使用了Bootstrap的横向表单布局其结构例如以下:

<div class="form-horizontal">
    <div class="form-group">
         <label class="control-label col-md-2" for=""></label>
          <div class="col-md-10">
          </div>
    </div>
    <div class="form-group">
         <label class="control-label col-md-2" for=""></label>
          <div class="col-md-10">
          </div>
    </div>
</div>

显示出来的效果例如以下所看到的:

每一行相应一个属性。左边是属性名,右边是属性相应的编辑框。属性名的col-md-2表示其占Form总宽度的2/12,col-md-10表示其占Form总宽度的10/12。

这用到了Bootstrop的栅格系统。栅格系统具体介绍请点这里

View第8行@Html.AntiForgeryToken()函数的作用是抵御网页跨站请求伪造漏洞(CSRF Cross-site request forgery)。这个漏洞能够盗用登录用户身份发送恶意请求。

比方一个用户登录了网上银行,然后訪问攻击者的站点,站点就会通过登录用户发出请求来获取银行信息。

View第11行使用Html.ValidationSummary(true)。表示仅仅输出Model级的验证错误信息。其具体使用方法会在后面章节中具体介绍。

上面这几段对Create.cshtml文件里具有代表性的技术知识点做了具体说明。其它行不再赘述,有问题请留言。

加入数据Action

从上面代码能够看出,Create.cshtml页面会把数据提交给当前页面相应的Controller和Action,因此我们就在CompanyController下写处理提交的数据的Action。代码例如以下:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "FirstName, LastName, Sex, Rating")] Worker worker)
{
    try
    {
        if (ModelState.IsValid)
        {
            db.Workers.Add(worker);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
    }
    catch (DataException /* dex */)
    {
        ModelState.AddModelError("unableToSave","Unable to save changes.Try again, and if the problem persists see your system administrator.");
    }
    return View(worker);
}

注意。之前我们已经写了一个Create Action用来进入加入页面。这里的Create不是改动前面的Create。而是新建了一个Action。

第1行在这个Action前加[HttpPost]表示仅仅有以Post方法请求Create Action的时候才会调用这个Action。

第2行ValidateAntiForgeryToken依旧是为了防止跨站请求伪造攻击而写的代码。

第3行Action的參数是以worker实例传递的。

也就是说Create.cshtml提交的4个值被赋值给work然后把worker传递给Create作为參数。而这个參数前面的[Bind(Include = "FirstName, LastName, Sex, Rating")]是为了防止过多提交(overposting)攻击的。从Create.cshtml的代码能够知道,这个页面仅仅会提交4个值。而黑客能够有办法通过这个页面提交很多其它的值给当前Action。而这些多出来的值也会存在worker实例中被加入到数据库,这无疑是危急的。因此[Bind(Include = "")]就限定了无论你提交多少值。我这个Action里仅仅接受"FirstName, LastName, Sex, Rating"这4个值。保证了页面的安全性。

第7行ModelState.IsValid表示提交的数据是否有效。比方对于一个类型为数字的属性必须提交一个数字才算是有效。

假设提交的数据有效则保存数据而且将页面跳转回Index.cshtml。

第16行ModelState.AddModelError()函数能够给Model加入一条错误信息,函数的第一个參数是key。用于查找这个错误信息,第二个參数是错误信息的详细内容。

这个错误信息能够在View中通过Html.ValidationMessage("unableToSave")来訪问到。

查看结果

点击下图的"Add New Worker"链接。

放空必填项或者输入不合法数据出现提示信息例如以下:

填入正确信息例如以下:

点击Submitbutton,成功加入数据后的结果例如以下:

结尾

最终又完毕了一篇,再接再厉!

原文地址:https://www.cnblogs.com/yfceshi/p/7225788.html