学习MVC项目在7天-第三天

介绍 我们假定你在来这里前几天已经读过了。在第2天,我们完成了一个项目,这个项目有一个员工列表的网格。 在第三天,我们将把它带到下一个层次,通过介绍数据访问层和数据输入屏幕。 完整的系列 第1天第2天第3天第4天第5天第6天7天奖金第1天奖金第2天 我们很高兴地宣布,这篇文章现在可以从www.amazon.com和www.flipkart.com获得同样的纸质书 议程 数据访问层 简单地说,实体框架是什么? 什么是代码优先方法? 实验8 -在项目中增加数据访问层 关于实验八的演讲 组织的一切 实验9 -创建数据输入屏幕 关于实验九的演讲 实验室10 -在服务器端/控制器中获取发布的数据 关于第十实验室的演讲 实验11 -重置和取消按钮 关于实验室11的演讲 实验12 -在数据库中保存记录并更新网格 实验13 -增加服务器端验证 模型绑定器如何与原始数据类型一起工作 模型绑定器如何与类一起工作 在第13实验室演讲 实验14 -自定义服务器端验证 结论 数据访问层 没有数据库的实时项目是不完整的。在我们的项目中,我们还没有谈到数据库层。第三天的第一个实验将是关于数据库和数据库层。 这里我们将分别使用Sql Server和Entity Framework来创建数据库和数据库访问层。 简单地说,实体框架是什么? 这是一个ORM工具。ORM代表对象关系映射。 在RDBMS中,我们用表和列来表示,而在。net中(一个面向对象的世界),我们用类、对象和属性来表示。 当我们考虑任何数据驱动的应用程序时,我们会得到以下两件事。 编写用于与数据库通信的代码(称为数据访问层或数据库逻辑)编写用于映射数据库数据到面向对象数据的代码,反之亦然。 ORM工具可以自动完成这两件事。实体框架是微软ORM工具。 什么是代码优先方法? 在实体框架中,我们可以采用这三种方法中的一种 数据库优先方法——创建包含表、列、关系等的数据库,实体框架将生成相应的模型类(业务实体)和数据访问层代码。模型优先方法——在这种方法中,模型类和它们之间的关系将使用Visual studio中的模型设计器手工定义,实体框架将自动生成数据访问层和具有表、列、关系的数据库。代码优先方法——在这种方法中,将手动创建POCO类。这些类之间的关系将通过代码来定义。当应用程序第一次执行时,实体框架将在数据库服务器中自动生成数据访问层和数据库以及表、列和关系。 什么是POCO类? POCO代表“普通的旧CLR对象”。POCO类意味着我们创建的简单的。net类。在前面的示例中,Employee类只是一个POCO类。 实验8 -在项目中增加数据访问层 步骤1 -创建数据库 连接到Sql服务器并创建名为“SalesERPDB”的新数据库。 步骤2 -创建ConnectionString 开放网络。配置文件和内部配置部分添加以下部分 隐藏,复制Code

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

步骤3 -添加实体框架引用 右键点击项目>>Nuget包管理。搜索实体框架并单击install。 步骤4 -创建数据访问层。 在根文件夹中创建一个名为“DataAccessLayer”的新文件夹,并在其中创建一个名为“SalesERPDAL”的新类,在顶部放置using语句,如下所示。 隐藏,使用System.Data.Entity复制代码; 从DbContext继承“SalesERPDAL” 隐藏,复制Code

public class SalesERPDAL: DbContext
{
}

步骤5 -为employee类创建主键字段 打开Employee类并在下面的topas处放置using语句。 隐藏,复制Code

using System.ComponentModel.DataAnnotations;

在Employee类中添加EmployeeId属性并将其标记为键属性。 隐藏,复制Code

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 -定义映射 将下面的using语句放在“SalesERPDAL”类的顶部 隐藏,复制Code

using WebApplication1.Models;

重写SalesERPDAL类中的onmodelcreate方法,如下所示。 隐藏,复制Code

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<employee>().ToTable("TblEmployee");
    base.OnModelCreating(modelBuilder);
}
</employee>

