我正在研究的一個項目的關鍵特性之一是用戶可以基於預先存在的字段類型池(衆所周知的類型,類型和類型)來配置表單(如在「表單」中填充)例如「用戶名」,「出生日期」等,還包括「字符串」,「日期時間」等「通用類型」)。如何將MetaData添加到動態構建MVC3 ViewModel?
我們曾經有一個運行良好的「衆所周知」的類型,看起來像這樣的靜態視圖模型:
public class UserInputModel
{
[StringLength(200)]
public string Name { get; set; }
[Required(ErrorMessageResourceName = "BirthDateEmptyError", ErrorMessageResourceType = typeof(Resources.ErrorMessages))]
public DateTime BirthDate { get; set; }
//Here comes a lot of other properties
}
所有已知的性能進行了上市,我們被顯示或隱藏他們給出的上下文。
但最後的要求來了,並改變了這一切。用戶現在應該能夠添加儘可能多的泛型類型字段。爲了做到這一點,我們決定讓這個InputModel完全動態化。它現在看起來像這樣:
public class UserInputModel
{
// Each ModelProperty has an "Id" and a "Value" property
public ICollection<ModelProperty> Properties { get; set; }
}
這工作就像一個魅力。剃刀視圖只需要遍歷集合,創建相應的控件集合的每個屬性在超過標準的方式:
@Html.TextBoxFor(m => m.Properties[index].Value);
...我們很好地取回數據作爲填好的表格。
=>這工作正常,但我們沒有任何客戶端驗證。爲此,我們需要一些元數據......這是我們沒有通過註釋了,因爲我們正在動態創建模型。
爲了提供這些元數據,我創建了一個CustomModelMetadataProvider
,它繼承自DataAnnotationsModelMetadataProvider
,並在Global.asax中將其註冊爲新的ModelMetadataProvider
。在創建ViewModel時調用CreateMetadata()
函數,並且對於ViewModel的每個屬性...都非常好。
問題開始的地方:爲了向當前屬性添加一些元數據,我首先需要確定我目前正在查看哪個屬性(「Name」的最大長度爲200,「出生日期」hasn所以我不能爲每個屬性默認分配最大長度)。還有一些人,我沒有設法做到這一點,因爲所有的財產都有相同的名稱Value
和相同的容器類型ModelProperty
。
我嘗試訪問通過反射屬性的容器,但自從ModelAccessor的目標是視圖模型本身(因爲lambda表達式m => m.Properties
的),下面的結構給我的視圖模型作爲一個整體,而不僅僅是ModelProperty:
var container = modelAccessor.Target.GetType().GetField("container");
var containerObject = (UserInputModel)container.GetValue(modelAccessor.Target);
我一直在翻轉這一遍又一遍,但無法找到一種方法來確定我手中有哪些ModelProperty。有沒有辦法做到這一點?
更新:經過一段時間翻轉了所有可能的方向之後,我們終於找到了另一條路。我們基本上使用unobstrusive javascript來使用MVC的驗證功能,而無需觸及屬性或元數據。簡而言之,我們將HTML屬性添加到@Html.TextBoxFor()
語句中,如value-data="true"
(以及所有其他必需的屬性)。這對於所有的原子驗證(需要的,stringlength等)都非常有用。
感謝您的回答,不幸的是 - 除非我誤解了你 - 我認爲你錯過了這一點。整個問題本身不是驗證,而是注入屬性的元數據。 –