2010-05-03 29 views
1

有几件事我不清楚ASP.NET MV2。 在数据库中,我有表Contacts与几个字段,并且有一个其他字段XmlFields其中的类型是xml。在该字段中存储额外的描述字段。
有4类:其对应于Contact表和缺省情况下创建LINQ类时定义
ASP.NET MVC2 - 使用LINQ生成的类(验证问题)

  1. Contact
  2. ContactListView类继承 Contact类和有一些 附加属性
  3. ContactXmlView类别包含 字段XmlFields字段
  4. ContactDetailsView类 合并ContactListViewContactXmlView为一类和 这一个用来在 视图页面来显示数据

ContactListView类已经重新定义从Contact类的一些属性(这样我可以添加[Required]滤波器用于验证) - 但我得到警告消息:

'ObjectTest.Models.Contacts.ContactListView.FirstName' 皮继承成员 “SA .Model.Contact.FirstName”。如果需要隐藏,请使用 新关键字。

ContactDetailsView类在创建新联系人并将其添加到数据库时也用于表单中。

我不确定这是否是正确的方法,并且警告消息让我困惑了一下。任何建议这个?

感谢,

编辑

根据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> 

当发布新的人,没有价值观,没有任何反应(页面刚被重新加载)。以某些值发布时,人员被添加到数据库。 我不知道我在做什么错。

编辑2

我认为问题是在已生成的部分类Person LINQ。当我定义新的部分类Person,并点击它, “转到定义”,我得到以下警告:

C:\ Documents和Settings \ Korisnik \我 文档\ Visual Studio的 2008 \项目\验证\验证\ n \型号DataClasses1.designer.cs - (78,23):Validate.Models.Person

C:\ Documents和Settings \ Korisnik \我 文档\ Visual Studio的 2008 \项目\验证\验证\ Models \ 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> 
+0

我更新了我的答案,以显示如何实现您的操作方法:-) – 2010-05-03 16:53:32

+0

很难说您的代码中出现了什么问题,但实际没有看到它,但请检查我的编辑#2。 – 2010-05-05 14:57:18

+0

我不确定你是什么意思的“大会”?命名空间是相同的,但我不确定程序集是否相同。我发布了所有的代码和文件夹结构,请再次检查我的新编辑。谢谢Jakob :) – 2010-05-07 08:16:04

回答

5

一种方式做,这是使用MetadataTypeAttribute。该属性允许您将“伙伴”类与您的LINQ2SQL类相关联。好友类包含与原始类相同的属性,但ASP.NET MVC将从好友类读取验证属性。引入了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类的属性是私有的。他们需要公开。我希望这有助于:-)

+0

我试过了,但没有任何效果...我将重新编辑我的问题,所以请检查 – 2010-05-03 14:01:37

+0

不,不幸的是它不起作用:/但谢谢试图帮助:) – 2010-05-04 07:05:38

+0

我再次重新编辑,请检查。谢谢:) – 2010-05-05 13:27:47

2

@Jakob展示了如果你想直接在你的视图中使用你的数据模型类,这样做的正确方法。您可能还想考虑将视图模型从数据模型中分离出来,并将注释添加到视图模型中。这并不妨碍您在数据模型上使用基于元数据的验证,但它会进一步将您的视图与数据模型分离。我经常发现,在我的视图中需要更多(或不同)数据,而不愿意用非持久数据扩展数据模型类,我发现使用单独的视图模型并在两者之间进行转换更可取。

+0

+1不要将你的实体发送到你的视图,发送一个“视图模型”。 – mxmissile 2010-05-07 08:51:32