注意:在上面的代码片段中,“TblEmployee”表示表名。它会在运行时自动创建。 步骤7 -创建属性以在数据库中保存雇员 在“SalesERPDAL”类中创建一个名为Employee的新属性,如下所示 隐藏,复制Code

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

DbSet将表示可以从数据库查询的所有员工。 步骤8 -更改业务层代码并从数据库中获取数据 打开EmployeeBusinessLayer类。将using语句放在顶部。 隐藏,复制Code

using WebApplication1.DataAccessLayer;

现在更改GetEmployees方法类如下。 隐藏,复制Code

public List<employee> GetEmployees()
{
    SalesERPDAL salesDal = new SalesERPDAL();
    return salesDal.Employees.ToList();
}
</employee>

步骤9 -执行和测试 按F5并执行应用程序。 现在我们d数据库中没有任何雇员,因此我们将看到一个空白的网格。 检查数据库。现在我们有一个名为TblEmployee的表,包含所有列。 步骤9 -插入测试数据 向TblEmployee表添加一些虚拟数据。 步骤10 -执行并测试应用程序 按F5再次运行应用程序。 开始吧:) 关于实验八的演讲 DbSet是什么? DbSet只是表示可以从数据库查询的所有实体的集合。当我们编写一个Linq查询DbSet对象时,它在内部转换为查询并针对数据库触发。 在我们的例子中,“Employees”是一个DbSet,它包含所有可以从数据库查询的“Employee”实体。每次我们尝试访问“Employees”时,它都会获取“TblEmployee”表中的所有记录,并将其转换为“Employee”对象并返回集合。 连接字符串和数据访问层是如何连接的? 映射将根据名称进行。在我们的示例中,ConnectionString名称和数据访问层类名称与“SalesERPDAL”相同,因此会自动映射。 我们可以改变ConnectionString的名字吗? 是的,在这种情况下,我们必须在数据访问层类中定义一个构造函数,如下所示。 隐藏,复制Code

public SalesERPDAL():base("NewName")
{
}

组织的一切 为了让每件事都有条理和意义,让我们做一些改变。 第一步-重命名 getview操作方法将测试文件夹(在Views文件夹内)索引为employee,将“MyView”视图索引为“Index” 步骤2 -从EmployeeListViewModel中删除用户名属性 步骤3 -从视图中删除用户名 视图/ Employee.Index开放。cshtml视图并从其中删除用户名。 简单地说,删除下面的代码块。 隐藏,复制Code

 Hello @Model.UserName
<hr />

步骤2 -改变员工控制员的索引操作方法 因此,将EmployeeController中的索引操作中的代码更改如下。 隐藏,复制Code

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

现在执行时URL将会“…/Employee/Index” 实验9 -创建数据输入屏幕 步骤1 -创建行动方法 在EmployeeController中创建一个名为“AddNew”的操作方法,如下所示 隐藏,复制Code

public ActionResult AddNew()
{
    return View("CreateEmployee");
}

步骤2 -创建视图 在view /Employee文件夹中创建一个名为“CreateEmployee”的视图,如下所示。 隐藏,复制Code

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
    <head>
      <meta name="viewport" content="width=device-width" />
      <title>CreateEmployee</title>
    </head>
    <body>
      <div>
         <form action="/Employee/SaveEmployee" method="post">
            First Name: <input type="text" id="TxtFName" name="FirstName" value="" /><br />
            Last Name: <input type="text" id="TxtLName" name="LastName" value="" /><br />
            Salary: <input type="text" id="TxtSalary" name="Salary" value="" /><br />
            <input type="submit" name="BtnSave" value="Save Employee" />
            <input type="button" name="BtnReset" value="Reset" />
         </form>
      </div>
    </body>
</html>

步骤3 -在索引视图中创建一个链接 开放指数。添加一个指向AddNew动作URL的超链接。 隐藏,复制Code

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

