我试图理解我应该如何独立验证我的MVC3页面的客户端部分,并提出了我想要实现的简化版本。
如果我使用一种形式:
优点:当我提交回“PostData”控制器方法时,我会收到表单中包含的所有数据。在这种情况下,值“name”和“description”,这意味着我可以实例化“PersonHobbyModel”并分配我收到的数据。我可以存储在数据库中,也可以返回相同的视图。
缺点:我无法独立验证。因此,如果“名称”没有完成,我完成“描述”,我仍然可以提交页面。 (这是我想要做的简单版本,我会有更多的字段而不仅仅是“名称”和“描述”)
有两种形式: 优点:我可以独立验证。
缺点:控制器方法只接收子表单数据,在这种情况下,“人名”或“爱好描述”,这意味着我无法重新创建“PersonHobbyModel”的完整实例。
这是模型:
public class Person {
[Display(Name = "Person name:")]
[Required(ErrorMessage = "Person name required.")]
public string Name { get; set; }
}
public class Hobby {
[Display(Name = "Hobby description:")]
[Required(ErrorMessage = "Hobby description required.")]
public string Description { get; set; }
}
public class PersonHobbyModel {
public PersonHobbyModel() {
this.Person = new Person();
this.Hobby = new Hobby();
}
public Person Person { get; set; }
public Hobby Hobby { get; set; }
}
这是控制器:
public class PersonHobbyController : Controller
{
//
// GET: /PersonHobby/
public ActionResult Index()
{
var model = new PersonHobbyModel();
return View(model);
}
public ActionResult PostData(FormCollection data) {
var model = new PersonHobbyModel();
TryUpdateModel(model.Person, "Person");
TryUpdateModel(model.Hobby,"Hobby");
return View("Index", model);
}
}
这是观点:
@model MultipleFORMStest.PersonHobbyModel
@{
ViewBag.Title = "Index";
}
<h2>
Index</h2>
@using (Html.BeginForm("PostData", "PersonHobby")) {
<div>
@Html.LabelFor(model => model.Person.Name)
@Html.TextBoxFor(model => model.Person.Name)
@Html.ValidationMessageFor(model => model.Person.Name)
<input type="submit" value="Submit person" />
</div>
}
@using (Html.BeginForm("PostData", "PersonHobby")) {
<div>
@Html.LabelFor(model => model.Hobby.Description)
@Html.TextBoxFor(model => model.Hobby.Description)
@Html.ValidationMessageFor(model => model.Hobby.Description)
<input type="submit" value="Submit hobby" />
</div>
}
更新1
我没有提及,因为我想让问题尽可能简单,但对于其中一个部分我正在使用“jquery ui对话框”。我最初使用DIV来定义对话框,我在主窗体中有这个对话框。这会导致一个问题,因为我无法在客户端验证“JQuery对话框表单”独立于表单的其余部分。
说这个jquery确实从主窗体中删除了“div jquery ui dialog”,这使得我以自己的形式包含了对话框。出于这个原因,我最终得到了两种形式。优点是我现在可以独立验证“jquery对话框ui表单”。
但我很困惑,我应该如何处理从客户端上的各种表单提交的服务器数据,因为用户可能已禁用JS。如果我从一个表单提交,我无法以其他形式访问数据。
更新2
谢谢你的回复。我相信我确实需要两个表单和两个实体,因为我想在客户端上独立地验证它们(除了被“Jquery UI Dialog”强制使用之外)。例如,如果我有,而不是一个爱好,我有一个爱好列表,我可以在同一视图中的网格中显示。所以我无法填写人名,但继续向网格添加爱好,如果我没有完成业余爱好描述我会得到验证错误。 (对不起,我应该在最初的问题中包括我的两个更新,但为了清楚起见,我希望保持它像posible一样简单)
答案 0 :(得分:4)
从我的角度来看,您有一个与两个实体模型相对应的视图模型。在您的位置,我将使用单个表单并验证视图模型,而不是真正将其视为两个(依赖)实体。在操作中接收视图模型,而不是通用表单集合,并通过数据注释属性使用基于模型的验证。获得有效的已发布模型后,您可以将其转换为适当的实体并将其保存到数据库中。
模型
public class PersonHobbyViewModel {
[Display(Name = "Person name:")]
[Required(ErrorMessage = "Person name required.")]
public string Name { get; set; }
[Display(Name = "Hobby description:")]
[Required(ErrorMessage = "Hobby description required.")]
public string Description { get; set; }
}
控制器
public class PersonHobbyController : Controller
{
//
// GET: /PersonHobby/
[HttpGet] // mark as accepting only GET
public ActionResult Create() // Index should probably provide some summary of people and hobbies
{
var model = new PersonHobbyViewModel();
return View(model);
}
[HttpPost] // mark as accepting only POST
public ActionResult Create(PersonHobbyViewModel model) {
if (ModelState.IsValid) {
var person = new Person { Name = model.Name };
var hobby = new Hobby { Description = model.Description };
person.Hobbies = new List<Hobby> { hobby };
db.Persons.Add( person );
db.SaveChanges();
}
return RedirectToAction( "details", new { id = person.Id } ); // view the newly created entity
}
}
查看
@model MultipleFORMStest.PersonHobbyViewModel
@{
ViewBag.Title = "Create";
}
<h2>
Create</h2>
@using (Html.BeginForm("Create", "PersonHobby")) {
<div>
@Html.LabelFor(model => model.Person.Name)
@Html.TextBoxFor(model => model.Person.Name)
@Html.ValidationMessageFor(model => model.Person.Name)
<input type="submit" value="Submit person" />
</div>
<div>
@Html.LabelFor(model => model.Hobby.Description)
@Html.TextBoxFor(model => model.Hobby.Description)
@Html.ValidationMessageFor(model => model.Hobby.Description)
<input type="submit" value="Submit hobby" />
</div>
}
答案 1 :(得分:1)
我认为您的ViewModel应该只针对您所代表的视图。在这种情况下,我会使用像这样的ViewModel
public class AddPersonHobbyViewModel
{
[Required]
[Display (Name="Person Name")]
public string PersonName { set;get;}
[Required]
[Display (Name="Hobby Description")]
public string HobbyDescription { set;get;}
}
在我的PostData ActionMethod中,我将检查模型验证
[HttpPost]
public ActionResult PostData(AddPersonHobbyViewModel objVM)
{
if(ModelState.IsValid)
{
// Everything is fine. Lets save and redirect to another get View( for PRG pattern)
}
return View(objVm);
}
您只能在视图中使用一个强类型为AddPersonHobbyViewModel
@model AddPersonHobbyViewModel
@using (Html.BeginForm("PostData","Person"))
{
@Html.TextBoxFor(m=>m.PersonName)
@Html.ValidationMessageFor(m => m.PersonName)
@Html.TextBoxFor(m=>m.HobbyDescription )
@Html.ValidationMessageFor(m => m.HobbyDescription )
<input type="submit" value="Save" />
}