c# - 自定义 ViewModel 类 - 除非指定前缀,否则并非所有字段都标记为无效

标签 c# asp.net-mvc viewmodel data-annotations xval

我有一个自定义 View 模型,其中有两个字段和一个 linq2sql 实体..所有字段都附加了验证属性。即使所有字段都无效,也只有 linq2sql 类中的字段在视觉上指示错误,而 viewmodel 中的字段正常显示。但是会显示所有无效字段的错误消息。

我的自定义 ViewModel 如下所示:

public class BooksViewModel
{
    public SelectList BookCategories { get; set; }

    public Book Book { get; set; }

    [Required(ErrorMessage="Field1 is required")]
    [StringLength(10)]
    public string Field1 { get; set; }

    [Required(ErrorMessage = "Field2 question is required")]
    [StringLength(100)]
    public string Field2 { get; set; }
}

Book 类是一个 linq2sql 实体,它附加了一个用于验证的元数据类型属性。

[MetadataType(typeof(BookMetadata))]
public partial class Book
{
}
public class BookMetadata
{
    [Required(ErrorMessage="Choose a category")]
    public int CategoryID { get; set; }

    [Required(ErrorMessage = "Title is required")]
    [StringLength(100)]
    public string Title { get; set; }

    [Required(ErrorMessage = "Published date is required")]
    [DataType(DataType.Date, ErrorMessage="Enter a valid date")]
    public DateTime PublishedDate { get; set; }

    [Required(ErrorMessage = "Author is required")]
    [StringLength(50)]
    public string Author { get; set; }
}

存储库中有一个具有两个重载的 AddBook 方法。一个采用 View 模型,一个采用 Book 类型:

public void AddBook(Book book)
{
    var errors = DataAnnotationsValidationRunner.GetErrors(book);

    if (errors.Any()) {
        throw new RulesException(errors);
    }

    _db.Books.InsertOnSubmit(book);
    _db.SubmitChanges();
}

public void AddBook(BooksViewModel model)
{
    var errors = DataAnnotationsValidationRunner.GetErrors(model);

    if (errors.Any()) {
        throw new RulesException(errors);
    }
}

Controller 中的创建操作如下所示:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "Book.ID")]BooksViewModel booksViewModel)
{
    try {
        // Validate Book
        _repository.AddBook(booksViewModel.Book);
    } catch(RulesException ex) {
        ex.AddModelStateErrors(ModelState, "Book");
    }

    try {
        // Validate other fields in the view model
        _repository.AddBook(booksViewModel);
    } catch (RulesException ex) {
        ex.AddModelStateErrors(ModelState, "");
    }

    if (ModelState.IsValid) {
        return RedirectToAction("Index");
    } else {
        booksViewModel.BookCategories = new SelectList(_repository.GetAllCategories().AsEnumerable(), "ID", "CategoryName", booksViewModel.Book.CategoryID);
        return (ActionResult)View(booksViewModel);
    }
}

我正在使用 xVal 生成客户端验证规则。我的创建 View 如下所示:

<% using (Html.BeginForm()) {%>

    <fieldset>
        <legend>Fields</legend>
        <p>
            <label for="Book.CategoryID">CategoryID:</label>
            <%= Html.DropDownList("Book.CategoryID", Model.BookCategories, "Select")%>
            <%= Html.ValidationMessage("Book.CategoryID", "*")%>
        </p>
        <p>
            <label for="Book.Title">Title:</label>
            <%= Html.TextBox("Book.Title")%>
            <%= Html.ValidationMessage("Book.Title", "*")%>
        </p>
        <p>
            <label for="Book.PublishedDate">PublishedDate:</label>
            <%= Html.TextBox("Book.PublishedDate")%>
            <%= Html.ValidationMessage("Book.PublishedDate", "*")%>
        </p>
        <p>
            <label for="Book.Author">Author:</label>
            <%= Html.TextBox("Book.Author")%>
            <%= Html.ValidationMessage("Book.Author", "*")%>
        </p>
        <p>
            <label for="Field1">Field1:</label>
            <%= Html.TextBox("Field1")%>
            <%= Html.ValidationMessage("Field1", "*")%>
        </p>
        <p>
            <label for="Field2">Field2:</label>
            <%= Html.TextBox("Field2")%>
            <%= Html.ValidationMessage("Field2", "*")%>
        </p>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>

<% } %>

<div>
    <%=Html.ActionLink("Back to List", "Index") %>
</div>
<%= Html.ClientSideValidation<BooksViewModel>() %>
<%= Html.ClientSideValidation<Book>("Book") %>

客户端验证工作正常..但如果我关闭 javascript 然后回发所有字段的表单错误消息,但 Field1 和 Field2 未标记为无效..没有 css 类添加到字段并且没有生成用于视觉错误指示的 span 标签。

Screenshot http://img22.imageshack.us/img22/324/26677634.jpg

但是如果我用任何东西来固定 ViewModel 字段

public ActionResult Create([Bind(Prefix = "VM", Exclude = "Book.ID")]BooksViewModel booksViewModel)

然后相应地修改 View 然后一切正常:

<p>
    <label for="VM.Book.Title">Title:</label>
    <%= Html.TextBox("VM.Book.Title")%>
    <%= Html.ValidationMessage("VM.Book.Title", "*")%>
</p>

<p>
    <label for="VM.Field1">Field1:</label>
    <%= Html.TextBox("VM.Field1")%>
    <%= Html.ValidationMessage("VM.Field1", "*")%>
</p>

<%= Html.ClientSideValidation<BooksViewModel>("VM") %>
<%= Html.ClientSideValidation<Book>("Book") %>

我在这里做错了什么?

抱歉让这篇文章这么长..

最佳答案

我认为问题可能出在您的变量名和类名相同。

也许在你的 ViewModel 中重命名为类似的东西,

public Book BookInstance { get; set; }

这需要进行一些重构,但我认为这是导致您出现问题的原因。

善良,

关于c# - 自定义 ViewModel 类 - 除非指定前缀,否则并非所有字段都标记为无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1277314/

相关文章:

c# - 如何通过操作结果从另一个局部 View 更新局部 View

jquery - WCF/ASP.NET MVC : Supporting events from WCF to asp.net MVC 或类似的概念?

asp.net-mvc - ASP.NET MVC - ViewModel 是否适合进行较小的计算?

c# - 使用 .Net6 Windows 10 在 Visual Studio Code for OmniSharp 上出错

c# - WPF在TabControl的DataTemplate中绑定(bind)不同的UserControl

c# - LINQ: "contains"和 Lambda 查询

asp.net - 如何强制 Web API 识别查询字符串参数

asp.net-mvc - 访问 RavenDB 时获取 System.Net.Sockets.SocketException

Android MVVM - 如何在 ViewModel 中引用 Activity

c# - MVVM 根据 ComboBox 所选项目加载 View