步骤4 -执行并测试应用程序 按F5并执行应用程序 关于实验九的演讲 表格标签的目的是什么? 在本系列的第一天,我们了解到“Web世界不会遵循事件驱动编程模型”。它遵循请求-响应模型。最终用户发出请求,服务器发送响应。表单标签是在HTML中发出请求的一种方式。一旦表单标签内的submit按钮被单击,一个请求将被发送到action属性中指定的URL。 什么是表单标签中的方法属性? 它决定请求的类型。请求可以是以下四种类型之一——get、post、put和delete。 按照网络标准,我们应该使用- ——比;当我们想要得到某物时。当我们想要创造一些东西时,放上->当我们想要更新一些东西,删除->当我们想要删除一些东西时。 使用表单标签发出请求与通过浏览器地址栏或超链接发出请求有何不同? 当在表单标记的帮助下发出请求时,所有输入控件的值将随请求一起发送以进行处理。 那么复选框、单选按钮和下拉菜单呢?此控件的值也将发送吗? 是的,所有的输入控件(input type=text, type=单选,type=复选框)和下拉菜单(表示为“Select”元素)。 值将如何发送到服务器? 当请求的类型为Get、Put或Delete时,值将作为查询字符串参数发送。 当它是post请求时,值将作为post数据发送。 名称属性在输入控件中的用途是什么? 如前所述,当单击submit按钮时,所有输入控件的值将随请求一起发送。它使服务器一次接收多个值。为了在发送时分别区分每个值,每个值都附加一个键,这个键将是简单的“name”属性。 名称和id属性用于相同的目的吗? 不,根据上一个问题,“name”属性会被HTML内部使用,当请求被发送,而“id”属性会被JavaScript内部的开发人员用于一些动态的东西。 “输入类型=提交”和“输入类型=按钮”有什么区别? Submit按钮将在我们想要向服务器发出请求时特别使用,而simple按钮将用于执行一些定制的客户端操作。简单按钮自己不会做任何事情。 实验室10 -在服务器端/控制器中获取发布的数据 步骤1 -创建SaveEmployee操作方法 在Employee控制器内部创建一个名为SaveEmployee的操作方法,如下所示。 隐藏所在sp;复制Code

public string SaveEmployee(Employee e)
{
   return e.FirstName + "|"+ e.LastName+"|"+e.Salary;
}

步骤2 -执行和测试 按F5并执行应用程序。 关于第十实验室的演讲 文本框的值是如何更新员工对象内部的动作方法? 在Asp。有一个概念叫做模型绑定器。 当对包含参数的动作方法发出请求时,模型绑定器将自动执行。模型绑定器将遍历方法的所有基本参数,然后将参数的名称与传入数据中的每个键进行比较(传入数据意味着发布的数据或查询字符串)。当找到匹配时,相应的传入数据将被分配给参数。在此之后,模型绑定器将遍历每个类参数的每个属性,并将每个属性名称与传入数据中的每个键进行比较。当找到匹配时,相应的传入值将被分配给参数。 如果指定了两个参数,一个是“雇员e”,另一个是“字符串FirstName”,会发生什么? FirstName将在原始FirstName变量和e中被更新。FirstName财产。 模型绑定与组合关系工作吗? 可以,但是在这种情况下,应该相应地给出控件的名称。 例子 假设我们有如下Customer类和Address类 隐藏,复制Code

public class Customer
{
	public string FName{get;set;}
    public Address address{get;set;}
}
public class Address
{
	public string CityName{get;set;}
	public string StateName{get;set;}
}

在这种情况下,Html应该是这样的 隐藏,复制Code

...
...
...
<input type="text" name="FName">
<input type="text" name="address.CityName">
<input type="text" name="address.StateName">
...
...
...

实验11 -重置和取消按钮 步骤1 -启动重置和取消按钮 添加一个重置和取消按钮,如下所示 隐藏,复制代码… … … <input type="submit" name="BtnSubmit" value="Save Employee" /> <input type="button" name="BtnReset" value="Reset" onclick="ResetForm();"/比; <input type="submit" name="BtnSubmit" value="Cancel" /> 注意:保存按钮和取消按钮的“Name”属性值相同,即“BtnSubmit”。 步骤2 -定义ResetForm函数 在Html的标题部分添加一个脚本标记,并在其中创建一个JavaScript函数ResetForm,如下所示。 隐藏,复制Code

