我有以下與一對多關係相關的模型類。這些類通過代碼優先的方法一直持續到SQL Server數據庫:在創建時預定義實體值
public class Topic
{
[Key]
public int Id { get; set; }
[InverseProperty("Topic")]
public virtual IList<Chapter> Chapters { get; set; }
//some other properties...
}
public class Chapter : IValidatableObject
{
[Key]
public int Id { get; set; }
[Required]
public string Key { get; set }
public virtual Topic Topic { get; set; }
//some other properties...
}
每個Topic
包含了一堆。每個Chapter
都有一個Key
,它的Topic
必須是唯一的。
我試圖用下面的方法來驗證這一點:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var chaptersWithSameKey = Topic.Chapters.Where(t => t.Key == Key);
foreach (var item in chaptersWithSameKey)
{
if (item.Id != Id)
{
yield return new ValidationResult("The key must be unique.", new string[] { "Key" });
break;
}
}
}
然而,Topic
總是null
在驗證發佈到創建或編輯動作之後發生。這似乎是合理的,因爲視圖不包含有關Topic
的信息。但是,我可以在控制器中提取主題,因爲主題的ID是URL的一部分。
我第一次嘗試是設定在文章的開頭的話題就在控制器創建行動:
[HttpPost]
public ActionResult Create(int topicId, Chapter chapter)
{
var topic = db.Topics.Find(topicId);
if (topic == null)
return HttpNotFound();
chapter.Topic = topic;
if(ModelState.IsValid)
...
}
然而,本章的Validate
方法被調用之前控制器可以做任何事情。因此,本章的主題是null
。
另一種方法就是告訴創建視圖它屬於什麼話題由:
[HttpGet]
public ActionResult Create(int topicId)
{
var topic = ...
var newChapter = new Chapter() { Topic = topic };
return View(newChapter);
}
,併成立了一個隱藏字段中的觀點:
@Html.HiddenFor(model => model.Topic)
@Html.HiddenFor(model => model.Topic.Id)
第一個給出了null
話題像之前一樣。這似乎很自然,因爲呈現的隱藏字段的值只是主題的ToString()
結果。
第二個似乎試圖驗證主題,但因爲缺少屬性而失敗。當Topic
的只讀屬性嘗試評估另一個null
屬性時,實際原因是NullReferenceException
。我不知道爲什麼只讀屬性被訪問。調用堆棧有一些Validate...
方法。
那麼上述場景的最佳解決方案是什麼?我試圖在模型中進行驗證,但是缺少一些可能在控制器中檢索到的必要值。
我可以爲此任務創建視圖模型,其中包含int TopicId
而不是Topic Topic
。但是之後我必須將每個屬性和註解複製到視圖模型或通過繼承來完成。第一種方法似乎相當低效。
所以到現在爲止,繼承方法可能是最好的選擇。但是有沒有其他的選擇不需要引入額外的類型呢?
如果'Topic'爲空,爲什麼不是在'Topic.Chapters.Where'處引發'NullReferenceException'? – haim770
@ haim770是的,當然。我認爲這很明顯。 –