http://www.cnblogs.com/powertoolsteam/p/MVC_three.html

第三天我们将学习Asp.Net中数据处理功能,了解数据访问层,EF,以及EF中常用的代码实现方式,创建数据访问层和数据入口,处理Post数据,以及数据验证等功能。

系列文章

七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC

七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递

七天学会ASP.NET MVC (三)——ASP.Net MVC 数据处理

七天学会ASP.NET MVC (四)——用户授权认证问题

七天学会ASP.NET MVC (五)——Layout页面使用和用户角色管理

七天学会ASP.NET MVC (六)——线程问题、异常处理、自定义URL

七天学会ASP.NET MVC(七)——创建单页应用

目录:

数据访问层

实体框架(EF)简述

什么是代码优先的方法?

实验8——在项目中添加数据访问层

关于实验8

实验9——创建数据输入屏幕

实验10——获取服务端或控制器端传递的数据。

实验11——重置及取消按钮

实验12——保存数据。库记录并更新表格

实验13——添加服务器端验证

实验14——自定义服务器端验证

结论

数据访问层

在实际开发中,如果一个项目不包含任何数据库,那么这个项目是不完整的,我们在一二节实例中未涉及数据库,在本节开始,实验8中讲解一个关于数据库和数据库层的实例。

本节将使用SQL Server和EF(Entity Framework)创建相关的数据库及数据库访问层。

简述实体框架(EF)

EF是一种ORM工具,ORM表示对象关联映射。

在RDMS中,对象称为表格和列对象,而在.net中(面向对象)称为类,对象以及属性。

任何数据驱动的应用实现的方式有两种:

1. 通过代码与数据库关联(称为数据访问层或数据逻辑层)

2. 通过编写代码将数据库数据映射到面向对象数据,或反向操作。

ORM是一种能够自动完成这两种方式的工具。EF是微软的ORM工具。

什么是代码优先的方法?

EF提供了三种方式来实现项目:

l 数据库优先方法——创建数据库,包含表,列以及表之间的关系等,EF会根据数据库生成相应的Model类(业务实体)及数据访问层代码。

l 模型优先方法——模型优先指模型类及模型之间的关系是由Model设计人员在VS中手动生成和设计的,EF将模型生成数据访问层和数据库。

l 代码优先方法——代码优先指手动创建POCO类。这些类之间的关系使用代码定义。当应用程序首次执行时,EF将在数据库服务器中自动生成数据访问层以及相应的数据库。

什么是POCO类?

POCO即Plain Old CLR对象,POCO类就是已经创建的简单.Net类。在上两节的实例中,Employee类就是一个简单的POCO类。

实验8——添加数据访问层

1. 创建数据库

连接SQL SERVER ,创建数据库 “SalesERPDB”。