<script>
    function ResetForm() {
        document.getElementById('TxtFName').value = "";
        document.getElementById('TxtLName').value = "";
        document.getElementById('TxtSalary').value = "";
    }
</script>

步骤3 -在EmplyeeController的SaveEmployee操作方法中实现取消点击。 将SaveEmployee操作方法更改如下 隐藏,复制Code

public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
    switch (BtnSubmit)
    {
        case "Save Employee":
            return Content(e.FirstName + "|" + e.LastName + "|" + e.Salary);
        case "Cancel":
            return RedirectToAction("Index");
    }
    return new EmptyResult();
}

步骤4 -执行应用程序。 按F5并执行应用程序。通过点击“添加新”链接导航到“添加新”屏幕。 步骤5 -测试重置功能 步骤6 -测试保存和取消功能 关于实验室11的演讲 为什么保存和取消按钮都有相同的名称? 我们知道,一旦单击submit按钮,就会向服务器发送请求。所有输入控件的请求值都将被发送。 提交按钮也是一个输入按钮。因此,submit按钮(负责请求)的值也将被发送。 当点击Save按钮时,将发送Save按钮的值,即Save Employee,当点击Cancel按钮时,将发送Cancel按钮的值,即Cancel,即Cancel。 在动作方法中,模型绑定器将完成剩余的工作。它将用输入数据中的值更新参数值(随请求一起来) 实现多个提交按钮的其他方法是什么? 有很多方法。我想讨论其中的三个。 1. 隐藏的表单元素 步骤1 -在视图中创建一个隐藏的表单元素,如下所示。 隐藏,复制Code

<form action="/Employee/CancelSave" id="CancelForm" method="get" style="display:none">

</form>

<form action="/Employee/CancelSave" id="CancelForm"方法="get" style="display:none"> </form> 第2步-将提交按钮改为普通按钮,用JavaScript将上面的表单发布出来。 隐藏,复制Code

<input type="button" name="BtnSubmit" value="Cancel" onclick="document.getElementById('CancelForm').submit()" />

2. 使用JavaScript动态更改动作URL 隐藏,复制Code

<form action="" method="post" id="EmployeeForm" >
...
...
<input type="submit" name="BtnSubmit" value="Save Employee" onclick="document.getElementById('EmployeeForm').action = '/Employee/SaveEmployee'" />
...
<input type="submit" name="BtnSubmit" value="Cancel" onclick="document.getElementById('EmployeeForm').action = '/Employee/CancelSave'" />
</form>

3.Ajax 而不是提交按钮使用简单的输入按钮和单击它使纯Ajax请求使用jQuery或任何其他库。 为什么我们没有使用input type=reset来实现reset功能? Input type=reset控件不会清除值,它只是将值设置为控件的默认值。例子: 隐藏,复制Code

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

在上面的例子中,控制的默认值是“Sukesh”。 如果我们使用input type=reset来实现reset功能,那么默认情况下“Sukesh”将会在文本框中设置每次“reset”按钮被点击。 如果名称与类的属性名称不匹配怎么办? 这是面试中很常见的问题。 假设我们有如下的HTML 隐藏,复制Code

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

现在,我们的模型类包含属性名,如FirstName、LastName和Salary。因此,默认的模型绑定器在这里不起作用。 在这种情况下,我们有以下三个解决方案 在action方法内部,使用Request检索已发送的值。表单语法和手动构造模型对象,如下所示。 隐藏,复制Code

public ActionResult SaveEmployee()
{
        Employee e = new Employee();
        e.FirstName = Request.Form["FName"];
        e.LastName = Request.Form["LName"];
        e.Salary = int.Parse(Request.Form["Salary"])
...
...
}

使用参数名称并按如下方式手动创建模型对象。 隐藏,复制Code

public ActionResult SaveEmployee(string FName, string LName, int Salary)
{
    Employee e = new Employee();
    e.FirstName = FName;
    e.LastName = LName;
    e.Salary = Salary;
...
...
}

创建自定义模型绑定并替换默认模型绑定,如下所示。 步骤1 -创建自定义模型绑定器 藏e,复制Code

