输入表单

本文总阅读量:
  1. 1. 数据输入的一般模式
    1. 1.1. 一个经典的选择编辑提交场景
      1. 1.1.1. 提供数据和处理选择项
      2. 1.1.2. 编辑数据
      3. 1.1.3. 保存数据
  2. 2. 输入表单自动化编写
    1. 2.1. 预定义的模板
      1. 2.1.1. 预定义模板使用的数据批注
      2. 2.1.2. 数据类型的默认模板
      3. 2.1.3. 用于数据类型的自定义模板
  3. 3. 输入验证
    1. 3.1. 利用数据批注
    2. 3.2. 高级数据批注
      1. 3.2.1. 跨属性验证
      2. 3.2.2. 创建自定义验证特性
      3. 3.2.3. 远程验证

不管你能做什么,或者梦想做什么,开始去做吧—-沃尔夫冈-歌德

数据输入的一般模式

  • 编辑→提交
  • 选择→编辑→提交

一个经典的选择编辑提交场景

提供数据和处理选择项

仅作演示,先创建index action,get 选择列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// GET: Test
public ActionResult Index()
{
var model = new IndexViewModel();
model.Tests = GeTests();
return View(model);
}

public List<Models.Test.Test> GeTests()
{
var tests = new List<Models.Test.Test>();
tests.Add(new Models.Test.Test()
{
Id = 1,
Name = "luox"
});
tests.Add(new Models.Test.Test()
{
Id = 2,
Name = "luox2"
});
tests.Add(new Models.Test.Test()
{
Id = 3,
Name = "luox3"
});
tests.Add(new Models.Test.Test()
{
Id = 4,
Name = "luox4"
});
tests.Add(new Models.Test.Test()
{
Id = 5,
Name = "luox5"
});
tests.Add(new Models.Test.Test()
{
Id = 6,
Name = "luox6"
});
return tests;
}

为了实现异步显示,使用ajaxhelper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@model _02.Models.Test.IndexViewModel
@{
ViewBag.Title = "Index";
}

<h2>Index</h2>

@using (Ajax.BeginForm("Edit", new AjaxOptions()
{
HttpMethod = "post",
UpdateTargetId = "show"
}))
{
@Html.DropDownList("test", new SelectList(Model.Tests, "id", "name"))
<input type="submit" value="submit" />
}

<div id="show"></div>
@Html.ValidationMessage("name")

@section scripts
{
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
}

其中Html.DropDownList方法

1
2
3
4
5
/// <param name="items">各个项。</param>
/// <param name="dataValueField">数据值字段。(option标签value属性)</param>
/// <param name="dataTextField">显示文本字段。</param>
/// <param name="selectedValue">选定的值。</param>
public SelectList(IEnumerable items, string dataValueField, string dataTextField, object selectedValue)

注意使用ajaxhelper要引入<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>

编辑数据

这里返回部分视图

1
2
3
4
5
6
7
8
9
10
11
12
[HttpPost]
public PartialViewResult Edit(int test)
{
return PartialView("_edit", new EditViewModel()
{
Test = new Models.Test.Test()
{
Id = test,
Name = "luox" + test.ToString()
}
});
}

视图中可以将修改提价到updata使用隐藏域,模型绑定器会指定生成Test模型

1
2
3
4
5
6
7
8
9
10
11
12
13
@model _02.Models.Test.EditViewModel

@using (Html.BeginForm("update", "Test"))
{
@Html.DisplayNameFor(m => m.Test.Id)
@Html.DisplayFor(m => m.Test.Id)
@Html.HiddenFor(m => m.Test.Id)
<br />
@Html.DisplayNameFor(m => m.Test.Name)
@Html.TextBoxFor(m => m.Test.Name)
<br />
<input type="submit" value="submit" />
}

保存数据

1
2
3
4
5
6
7
8
9
10
11
12
[HttpPost]
public ActionResult Update(Models.Test.Test test)
{
//model验证
if (test.Name == "luox78")
{
ModelState.AddModelError("name", "can not be luox78");
}
TempData["modelstate"] = ModelState;
//todo 更新数据库
return Redirect("index");
}

传入的模型首先要验证,不通过将modelstate存入tempdata,tempdata会保存信息至第二次请求结束,重定向到index,同时要合并modelstate,index方法中添加

1
ModelState.Merge(TempData["modelstate"] as ModelStateDictionary);

输入表单自动化编写

预定义的模板

