如何“扩展”模型验证?

时间:2012-09-19 15:20:27

标签: asp.net-mvc razor

我有一个使用数据注释验证的创建页面。我还有一个编辑页面。两个页面都使用不同的模型我必须为“编辑”页面使用特定模型,以便显示所选行的值。我如何:

1)让编辑控制器使用相同的验证,或者 2)如果我使用与创建页面相同的模型,则获取编辑页面以显示当前行的值?

e.g:

我的创建页面:

@model Test.Models.NewPerson
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true, "Failed. Please fix the errors.")

        <div class="editor-label">
            @Html.LabelFor(m => m.FirstName)
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(m => m.FirstName)
            @Html.ValidationMessageFor(m => m.FirstName)
        </div>
        <div class="editor-label">
            @Html.LabelFor(m => m.LastName)
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(m => m.LastName)
            @Html.ValidationMessageFor(m => m.LastName)
        </div>
    <input type="submit" value="Submit" />
}

@model Test.Models.NewPerson @using (Html.BeginForm()) { @Html.ValidationSummary(true, "Failed. Please fix the errors.") <div class="editor-label"> @Html.LabelFor(m => m.FirstName) </div> <div class="editor-field"> @Html.TextBoxFor(m => m.FirstName) @Html.ValidationMessageFor(m => m.FirstName) </div> <div class="editor-label"> @Html.LabelFor(m => m.LastName) </div> <div class="editor-field"> @Html.TextBoxFor(m => m.LastName) @Html.ValidationMessageFor(m => m.LastName) </div> <input type="submit" value="Submit" /> }

我的模特:

public class NewPerson 
{
    [Required(ErrorMessage = "*")]
    [Display(Name = "First name")]
    public string FirstName { get; set; }

    [Required(ErrorMessage = "*")]
    [Display(Name = "Last name")]
    public string LastName { get; set; }
}

然后我的编辑页面:

public class NewPerson { [Required(ErrorMessage = "*")] [Display(Name = "First name")] public string FirstName { get; set; } [Required(ErrorMessage = "*")] [Display(Name = "Last name")] public string LastName { get; set; } }

@model Test.Person

修改

在我的控制器中,编辑操作,我有:

using (Html.BeginForm())
{
    @Html.ValidationSummary(true, "Please fix the errors below.")

        <div class="editor-label">
            @Html.LabelFor(m => m.FirstName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(m => m.FirstName)
            @Html.ValidationMessageFor(m => m.FirstName)
        </div>
        <div class="editor-label">
            @Html.LabelFor(m => m.LastName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(m => m.LastName)
            @Html.ValidationMessageFor(m => m.LastName)
        </div>
    <input type="submit" value="Update" />
}

using (Html.BeginForm()) { @Html.ValidationSummary(true, "Please fix the errors below.") <div class="editor-label"> @Html.LabelFor(m => m.FirstName) </div> <div class="editor-field"> @Html.EditorFor(m => m.FirstName) @Html.ValidationMessageFor(m => m.FirstName) </div> <div class="editor-label"> @Html.LabelFor(m => m.LastName) </div> <div class="editor-field"> @Html.EditorFor(m => m.LastName) @Html.ValidationMessageFor(m => m.LastName) </div> <input type="submit" value="Update" /> }

当我在该函数中放置一个断点时,我看到var人的结果。但是,它在视图中不返回任何内容。为什么不呢?

修改

以下是我的行动代码:

var context = new MyContext();          
var person = context.Person.Single(m => m.ID == id);

if (Request.IsAjaxRequest())
{
    return PartialView("Edit", person);
}
return View(person);

var context = new MyContext(); var person = context.Person.Single(m => m.ID == id); if (Request.IsAjaxRequest()) { return PartialView("Edit", person); } return View(person);

编辑动作:

[HttpPost]

public ActionResult Create(NewPerson model)
{
if (ModelState.IsValid)
{
    string UID = Membership.GetUser().ProviderUserKey.ToString();
    System.Guid myUID = System.Guid.Parse(UID);

    using (var context = new MyContext())
    {   
       Person newPerson = new Person();
       newPerson.UserId = myUID;
       newPerson.FirstName = model.FirstName;
       newPerson.LastName = model.LastName;
       context.Person.AddObject(newPerson);
       context.SaveChanges();
    }
    }

我的观点: public ActionResult Create(NewPerson model) { if (ModelState.IsValid) { string UID = Membership.GetUser().ProviderUserKey.ToString(); System.Guid myUID = System.Guid.Parse(UID); using (var context = new MyContext()) { Person newPerson = new Person(); newPerson.UserId = myUID; newPerson.FirstName = model.FirstName; newPerson.LastName = model.LastName; context.Person.AddObject(newPerson); context.SaveChanges(); } }

2 个答案:

答案 0 :(得分:0)

两个视图都可以使用相同的模型。这是创建/编辑功能的常见做法,将解决问题1,具有相同的验证规则。

要在编辑视图的输入字段中显示现有数据,您需要在控制器中检索该数据并将其传递给视图(即填充模型)。

据推测,在编辑中,您将拥有某种ID。使用它从数据源获取正确的记录,然后在模型中设置FirstName和LastName值。然后,当您渲染视图时(当然,在传入模型之后),您将看到文本框中的现有值。

答案 1 :(得分:0)

这里有点令人困惑的是你有什么和没做过什么,什么做不起作用。但是,您应该解决一些问题。

首先,您不应该将来自数据库的Person对象直接传递给视图。相反,您应该拥有自己的特定Person ViewModel。此ViewModel应该为您的视图提供数据注释。当您从数据库中获取Person时,将它们投影到ViewModel中,如下所示:

var camper = context.Person
    .Select(m => new ViewModel.Person
         { Firstname = m.Firstname, Lastname = m.Lastname}).Single(m => m.ID == id);

这可以防止您的数据模型的Person因View要求而膨胀(例如,您的数据模型可能允许空值,但您希望将View设置为必需。)

其次,您没有在编辑视图中使用using语句。像这样:

using (var camper = ..) {
    ...
}

使用ViewModel也有帮助,因为这样可以销毁上下文,而不会与更改跟踪的实体发生冲突。

第三,你应该更好地使用DisplayTemplates。不要在您的视图中使用foreach语句,而是执行此操作:

@Html.DisplayForModel()

然后在Views \ Shared(或视图所在的文件夹中)创建一个名为DisplayTemplates的文件夹,并创建一个名为Person.cshtml的新.cshtml文件,其中包含以下代码:

@model Person
@Html.DisplayFor(m => m.LastName), @Html.DisplayFor(m => m.FirstName)

@Html.ActionLink("Edit", "Edit", new { id = person.ID }, new { @class = "openDialog", 
    data_dialog_id = "emailDialog", data_dialog_title = "Edit Person" })

我还注意到您的命名空间中存在一些差异。在一个地方你有Test.Person,在另一个地方你有Test.Models.NewPerson。你是否有可能还有一个Test.Models.Person并且你对哪个是哪个感到困惑,所以你最终填充了错误的一个?