public class MyEmployeeModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        Employee e = new Employee();
        e.FirstName = controllerContext.RequestContext.HttpContext.Request.Form["FName"];
        e.LastName = controllerContext.RequestContext.HttpContext.Request.Form["LName"];
        e.Salary = int.Parse(controllerContext.RequestContext.HttpContext.Request.Form["Salary"]);
        return e;
    }
}

步骤2-用这个新的模型绑定替换默认的模型绑定 隐藏,复制Code

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

RedirecttToFunction做什么? 就像ViewResult和ContentResult(第1天讨论的)一样,RedirectToRouteResult是ActionResult的子元素。它表示重定向响应。当浏览器接收到RedirectToRouteResult时,它会向新的动作方法发出新的请求。 注意:这里浏览器负责新请求,因此URL将被更新为新URL。 EmptyResult是什么? 又一个孩子的行动的结果。当浏览器接收到EmptyResult作为响应时,它只会显示空白的屏幕。它只是表示“没有结果”。 在我们的例子中,这种情况不会发生。只是为了确保所有的代码路径都返回写好的value EmptyResult语句。 注意:当ActionMethod返回类型为Void时,它等价于EmptyResult 实验12 -在数据库中保存记录并更新网格 步骤1 -在EmployeeBusinessLayer中创建SaveEmployee,如下所示 隐藏,复制Code

public Employee SaveEmployee(Employee e)
{
    SalesERPDAL salesDal = new SalesERPDAL();
    salesDal.Employees.Add(e);
    salesDal.SaveChanges();
    return e;
}

步骤2 -更改SaveEmployee操作方法 在EmployeeController中更改SaveEmployee操作方法代码,如下所示。 隐藏,复制Code

public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
    switch (BtnSubmit)
    {
        case "Save Employee":
            EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
            empBal.SaveEmployee(e);
            return RedirectToAction("Index");
        case "Cancel":
            return RedirectToAction("Index");
    }
    return new EmptyResult();
}

步骤3 -执行和测试 按F5并执行应用程序。导航到数据输入屏幕并放置一些有效值。 实验13 -增加服务器端验证 在实验10中,我们已经看到了模型绑定器的基本功能。让我们再多了解一点。 模型绑定器使用发布的数据更新Employee对象。但是这并不是模型绑定执行的唯一功能。模型绑定器还会更新ModelState。ModelState封装了模型的状态。 它有一个名为IsValid的属性,用于确定模型(即Employee对象)是否被成功更新。如果任何服务器端验证失败,模型将不会更新。它保存验证错误。 例如:状态(“FirstName”)。错误将包含与名字相关的所有错误它持有传入值(发布数据或查询字符串数据)它持有传入值(发布数据或查询字符串数据) 在Asp.net MVC中,我们使用DataAnnotations来执行服务器端验证。 在我们进入数据注释之前,让我们先了解一些关于模型绑定器的事情 模型绑定器如何与原始数据类型一起工作 当Action方法包含基本类型参数时,模型绑定器将把参数的名称与传入数据中的每个键进行比较(传入数据意味着发布的数据或查询字符串)。 当找到匹配时,相应的传入数据将被分配给参数。当没有找到匹配项时,参数将被指定为默认值。(默认值-对于整数是0(零),对于字符串是null,等等)如果分配是不可能的,因为数据类型不匹配异常将被抛出。 模型绑定器如何与类一起工作 当parameter是类参数时,模型绑定器将遍历所有类的所有属性,并将每个属性名称与传入数据中的每个键进行比较。 当找到匹配时, 如果相应的传入值为空,则 属性将被赋空值。如果不可能赋空值,将设置默认值和ModelState。IsValid将被设置为false。如果null赋值是可能的,但将被视为无效值,因为验证附加到属性,然后null被分配为值和ModelState。IsValid将被设置为false。 如果相应的传入值非空, 如果由于数据类型不匹配或服务器端验证失败而无法分配,则将分配空值和ModelState。IsValid将被设置为false。 如果不可能赋空值,则设置默认值 当没有找到匹配项时,参数将被指定为默认值。(默认值——对于整数它是0(零),对于字符串它是null,等等)在这种情况下ModelState。“有效”将不受影响。 让我们通过向我们正在进行的项目中添加验证特性来理解这一点。 步骤1 -用DataAnnotations装饰属性 从模型文件夹中打开Employee类,并使用DataAnnotation属性修饰FirstName和LastName属性,如下所示。 隐藏,复制Code

