ASP.NET MVC2 - 使用LINQ生成的类(验证问题)

时间:2010-05-03 12:13:06

标签: c# asp.net-mvc-2

关于ASP.NET MV2,我很少有事情不清楚。 在数据库中,我有一个包含多个字段的表Contacts,还有一个字段XmlFields,其类型为xml。在该字段中存储了附加描述字段 共有4个班级:

  1. Contact类,对应Contact表,在创建LINQ类时默认定义
  2. ContactListView继承的类 Contact上课并且有一些 其他属性
  3. ContactXmlView包含的类 来自XmlFields字段
  4. 的字段
  5. ContactDetailsView上课哪个 合并ContactListViewContactXmlView进入一个班级 这一个用于显示数据 查看页面
  6. ContactListView类重新定义了Contact类中的一些属性(以便我可以添加用于验证的[Required]过滤器) - 但是我收到警告消息:

      

    'ObjectTest.Models.Contacts.ContactListView.FirstName'   隐藏继承的成员   'SA.Model.Contact.FirstName'。使用   如果想隐藏新关键字。

    在创建新联系人并将其添加到数据库时,

    ContactDetailsView类也会在表单中使用。

    我不确定这是否正确,警告信息让我感到困惑。有关于此的任何建议吗?

    谢谢,
    ILE

    修改

    根据Jakob's instructions我从头开始尝试:

    [MetadataType(typeof(Person_Validation))]
        public partial class Person
        {
        }
    
        public class Person_Validation 
        {
            [Required]
            string FirstName { get; set; }
    
            [Required]
            string LastName { get; set; }
    
            [Required]
            int Age { get; set; }
        }
    

    在控制器中我有这个:

    [HttpPost]
            public ActionResult Create(Person person, FormCollection collection)
            {
                if (ModelState.IsValid)
                {
                    try
                    {
                        personRepository.Add(person);
                        personRepository.Save();
                    }
                    catch
                    {
                        return View(person);
                    }
                }
    
                return RedirectToAction("Index");            
            }
    

    查看:

    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Validate.Models.Person>" %>
    
    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
     Create
    </asp:Content>
    
    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    
        <h2>Create</h2>
    
        <% using (Html.BeginForm()) {%>
            <%= Html.ValidationSummary(true) %>
    
            <fieldset>
                <legend>Fields</legend>           
    
                <div class="editor-label">
                    <%= Html.LabelFor(model => model.FirstName) %>
                </div>
                <div class="editor-field">
                    <%= Html.TextBoxFor(model => model.FirstName) %>
                    <%= Html.ValidationMessageFor(model => model.FirstName) %>
                </div>
    
                <div class="editor-label">
                    <%= Html.LabelFor(model => model.LastName) %>
                </div>
                <div class="editor-field">
                    <%= Html.TextBoxFor(model => model.LastName) %>
                    <%= Html.ValidationMessageFor(model => model.LastName) %>
                </div>
    
                <div class="editor-label">
                    <%= Html.LabelFor(model => model.Age) %>
                </div>
                <div class="editor-field">
                    <%= Html.TextBoxFor(model => model.Age) %>
                    <%= Html.ValidationMessageFor(model => model.Age) %>
                </div>
    
                <p>
                    <input type="submit" value="Create" />
                </p>
            </fieldset>
    
        <% } %>
    
        <div>
            <%= Html.ActionLink("Back to List", "Index") %>
        </div>
    
    </asp:Content>
    

    在发布没有值的新人时,没有任何反应(页面只是重新加载)。使用某些值发布时,person会添加到db。 我不知道我做错了什么。

    编辑2

    我认为问题出现在已经生成了部分类Person的LINQ中。当我定义新的部分类Person并单击它并“转到定义”时,我收到以下警告:

      

    C:\ Documents and Settings \ Korisnik \ My   Documents \ Visual Studio   2008 \项目\验证\验证\型号\ DataClasses1.designer.cs    - (78,23):Validate.Models.Person

         

    C:\ Documents and Settings \ Korisnik \ My   Documents \ Visual Studio   2008 \项目\验证\验证\型号\ PersonRepository.cs    - (11,26):Validate.Models.Person

    这是LINQ生成的类的一部分:

    [Table(Name="dbo.Persons")]
     public partial class Person : INotifyPropertyChanging, INotifyPropertyChanged
     {
    
      private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
    
      private int _PersonID;
    
      private string _FirstName;
    
      private string _LastName;
    
      private string _Age;
    
                    ...
    

    我很确定这是原因,但我不知道如何解决这个问题。有什么想法吗?

    编辑3
    好吧,让我们从头开始......所以这是文件夹结构:

    http://img535.imageshack.us/img535/3187/70090809.gif http://img227.imageshack.us/img227/6643/15910591.gif

    Dataclasses1.designer.cs:

    #pragma warning disable 1591
    //------------------------------------------------------------------------------
    // <auto-generated>
    //     This code was generated by a tool.
    //     Runtime Version:2.0.50727.3603
    //
    //     Changes to this file may cause incorrect behavior and will be lost if
    //     the code is regenerated.
    // </auto-generated>
    //------------------------------------------------------------------------------
    
    namespace Validate.Models
    {
     using System.Data.Linq;
     using System.Data.Linq.Mapping;
     using System.Data;
     using System.Collections.Generic;
     using System.Reflection;
     using System.Linq;
     using System.Linq.Expressions;
     using System.ComponentModel;
     using System;
    
    
     [System.Data.Linq.Mapping.DatabaseAttribute(Name="Database1")]
     public partial class DataClasses1DataContext : System.Data.Linq.DataContext
     {
    
      private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource();
    
        #region Extensibility Method Definitions
        partial void OnCreated();
        partial void InsertPerson(Person instance);
        partial void UpdatePerson(Person instance);
        partial void DeletePerson(Person instance);
        #endregion
    
      public DataClasses1DataContext() : 
        base(global::System.Configuration.ConfigurationManager.ConnectionStrings["Database1ConnectionString"].ConnectionString, mappingSource)
      {
       OnCreated();
      }
    
      public DataClasses1DataContext(string connection) : 
        base(connection, mappingSource)
      {
       OnCreated();
      }
    
      public DataClasses1DataContext(System.Data.IDbConnection connection) : 
        base(connection, mappingSource)
      {
       OnCreated();
      }
    
      public DataClasses1DataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) : 
        base(connection, mappingSource)
      {
       OnCreated();
      }
    
      public DataClasses1DataContext(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource) : 
        base(connection, mappingSource)
      {
       OnCreated();
      }
    
      public System.Data.Linq.Table<Person> Persons
      {
       get
       {
        return this.GetTable<Person>();
       }
      }
     }
    
     [Table(Name="dbo.Persons")]
     public partial class Person : INotifyPropertyChanging, INotifyPropertyChanged
     {
    
      private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
    
      private int _PersonID;
    
      private string _FirstName;
    
      private string _LastName;
    
      private string _Age;
    
        #region Extensibility Method Definitions
        partial void OnLoaded();
        partial void OnValidate(System.Data.Linq.ChangeAction action);
        partial void OnCreated();
        partial void OnPersonIDChanging(int value);
        partial void OnPersonIDChanged();
        partial void OnFirstNameChanging(string value);
        partial void OnFirstNameChanged();
        partial void OnLastNameChanging(string value);
        partial void OnLastNameChanged();
        partial void OnAgeChanging(string value);
        partial void OnAgeChanged();
        #endregion
    
      public Person()
      {
       OnCreated();
      }
    
      [Column(Storage="_PersonID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
      public int PersonID
      {
       get
       {
        return this._PersonID;
       }
       set
       {
        if ((this._PersonID != value))
        {
         this.OnPersonIDChanging(value);
         this.SendPropertyChanging();
         this._PersonID = value;
         this.SendPropertyChanged("PersonID");
         this.OnPersonIDChanged();
        }
       }
      }
    
      [Column(Storage="_FirstName", DbType="NChar(10)")]
      public string FirstName
      {
       get
       {
        return this._FirstName;
       }
       set
       {
        if ((this._FirstName != value))
        {
         this.OnFirstNameChanging(value);
         this.SendPropertyChanging();
         this._FirstName = value;
         this.SendPropertyChanged("FirstName");
         this.OnFirstNameChanged();
        }
       }
      }
    
      [Column(Storage="_LastName", DbType="NChar(10)")]
      public string LastName
      {
       get
       {
        return this._LastName;
       }
       set
       {
        if ((this._LastName != value))
        {
         this.OnLastNameChanging(value);
         this.SendPropertyChanging();
         this._LastName = value;
         this.SendPropertyChanged("LastName");
         this.OnLastNameChanged();
        }
       }
      }
    
      [Column(Storage="_Age", DbType="NChar(10)")]
      public string Age
      {
       get
       {
        return this._Age;
       }
       set
       {
        if ((this._Age != value))
        {
         this.OnAgeChanging(value);
         this.SendPropertyChanging();
         this._Age = value;
         this.SendPropertyChanged("Age");
         this.OnAgeChanged();
        }
       }
      }
    
      public event PropertyChangingEventHandler PropertyChanging;
    
      public event PropertyChangedEventHandler PropertyChanged;
    
      protected virtual void SendPropertyChanging()
      {
       if ((this.PropertyChanging != null))
       {
        this.PropertyChanging(this, emptyChangingEventArgs);
       }
      }
    
      protected virtual void SendPropertyChanged(String propertyName)
      {
       if ((this.PropertyChanged != null))
       {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
       }
      }
     }
    }
    #pragma warning restore 1591
    

    PersonRepository.cs:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.ComponentModel.DataAnnotations;
    using System.Web.Mvc;
    using Validate.Models;
    
    namespace Validate.Models
    {
        [MetadataType(typeof(Person_Validation))]
        public partial class Person
        {
        }
    
        public class Person_Validation 
        {
            [Required]
            string FirstName { get; set; }
    
            [Required]
            string LastName { get; set; }
    
            [Required]
            int Age { get; set; }
        }
    
        public class PersonRepository
        {
            private DataClasses1DataContext db = new DataClasses1DataContext();
    
            public IQueryable<Person> FindAllPersons()
            {
                return db.Persons;
            }
    
            public Person GetPerson(int id)
            {
                return db.Persons.SingleOrDefault(x => x.PersonID == id);
            }
    
            public void Add(Person person)
            {
                db.Persons.InsertOnSubmit(person);
            }
    
            public void Delete(Person person)
            {
                db.Persons.DeleteOnSubmit(person);
            }
    
            public void Save()
            {
                db.SubmitChanges();
            }
        }
    }
    

    /Views/Person/Create.aspx:

    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Validate.Models.Person>" %>
    
    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
     Create
    </asp:Content>
    
    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    
        <h2>Create</h2>
    
        <%= ViewData["greska"]%>
    
        <% using (Html.BeginForm()) {%>
            <%= Html.ValidationSummary(true) %>
    
            <fieldset>
                <legend>Fields</legend>           
    
                <div class="editor-label">
                    <%= Html.LabelFor(model => model.FirstName) %>
                </div>
                <div class="editor-field">
                    <%= Html.TextBoxFor(model => model.FirstName) %>
                    <%= Html.ValidationMessageFor(model => model.FirstName) %>
                </div>
    
                <div class="editor-label">
                    <%= Html.LabelFor(model => model.LastName) %>
                </div>
                <div class="editor-field">
                    <%= Html.TextBoxFor(model => model.LastName) %>
                    <%= Html.ValidationMessageFor(model => model.LastName) %>
                </div>
    
                <div class="editor-label">
                    <%= Html.LabelFor(model => model.Age) %>
                </div>
                <div class="editor-field">
                    <%= Html.TextBoxFor(model => model.Age) %>
                    <%= Html.ValidationMessageFor(model => model.Age) %>
                </div>
    
                <p>
                    <input type="submit" value="Create" />
                </p>
            </fieldset>
    
        <% } %>
    
        <div>
            <%= Html.ActionLink("Back to List", "Index") %>
        </div>
    
    </asp:Content>
    

2 个答案:

答案 0 :(得分:5)

执行此操作的一种方法是使用MetadataTypeAttribute。此属性允许您将“伙伴”类与LINQ2SQL类相关联。 buddy类包含与原始类相同的属性,但ASP.NET MVC将从buddy类中读取验证属性。引入了MetadataTypeAttribute是因为C#不允许您添加在基类中定义的属性 - 因此您将获得错误。

以下示例是从MSDN复制的:

[MetadataType(typeof(CustomerMetaData))]
public partial class Customer
{
}

public class CustomerMetaData
{
    // Apply RequiredAttribute
    [Required(ErrorMessage = "Title is required.")]
    public object Title { get; set; }
}

修改

我不确定您的操作实施是否正确。当模型状态无效时,您希望再次显示“创建”视图。请尝试沿着这些方向尝试:

[HttpPost]
public ActionResult Create(Person person, FormCollection collection)
{
    if (ModelState.IsValid)
    {
        try
        {
            personRepository.Add(person);
            personRepository.Save();
            return RedirectToAction("Index");            
        }
        catch
        {
            return View(person);
        }
    }
    else
        return View(person);     
}

编辑2:

Linq2Sql已经为你创建了一个部分Person类,这就是应该的样子。当您创建自己的部分Person类时,编译器会将您的类定义与Linq2Sql创建的类定义合并到单个Person类。但是,两个部分类定义在同一个程序集和在同一个名称空间中非常重要。因此,请确保将部分Person类定义放在与Linq2Sql Person类相同的命名空间中。


编辑3:

我突然想到你Person_Validation课程的属性是私有的。他们需要公开。我希望有所帮助: - )

答案 1 :(得分:2)

如果您想直接在视图中使用数据模型类,

@Jakob会显示正确的方法。您可能还需要考虑将视图模型与数据模型分离,并将注释添加到视图模型中。这并不妨碍您在数据模型上使用基于元数据的验证,但它会进一步将您的视图与数据模型分离。我经常发现在我的视图中需要更多(或不同)的数据,而不是试图用非持久性数据扩展数据模型类,我发现使用单独的视图模型并在两者之间进行转换是可取的。 / p>