@Html.DisplayNameFor(m => m.Test.Id)

@Html.DisplayFor(m => m.Test.Id)

@Html.TextBoxFor(m => m.Test.Name)

预定义模板使用的数据批注

特性 描述
DataType 表示该数据应该展示为的类型,支持Decimal,Date,DateTime,Email,Password,Url,PhoneNumber,MultilineText
DisplayFormat 表示通过什么格式显示
DisplayName 标签内文本
HiddenInput 表示一个隐藏输入字段是否应该显示以替代一个可见输入字段
UIHint 表示使用用户自定义模板名称

数据类型的默认模板

当使用editor、display时,系统有自己的默认模板,用于bool,decimal,emailaddress,hiddeninput,html,object,string,text,url这些数据类型

用于数据类型的自定义模板

首先添加对应的特性

1
2
[UIHint("Edit_DateTime")]
public DateTime DateTime { get; set; }

Editor,Display模板摆放在对应的views/controller/EditorTemplates|DisplayTemplates文件夹下

自定义的DateTime Editor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@model DateTime
<div>
<table>
<tr>
@Html.Label("year")
@Html.TextBox("year",@Model.Year)
</tr>
<tr>
@Html.Label("month")
@Html.TextBox("month", @Model.Month)
</tr>
<tr>
@Html.Label("day")
@Html.TextBox("day", @Model.Day)
</tr>
</table>
</div>

使用@Html.EditorFor(m => m.DateTime)

输入验证

利用数据批注

用于数据验证的特性是DataAnnotationsModelValidatorProvider类

Attribute Description
Required Indicates that the property is a required field
StringLength Defines a maximum length for string field
Range Defines a maximum and minimum value for a numeric field
RegularExpression Specifies that the field value must match with specified Regular Expression
CreditCard Specifies that the specified field is a credit card number
CustomValidation Specified custom validation method to validate the field
EmailAddress Validates with email address format
FileExtension Validates with file extension
MaxLength Specifies maximum length for a string field
MinLength Specifies minimum length for a string field
Phone Specifies that the field is a phone number using regular expression for phone numbers

这些特性都是继承自ValidationAttribute

模型绑定器会自动将无效的验证信息放入ModelState字典中,通过Html.ValidationMessage显示出来

Example: Apply DataAnnotation Attributes

1
2
3
4
5
6
7
8
9
10
public class Student
{
public int StudentId { get; set; }

[Required]
public string StudentName { get; set; }

[Range(5,50)]
public int Age { get; set; }
}

通过[Required(ErrorMessage = "....")]自定义错误显示

高级数据批注

跨属性验证

默认的compare特性就是跨属性验证

通过CustomValidation实现自定义跨属性验证

1
2
3
[CustomValidation(typeof(EditViewModel),"MyValidation")]
public string Str1 { get; set; }
public string Str2 { get; set; }
1
public CustomValidationAttribute(Type validatorType, string method)

validatorType:所在类

method:对应验证方法

1
2
3
4
5
6
7
8
9
10
11
12
13
public static ValidationResult MyValidation(string Str1, ValidationContext context)
{
var obj = context.ObjectInstance as EditViewModel;
if (obj == null)
throw new NullReferenceException();

if (Str1 == obj.Str2 && Str1 == "luox78")
{
return ValidationResult.Success;
}

return new ValidationResult("str1 != str2 or != luox78");
}

创建自定义验证特性

继承自ValidationAttribute重写方法即可

1
2
3
4
5
6
7
8
9
10
11
public class IsLuox78Attribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value == "luox78")
{
return ValidationResult.Success;
}
return new ValidationResult("!=luox78");
}
}
1
2
[IsLuox78]
public string Str2 { get; set; }

远程验证

当必须访问数据库验证某些信息的时候可以使用远程验证

1
2
[Remote("IsOk","Test",ErrorMessage = "not ok")]
public string Str2 { get; set; }
1
2
3
4
/// <summary>使用指定的操作方法名称和控制器名称来初始化 <see cref="T:System.Web.Mvc.RemoteAttribute" /> 类的新实例。</summary>
/// <param name="action">操作方法的名称。</param>
/// <param name="controller">控制器的名称。</param>
public RemoteAttribute(string action, string controller)
1
2
3
4
5
6
7
8
public ActionResult IsOk(string str2)
{
if (str2 == "luox782")
{
return Json(true, JsonRequestBehavior.AllowGet);
}
return Json(false, JsonRequestBehavior.AllowGet);
}