public class Employee
{
...
...
    [Required(ErrorMessage="Enter First Name")]
    public string FirstName { get; set; }

    [StringLength(5,ErrorMessage="Last Name length should not be greater than 5")]
    public string LastName { get; set; }
...
...
}

步骤2 -更改SaveEmployee操作方法 打开EmplyeeController并更改SaveEmployee操作方法,如下所示。 隐藏,复制Code

public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
    switch (BtnSubmit)
    {
        case "Save Employee":
            if (ModelState.IsValid)
            {
                EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
                empBal.SaveEmployee(e);
                return RedirectToAction("Index");
            }
            else
            {
                return View("CreateEmployee ");
            }
        case "Cancel":
            return RedirectToAction("Index");
    }
    return new EmptyResult();
}

注意:正如您所看到的,当ModelState。IsValid是错误的响应SaveEmployee按钮点击是ViewResult指向“CreateEmployee”视图。 步骤3 -在视图中显示错误 更改“Views/Index/CreateEmployee”中的HTML。cshtml”之后。 这一次我们将格式化我们的UI与“表格”标签的帮助; 隐藏,收缩,复制Code

<table>
   <tr>
      <td>
         First Name:
      </td>
      <td>
         <input type="text" id="TxtFName" name="FirstName" value="" />
      </td>
   </tr>
   <tr>
      <td colspan="2" align="right">
        @Html.ValidationMessage("FirstName")
      </td>
   </tr>
   <tr>
      <td>
        Last Name:
      </td>
      <td>
         <input type="text" id="TxtLName" name="LastName" value="" />
      </td>
   </tr>
   <tr>
      <td colspan="2" align="right">
         @Html.ValidationMessage("LastName")
      </td>
   </tr>

   <tr>
      <td>
        Salary:
      </td>
      <td>
         <input type="text" id="TxtSalary" name="Salary" value="" />
      </td>
   </tr>
   <tr>
      <td colspan="2" align="right">
        @Html.ValidationMessage("Salary")
      </td>
   </tr>

   <tr>
      <td colspan="2">
         <input type="submit" name="BtnSubmit" value="Save Employee" />
         <input type="submit" name="BtnSubmit" value="Cancel" />
         <input type="button" name="BtnReset" value="Reset" onclick="ResetForm();" />
      </td>
   </tr>
</table>

步骤4 -执行和测试 按F5并执行应用程序。导航到“Employee/AddNew”操作方法并测试应用程序。 测试1 测试2 注意:您可能会出现以下错误。 “模型backi自从创建数据库以来,'SalesERPDAL'上下文已经发生了变化。考虑使用代码优先迁移来更新数据库。” 要删除此错误,只需在全局中的Application_Start中添加以下语句。asax文件。 隐藏,CodeDatabase副本。SetInitializer(新DropCreateDatabaseIfModelChanges< SalesERPDAL> ()); 数据库类存在于System.Data内部。实体名称空间 如果您仍然得到相同的错误,然后在Sql server中打开数据库并删除剩余的migrationhistory表。 很快我将发布一个关于实体框架的新系列,在这里我们将一步一步地学习实体框架。本系列旨在使用MVC模式,我们正努力坚持使用它。 在第13实验室演讲 什么@Html。ValidationMessage做什么? 意思是它是一个剃刀代码html是一个实例HtmlHelper类在视图内部可用。validationmessage是HtmlHelper类的一个函数,它显示错误消息 ValidationMessage函数是如何工作的? ValidationMessage是一个函数。它在运行时执行。如前所述,ModelBinder更新ModelState。ValidationMessage显示来自ModelState的基于键的错误消息。 示例:ValidationMessage(“FirstName”)显示与名字相关的错误消息。 我们是否有更多的属性,如required和StringLength? 有,这里有一些 数据类型-确保数据是特定的类型,如电子邮件,信用卡号码,网址等。enumdatatypeattribu—确保该值存在于枚举中。Range属性-确保值在一个特定的范围内。正则表达式——根据特定的正则表达式验证值。Required——确保提供了该值。StringthLength—验证字符串的最大和最小字符数。 工资是如何被确认的? 我们没有添加任何数据注释属性到工资属性,但它仍然得到验证。原因是,模型绑定器在更新模型时还考虑属性的数据类型。 在测试1中-我们将薪金保留为空字符串。在这种情况下,根据我们的模型绑定解释(在实验13中),ModelState。IsVaid将为false, ModelState将保留与将在视图中显示的薪水相关的验证错误,因为Html.ValidationMessage(" Salary ") 在测试2 -工资数据类型不匹配,因此验证失败。 这是否意味着,整数属性在默认情况下是强制性的? 是的,不仅是整数,而且是所有的值类型,因为它们不能容纳空值。 如果我们想要一个非必需的整数字段呢? 可以为空吗? 隐藏,复制Code