2. 创建连接字符串(ConnectionString

打开Web.Config 文件,在< Configuration >标签内添加以下代码:

   1:  <connectionStrings>
   2:  <add connectionString="Data Source=(local);Initial Catalog=SalesERPDB;Integrated Security=True"
   3:          name="SalesERPDAL"       
   4:          providerName="System.Data.SqlClient"/>
   5:  </connectionStrings>

3. 添加EF引用

右击项目->管理Nuget 包。选择Entity Framework 并点击安装。

4. 创建数据访问层

  • 在根目录下,新建文件夹”Data Access Layer“,并在Data Access Layer文件夹中新建类” SalesERPDAL “
  • 在类文件顶部添加 Using System.Data.Entity代码。
  • 继承DbContext类
   1:  public class SalesERPDAL: DbContext
   2:  {
   3:  }

5. 创建Employee类的主键

打开Employee类,输入using语句

   1:  using System.ComponentModel.DataAnnotations;

添加Employee的属性,并使用Key 关键字标识主键。

1
2
3
4
5
6
7
8
public class Employee
{
    [Key]
    public int EmployeeId  { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Salary { get; set; }
}

6. 定义映射关系

在SalesERPDAL类文件输入using语句。

   1:  using WebApplication1.Models;

在 SalesERPDAL 类中重写 OnModelCreating方法,代码如下:

   1:  protected override void OnModelCreating(DbModelBuilder modelBuilder)
   2:  {
   3:      modelBuilder.Entity<employee>().ToTable("TblEmployee");
   4:      base.OnModelCreating(modelBuilder);
   5:  }
   6:  </employee>

注意:上述代码中提到“TblEmployee”是表名称,是运行时自动生成的。

7. 在数据库中添加新属性Employee

在 SalesERPDAL 类中添加新属性 Employee。

   1:  public DbSet<employee> Employees{get;set;}
   2:  </employee>
 

DbSet表示数据库中能够被查询的所有Employee

8. 改变业务层代码,并从数据库中获取数据

打开 EmployeeBusinessLayer 类,输入Using 语句。

   1:  using WebApplication1.DataAccessLayer;

修改GetEmployees 方法:

   1:  public List<employee> GetEmployees()
   2:  {
   3:      SalesERPDAL salesDal = new SalesERPDAL();
   4:      return salesDal.Employees.ToList();
   5:  }
   6:  </employee>

9. 运行并测试

右击,查看并没有任何Employee的表格,查看数据库文件,我们会看到 TblEmployee 表

10. 插入测试数据

在TblEmployee 中插入一些测试数据

11. 运行程序

关于实验8

什么是数据集?

DbSet数据集是数据库方面的概念 ,指数据库中可以查询的实体的集合。当执行Linq 查询时,Dbset对象能够将查询内部转换,并触发数据库。

在本实例中,数据集是Employees,是所有Employee的实体的集合。当每次需要访问Employees时,会获取“TblEmployee”的所有记录,并转换为Employee对象,返回Employee对象集。

如何连接数据访问层和数据库?

数据访问层和数据库之间的映射通过名称实现的,在实验8中,ConnectionString(连接字符串)的名称和数据访问层的类名称是相同的,都是SalesERPDAL,因此会自动实现映射。

连接字符串的名称可以改变吗?

可以改变,在实验8中,在数据访问层中定义了构造函数,如下:

   1:  public SalesERPDAL():base("NewName")
   2:  {
   3:  }

实验8已经完成,相信大家已经了解基本的原理和操作,接下来我们将做一些改变,使得每件事情都变得有组织有意义:

1. 重命名

  • 将“TestController”改成 “EmployeeController”
  • GetView的行为方法改为Index
  • Views文件夹目录下的Test 文件夹改成Employee
  • MyView的View 改为“Index”

2. 删除EmployeeListViewModel 的 UserName  属性

3. 删除View中的 UserName

打开 Views/Employee.Index.cshtml View ,删除 UserName ,即删除以下代码:

   1:  Hello @Model.UserName
   2:  <hr />

4. 修改 EmployeeController 中的 Index方法

根据以下代码修改Index 方法,执行时URL会变成  “…./Employee/Index”

public ActionResult Index()
{
&hellip;&hellip;
&hellip;&hellip;
&hellip;&hellip;
employeeListViewModel.Employees = empViewModels;
//employeeListViewModel.UserName = "Admin";-->Remove this line -->Change1
return View("Index", employeeListViewModel);//-->Change View Name -->Change 2
}

实验 9——创建数据入口(Data Entry Screen)

1. 新建 action  方法

在 EmployeeController 中新建 “AddNew”action 方法:

   1:  public ActionResult AddNew()
   2:  {
   3:      return View("CreateEmployee");
   4:  }
 

2. 创建 View

在View/Employee目录下 新建 View 命名为:CreateEmployee。

   1:  @{
   2:      Layout = null;
   3:  }
   4:  <!DOCTYPE html>
   5:  <html>
   6:      <head>
   7:        <meta name="viewport" content="width=device-width" />
   8:        <title>CreateEmployee</title>
   9:      </head>
  10:      <body>
  11:        <div>
  12:           <form action="/Employee/SaveEmployee" method="post">
  13:              First Name: <input type="text" id="TxtFName" name="FirstName" value="" /><br />
  14:              Last Name: <input type="text" id="TxtLName" name="LastName" value="" /><br />
  15:              Salary: <input type="text" id="TxtSalary" name="Salary" value="" /><br />
  16:              <input type="submit" name="BtnSave" value="Save Employee" />
  17:              <input type="button" name="BtnReset" value="Reset" />
  18:           </form>
  19:        </div>
  20:      </body>
  21:  </html>

3. 创建Index View的链接

打开 Index.cshtml 文件,添加指向 AddNew action方法的链接

   1:  <ahref="/Employee/AddNew">Add New</a>

4. 运行

关于实验9

使用Form 标签的作用是什么?

在系列文章第一讲中,我们已经知道,Web编程模式不是事件驱动的编程模式,是请求响应模式。最终用户会产生发送请求。Form标签是HTML中产生请求的一种方式,Form标签内部的提交按钮只要一被点击,请求会被发送到相关的action 属性。

Form标签中方法属性是什么?

方法属性决定了请求类型。有四种请求类型:get,post,put以及delete.

  • Get: 当需要获取数据时使用。
  • Post: 当需要新建一些事物时使用。
  • Put: 当需要更新数据时使用。
  • Delete:需要删除数据时使用。

使用Form 标签来生成请求,与通过浏览器地址栏或超链接来生成请求,有什么区别?

使用Form标签生成请求时,所有有关输入的控件值会随着请求一起发送。

输入的值是怎样发送到服务器端的?

当请求类型是Get,Put或Delete时,值会通过查询语句发送,当请求是Post类型,值会通过Post数据传送。

使用输入控件名的作用是什么?

所有输入控件的值将随着请求一起发送。同一时间可能会接收到多个值,为了区分发送到所有值为每个值附加一个Key,这个Key在这里就是名称属性。

名称和 Id的作用是否相同?

不相同,名称属性是HTML内部使用的,当请求被发送时,然而 ID属性是在JavaScript中开发人员为了实现一些动态功能而调用的。

“input type=submit” 和 “input type=button”的区别是什么?

提交按钮在给服务器发送请求而专门使用的,而简单的按钮是执行一些自定义的客户端行为而使用的。按钮不会自己做任何事情。

实验10——在服务器端(或Controller)获取Post数据

1. 创建 SaveEmployee  action 方法

在 Employee控制器中创建 名为 ”SaveEmployee“ action 方法:

   1:  public string SaveEmployee(Employee e)
   2:  {
   3:     return e.FirstName + "|"+ e.LastName+"|"+e.Salary;
   4:  }

2. 运行

关于实验10

action 方法内部的Textbox 值是如何更新 Employee 对象的?

在 Asp.Net MVC中有个 Model Binder的概念:

  • 无论请求是否由带参的action方法生成,Model Binder都会自动执行。
  • Model Binder会通过方法的元参数迭代,然后会和接收到参数名称做对比。如果匹配,则响应接收的数据,并分配给参数。
  • 在Model Binder迭代完成之后,将类参数的每个属性名称与接收的数据做对比,如果匹配,则响应接收的数据,并分配给参数。

如果两个参数是相关联的会发生什么状况,如参数”Employee e“和 “string FirstName”?

FirstName会被元 First Name变量和 e.FirstName 属性更新。

Model Binder是组合的关系吗?

是,在实验 9 中都是根据控件名称执行的。

例如:

Customer 类和 Address 类:

   1:  public class Customer
   2:  {
   3:      public string FName{get;set;}
   4:      public Address address{get;set;}
   5:  }
   6:  public class Address
   7:  {
   8:      public string CityName{get;set;}
   9:      public string StateName{get;set;}
  10:  }

Html 代码

   1:  ...
   2:  ...
   3:  ...
   4:  <input type="text" name="FName">
   5:  <input type="text" name="address.CityName">
   6:  <input type="text" name="address.StateName">
   7:  ...
   8:  ...
   9:  ...

实验11——重置按钮和取消按钮

1. 添加重置和取消按钮

   1:  ...
   2:   
   3:  ...
   4:   
   5:  ...
   6:   
   7:  <input type="submit" name="BtnSubmit” value="Save Employee" />
   8:   
   9:  <input type="button" name="BtnReset" value="Reset" onclick="ResetForm();" />
  10:   
  11:  <input type="submit" name="BtnSubmit" value="Cancel" />

2. 定义 ResetForm 函数

在Html的头部分添加脚本标签,并编写JavaScript 函数 命名为”ResetForm“如下:

   1:  <script>
   2:      function ResetForm() {
   3:          document.getElementById('TxtFName').value = "";
   4:          document.getElementById('TxtLName').value = "";
   5:          document.getElementById('TxtSalary').value = "";
   6:      }
   7:  </script>

3. 在 EmplyeeController SaveEmployee 方法中实现取消按钮的点击功能

修改SaveEmployee  方法:

   1:  public ActionResult SaveEmployee(Employee e, string BtnSubmit)
   2:  {
   3:      switch (BtnSubmit)
   4:      {
   5:          case "Save Employee":
   6:              return Content(e.FirstName + "|" + e.LastName + "|" + e.Salary);
   7:          case "Cancel":
   8:              return RedirectToAction("Index");
   9:      }
  10:      return new EmptyResult();
  11:  }

4.  运行

5. 测试重置功能

6. 测试保存和取消功能

关于实验11

在实验11中为什么将保存和取消按钮设置为同名?

在日常使用中,点击提交按钮之后,请求会被发送到服务器端,所有输入控件的值都将被发送。提交按钮也是输入按钮的一种。因此提交按钮的值也会被发送。

当保存按钮被点击时,保存按钮的值也会随着请求被发送到服务器端,当点击取消按钮时,取消按钮的值”取消“会随着请求发送。

在Action 方法中,Model Binder 将维护这些工作。会根据接收到的值更新参数值。

实现多重提交按钮有没有其他可用的方法?

事实上,有很多可实现的方法。以下会介绍三种方法。

1. 隐藏 Form 元素

  • 在View中创建一个隐藏form元素
   1:  <form action="/Employee/CancelSave" id="CancelForm" method="get" style="display:none">
   2:   
   3:  </form>
  • 将提交按钮改为正常按钮,并且使用JavaScript脚本代码:
   1:  <input type="button" name="BtnSubmit" value="Cancel" onclick="document.getElementById('CancelForm').submit()" />
 
2. 使用JavaScript 动态的修改URL
 
   1:  <form action="" method="post" id="EmployeeForm" >
   2:  ...
   3:  ...
   4:  <input type="submit" name="BtnSubmit" value="Save Employee" onclick="document.getElementById('EmployeeForm').action = '/Employee/SaveEmployee'" />
   5:  ...
   6:  <input type="submit" name="BtnSubmit" value="Cancel" onclick="document.getElementById('EmployeeForm').action = '/Employee/CancelSave'" />
   7:  </form>

3. Ajax

使用常规输入按钮来代替提交按钮,并且点击时使用jQuery或任何其他库来产生纯Ajax请求。

为什么在实现重置功能时,不使用 input type=reset ?

因为输入类型type=reset 不是清晰的值,仅设置了控件的默认值。如:

   1:  <input type="text" name="FName" value="Sukesh">

在该实例中控件值为:Sukesh,如果使用type=reset来实现重置功能,当重置按钮被点击时,textbox的值会被设置为”Sukesh“。

如果控件名称与类属性名称不匹配会发生什么情况?

首先来看一段HTML代码:

   1:  First Name: <input type="text" id="TxtFName" name="FName" value="" /><br />
   2:  Last Name: <input type="text" id="TxtLName" name="LName" value="" /><br />
   3:  Salary: <input type="text" id="TxtSalary" name="Salary" value="" /><br />

Model 类包含属性名称如FirstName, LastName 和 Salary。由于默认的Model Binder在该片段内不会发生作用。

我们会给出三种解决方案

  • 内部action 方法,获取请求中的post数据。Form 语法和手动构建Model对象:
   1:  public ActionResult SaveEmployee()
   2:  {
   3:          Employee e = new Employee();
   4:          e.FirstName = Request.Form["FName"];
   5:          e.LastName = Request.Form["LName"];
   6:          e.Salary = int.Parse(Request.Form["Salary"])
   7:  ...
   8:  ...
   9:  }
  • 使用参数名称和手动创建Model对象:
   1:  public ActionResult SaveEmployee(string FName, string LName, int Salary)
   2:  {
   3:      Employee e = new Employee();
   4:      e.FirstName = FName;
   5:      e.LastName = LName;
   6:      e.Salary = Salary;
   7:  ...
   8:  ...
   9:  }
  • 创建自定义 Model Binder ,代替默认的Model Binder:

1. 创建自定义Model Binder

   1:  public class MyEmployeeModelBinder : DefaultModelBinder
   2:  {
   3:      protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
   4:      {
   5:          Employee e = new Employee();
   6:          e.FirstName = controllerContext.RequestContext.HttpContext.Request.Form["FName"];
   7:          e.LastName = controllerContext.RequestContext.HttpContext.Request.Form["LName"];
   8:          e.Salary = int.Parse(controllerContext.RequestContext.HttpContext.Request.Form["Salary"]);
   9:          return e;
  10:      }
  11:  }

2. 替换默认的 Model Binder

   1:  public ActionResult SaveEmployee([ModelBinder(typeof(MyEmployeeModelBinder))]Employee e, string BtnSubmit)
   2:  {
   3:      ......
 

RedirectToAction 函数的功能?

RedirectToAction 生成 RedirectToRouteResult 如ViewResult 和 ContentResult,RedirectToRouteResult是 ActionResult的孩子节点,表示间接响应,当浏览器接收到RedirectToRouteResult,新Action 方法产生新的请求。

EmptyResult是什么?

是ActionResult的一个孩子节点,当浏览器接收到 EmptyResult,作为响应,它会显示空白屏幕,表示无结果。在本实验中不会发生EmptyResult。

实验12——保存数据库记录,更新表格

1. 在EmployeeBusinessLayer  中创建 SaveEmployee,如下:

   1:  public Employee SaveEmployee(Employee e)
   2:  {
   3:      SalesERPDAL salesDal = new SalesERPDAL();
   4:      salesDal.Employees.Add(e);
   5:      salesDal.SaveChanges();
   6:      return e;
   7:  }

2. 修改 SaveEmployee 的Action 方法

在 EmployeeController 中修改 SaveEmployee ation方法 代码如下:

   1:  public ActionResult SaveEmployee(Employee e, string BtnSubmit)
   2:  {
   3:      switch (BtnSubmit)
   4:      {
   5:          case "Save Employee":
   6:              EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
   7:              empBal.SaveEmployee(e);
   8:              return RedirectToAction("Index");
   9:          case "Cancel":
  10:              return RedirectToAction("Index");
  11:      }
  12:      return new EmptyResult();
  13:  }

3.运行

实验 13——添加服务器端验证

在实验10中已经了解了Model Binder的基本功能,再来了解一下:

  • Model Binder使用 post数据更新 Employee对象
  • 但是这不仅仅执行Model Binder的。Model Binder需要更新Model State。Model State封装了 Model状态。
  • ModelState包含属性IsValid ,该属性表示 Model 是否成功更新。如果任何服务器端验证失败,Model将不更新。

ModelState保存验证错误的详情。

如:ModelState[“FirstName”],表示将包含所有与First Name相关的错误。

保存接收的值(Post 数据或查询字符串的值)

在Asp.net MVC,将使用 DataAnnotations来执行服务器端的验证。

在我们了解Data Annotation之前先来了解一些Model Binder知识:

使用元数据类型时,Model Binder 是如何工作的?

当Action方法包含元类型参数,Model Binder会与参数名称对比。

  • 当匹配成功时,响应接收的数据会被分配给参数。
  • 匹配不成功时,参数会设置为缺省值,例如,如果是字符串类型则被设置为null,如果是整型则设置为0.
  • 由于数据类型未匹配异常的抛出,不会进行值分配。

当参数是类时,Model Binder 是如何工作的?

当参数为类,Model Binder将通过检索类所有的属性,将接收的数据与类属性名称比较。

当匹配成功时:

如果接收的值是空,则会将空值分配给属性,如果无法执行空值分配,会设置缺省值,ModelState.IsValid将设置为fasle。

如果空值分配成功,会考虑值是否合法,ModelState.IsValid将设置为fasle。

如果匹配不成功,参数会被设置为缺省值。在本实验中ModelState.IsValid不会受影响。

1. 使用 DataAnnotations 装饰属性

   1:  public class Employee
   2:  {
   3:  ...
   4:  ...
   5:      [Required(ErrorMessage="Enter First Name")]
   6:      public string FirstName { get; set; }
   7:   
   8:      [StringLength(5,ErrorMessage="Last Name length should not be greater than 5")]
   9:      public string LastName { get; set; }
  10:  ...
  11:  ...
  12:  }

2.  修改  SaveEmployee 方法

   1:  public ActionResult SaveEmployee(Employee e, string BtnSubmit)
   2:  {
   3:      switch (BtnSubmit)
   4:      {
   5:          case "Save Employee":
   6:              if (ModelState.IsValid)
   7:              {
   8:                  EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
   9:                  empBal.SaveEmployee(e);
  10:                  return RedirectToAction("Index");
  11:              }
  12:              else
  13:              {
  14:                  return View("CreateEmployee ");
  15:              }
  16:          case "Cancel":
  17:              return RedirectToAction("Index");
  18:      }
  19:      return new EmptyResult();
  20:  }

3. 在View中显示错误,修改 Views/Index/CreateEmployee.cshtml 代码,使用Table标签如下:

   1:  <table>
   2:     <tr>
   3:        <td>
   4:           First Name:
   5:        </td>
   6:        <td>
   7:           <input type="text" id="TxtFName" name="FirstName" value="" />
   8:        </td>
   9:     </tr>
  10:     <tr>
  11:        <td colspan="2" align="right">
  12:          @Html.ValidationMessage("FirstName")
  13:        </td>
  14:     </tr>
  15:     <tr>
  16:        <td>
  17:          Last Name:
  18:        </td>
  19:        <td>
  20:           <input type="text" id="TxtLName" name="LastName" value="" />
  21:        </td>
  22:     </tr>
  23:     <tr>
  24:        <td colspan="2" align="right">
  25:           @Html.ValidationMessage("LastName")
  26:        </td>
  27:     </tr>
  28:   
  29:     <tr>
  30:        <td>
  31:          Salary:
  32:        </td>
  33:        <td>
  34:           <input type="text" id="TxtSalary" name="Salary" value="" />
  35:        </td>
  36:     </tr>
  37:     <tr>
  38:        <td colspan="2" align="right">
  39:          @Html.ValidationMessage("Salary")
  40:        </td>
  41:     </tr>
  42:   
  43:     <tr>
  44:        <td colspan="2">
  45:           <input type="submit" name="BtnSubmit" value="Save Employee" />
  46:           <input type="submit" name="BtnSubmit" value="Cancel" />
  47:           <input type="button" name="BtnReset" value="Reset" onclick="ResetForm();" />
  48:        </td>
  49:     </tr>
  50:  </table>

4. 运行测试

导航到“Employee/AddNew” 方法,执行测试。

测试1。

测试2

注意:可能会出现以下错误:

“The model backing the 'SalesERPDAL' context has changed since the database was created. Consider using Code First Migrations to update the database.”

为了解决上述错误,在Global.asax文件中在 Application_Start后添加以下语句:

   1:  Database.SetInitializer(new DropCreateDatabaseIfModelChanges<SalesERPDAL>());

注意: 使用Database类需要引用 “System.Data.Entity”命名空间

关于实验13

@Html.ValidationMessage是什么意思?

  • @符号表示是Razor代码
  • Html是HtmlHelper类的实例。
  • ValidationMessage是HtmlHelper类的函数,用来表示错误信息。

ValidationMessage 函数是如何工作的?

ValidationMessage 是运行时执行的函数。如之前讨论的,ModelBinder更新ModelState。ValidationMessage根据关键字显示ModelState表示的错误信息。

如果我们需要可空的整数域,该怎么做?

   1:  public int? Salary{get;set;}

UpdateModel 和 TryUpdateModel 方法之间的区别是什么?

TryUpdateModel 与UpdateModel 几乎是相同的,有点略微差别。

如果Model调整失败,UpdateModel会抛出异常。就不会使用UpdateModel的 ModelState.IsValid属性。

TryUpdateModel是将函数参数与Employee对象保持相同,如果更新失败,ModelState.IsValid会设置为False值。

客户端验证是什么?

客户端验证是手动执行的,除非使用HTML 帮助类。我们将在下一节介绍HTML 帮助类。

实验14——自定义服务器端验证

1. 创建自定义验证

新建类,并命名为FirstNameValidation,代码如下:

   1:  public class FirstNameValidation:ValidationAttribute
   2:  {
   3:      protected override ValidationResult IsValid(object value, ValidationContext validationContext)
   4:      {
   5:          if (value == null) // Checking for Empty Value
   6:          {
   7:              return new ValidationResult("Please Provide First Name");
   8:          }
   9:          else
  10:          {
  11:              if (value.ToString().Contains("@"))
  12:              {
  13:                  return new ValidationResult("First Name should contain @");
  14:              }
  15:          }
  16:          return ValidationResult.Success;
  17:      }
  18:  }

2. 附加到First Name

打开Employee类,删除FirstName的默认的Required属性,添加FirstNameValidation,代码如下:

   1:  [FirstNameValidation]
   2:  public string FirstName { get; set; }

3. 运行

导航到Employee/AddNew

测试1:

测试2:

结论

本节主要讲解了数据访问层相关的知识,如数据验证,数据更新,数据处理,form表单的使用等。

在下一章,我们主要讲述以下内容:

  • 实现客户端验证
  • 理解HTML 帮助类
  • 实现认证功能
  • 给部分View添加页脚
  • 使用母版页创建统一的布局
  • 自定义请求过滤器

ComponentOne Studio ASP.NET MVC 帮助您更好更高效地完成应用开发,满足用户的所有需求。

它与Visual Studio无缝集成,完全与MVC6和ASP.NET 5.0兼容,将大幅提高效率,能提供从桌面到移动设备的体验,不用任何妥协就能创建触控优先的现代化解决方案。

原文链接:http://www.codeproject.com/Articles/986730/Learn-MVC-Project-in-days-Day

七天学会ASP.NET MVC (三)——ASP.Net MVC 数据处理 【转】的更多相关文章

  1. 七天学会ASP.NET MVC (三)——ASP.Net MVC 数据处理

    第三天我们将学习Asp.Net中数据处理功能,了解数据访问层,EF,以及EF中常用的代码实现方式,创建数据访问层和数据入口,处理Post数据,以及数据验证等功能. 系列文章 七天学会ASP.NET M ...

  2. Asp.Net MVC<三> : ASP.NET MVC 基本原理及项目创建

    MVC之前的那点事儿系列 解读ASP.NET 5 & MVC6系列 MVC模拟(摘自ASP.NET MVC5框架揭秘) Asp.net中,通过HttpModule的形式定义拦截器,也就是路由表 ...

  3. 七天学会ASP.NET MVC(七)——创建单页应用

    系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...

  4. 七天学会ASP.NET MVC (六)——线程问题、异常处理、自定义URL

    本节又带了一些常用的,却很难理解的问题,本节从文件上传功能的实现引出了线程使用,介绍了线程饥饿的解决方法,异常处理方法,了解RouteTable自定义路径 . 系列文章 七天学会ASP.NET MVC ...

  5. 七天学会ASP.NET MVC (五)——Layout页面使用和用户角色管理

    系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...

  6. 七天学会ASP.NET MVC (四)——用户授权认证问题

    小编应各位的要求,快马加鞭,马不停蹄的终于:七天学会 Asp.Net MVC 第四篇出炉,在第四天的学习中,我们主要了学习如何在MVC中如何实现认证授权等问题,本节主要讲了验证错误时的错误值,客户端验 ...

  7. 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递

    通过第一天的学习之后,我们相信您已经对MVC有一些基本了解. 本节所讲的内容是在上节的基础之上,因此需要确保您是否掌握了上一节的内容.本章的目标是在今天学习结束时利用最佳实践解决方案创建一个小型的MV ...

  8. 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC

    系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...

  9. 七天学会ASP.NET MVC ——深入理解ASP.NET MVC

    七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC   系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二) ...

随机推荐

  1. Python-S9-Day89_stark总结

    01 Stark总结 02 ORM总结 03 上节作业 04 Stark组件之查看页面表头 05 list_display_links 06 stark组件之添加页面 07 编辑删除页面 01 Sta ...

  2. Python-S9-Day88——stark组件之设计urls

    03 stark组件之设计urls 04 stark组件之设计urls2 05 stark组件之设计list_display 06 stark组件之z查看页面的数据展示 03 stark组件之设计ur ...

  3. Leetcode 558.四叉树交集

    四叉树交集 四叉树是一种树数据,其中每个结点恰好有四个子结点:topLeft.topRight.bottomLeft 和 bottomRight.四叉树通常被用来划分一个二维空间,递归地将其细分为四个 ...

  4. vue tradingView(二)

    tradingView 一些配置问题 tradingView 一些配置问题 javascript Demo_Hu 4月17日提问 · 4月17日更新 9 关注 1 收藏,993 浏览 问题对人有帮助, ...

  5. sqlserver执行时间和自行效率

    SET STATISTICS PROFILE ON --SET STATISTICS IO ON --SET STATISTICS TIME ON declare @dtm datetime SQL语 ...

  6. UVALive 5987

    求第n个数,该数满足至少由3个不同的素数的乘机组成 #include #include #include #include #include using namespace std; int prim ...

  7. ansible Failed to connect to the host via ssh: no such identity: /root/.ssh/id_rsa.bak

    中控机和远端主机配置完密钥后,在中控台上通过ansible检测联通性 ansible -i inventory.cfg all -m ping 10.1.1.1 | UNREACHABLE! => ...

  8. spring boot redis代码与配置

    import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Co ...

  9. call、apply与bind在理解

    call() 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法. fun.call(thisArg[, arg1[, arg2[, ...]]]) apply() 方法 ...

  10. [TC_SRM_460]TheCitiesAndRoadsDivOne

    [TC_SRM_460]TheCitiesAndRoadsDivOne 试题描述 John and Brus have become very famous people all over the w ...