public int? Salary{get;set;}

如何更改为工资指定的验证消息? 对Salary的默认验证支持(因为int数据类型)不允许我们更改验证消息。我们通过使用自己的验证(如正则表达式、范围或自定义验证器)来实现同样的效果。 为什么值在验证失败时被清除? 因为这是一个新请求。从开发的角度来看,在开始时呈现的数据条目视图和后来呈现的数据条目视图是相同的,但是从请求的角度来看是不同的。我们将在第4天学习如何保持价值。 我们可以显式地要求模型绑定器执行吗? 是的,只是从动作方法中删除参数。它会在默认情况下停止执行默认的模型绑定。 在本例中,我们可以使用UpdateModel函数,如下所示。 隐藏,复制Code

Employee e = new Employee();
UpdateModel<employee>(e);
</employee>

注意:UpdateModel不适用于原始数据类型。 UpdateModel和TryUpdateModel方法有什么区别? TryUpdateModel将与UpdateModel相同,除了一个额外的优点。 如果由于任何原因导致模型适应失败,UpdateModel将抛出一个异常。对于UpdateModel函数ModelState。有效将没有任何用处。 TryUpdateModel与将Employee对象作为函数参数完全相同。如果更新失败ModelState。IsValid将为false; 那么客户端验证呢? 除非使用HTML Helper类,否则应该手动完成。 在第4天,我们将在HTML helper类的帮助下讨论手工客户端验证和自动客户端验证。 我们可以将多个DataAnnotation属性附加到同一属性吗? 是的,我们可以。在这种情况下,两个验证都将触发。 实验14 -自定义服务器端验证 步骤1 -创建自定义验证 打开Employee.cs文件并在其中创建一个名为FirstNameValidation的新类,如下所示。 隐藏,复制Code

public class FirstNameValidation:ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null) // Checking for Empty Value
        {
            return new ValidationResult("Please Provide First Name");
        }
        else
        {
            if (value.ToString().Contains("@"))
            {
                return new ValidationResult("First Name should Not contain @");
            }
        }
        return ValidationResult.Success;
    }
}

注意:在一个文件中创建多个类绝不是好的做法。因此,在您的示例中,我建议您在根位置创建一个名为“Validations”的新文件夹,并在其中创建一个新类。 步骤2-附加到名字 打开Employee类并从FirstName属性中删除默认的“Required”属性,并附加FirstNameValidation,如下所示。 隐藏,复制Code

[FirstNameValidation]
public string FirstName { get; set; }

步骤3 -执行和测试 按F5。导航到“员工/添加新”行为离子。 测试1 测试2 结论 这是我们第三天的节目。在第四天,我们将把我们的项目进入下一个版本。下面是第四天的议程 实现客户端验证理解HTML助手实现身份验证添加页脚与部分视图创建与母版页一致的布局自定义请求过滤 在Facebook, LinkedIn或twitter上联系我们,以保持最新的版本。 如需在孟买进行线下技术培训,请访问StepByStepSchools.Net 在线培训请访问JustCompile.com 本文转载于:http://www.diyabc.com/frontweb/news1716.html

原文地址:https://www.cnblogs.com/Dincat/p/13456325.html