我有一個包含多態對象列表的ViewModel。在MVC3中綁定嵌套集合
public class InputParameters
{
public InputParameters()
{
InputPrompts = new List<IInputPrompt>();
}
public string Name { get; set; }
public string Path { get; set; }
public IList<IInputPrompt> InputPrompts { get; set; }
}
這反過來看這個:
public interface IInputPrompt
{
string Name { get; set; }
bool IsHidden { get; set; }
bool IsRequired { get; set; }
dynamic Value { get; set; }
}
public class TextPrompt : IInputPrompt
{
public string Name { get; set; }
public bool IsHidden { get; set; }
public bool IsRequired { get; set; }
public dynamic Value { get; set; }
}
public class MultiSelectPrompt : IInputPrompt
{
public string Name { get; set; }
public bool IsHidden { get; set; }
public bool IsRequired { get; set; }
public dynamic Value { get; set; }
public MultiSelectList Values
{
get
{
return new MultiSelectList(((IDictionary<int, string>)Value).ToList(), "Key", "Value");
}
}
}
有一個編輯器視圖模板爲每個派生類型,觀點看這本:
@model OptionListModelBinding.Models.InputParameters
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@using (Html.BeginForm())
{
<fieldset>
<legend><strong>@Model.Name</strong></legend>
<div><em>@Model.Path</em></div>
<div>@Html.EditorFor(p => p.InputPrompts)</div>
<div><input type="submit" /></div>
</fieldset>
}
// editor template
@model OptionListModelBinding.Models.InputParameters
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@using (Html.BeginForm())
{
<fieldset>
<legend><strong>@Model.Name</strong></legend>
<div><em>@Model.Path</em></div>
<div>@Html.EditorFor(p => p.InputPrompts)</div>
<div><input type="submit" /></div>
</fieldset>
}
// editor template
@model OptionListModelBinding.Models.MultiSelectPrompt
@{
ViewBag.Title = "MultiSelectPrompt";
}
<h2>MultiSelectPrompt</h2>
<div><strong>@Model.Name</strong></div>
<div><em>@Html.ListBox(Model.Name, Model.Values)</em></div>
這一切都呈現很好:
問題是這樣的:
我該如何將它綁定回模型?我有一個自定義模型聯編程序:(原諒這個代碼的黑客性質)。
public class InputParameterModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException("bindingContext");
}
// iterate over the form fields
foreach (string item in controllerContext.HttpContext.Request.Form.AllKeys)
{
// this is where the problem is ... I cannot use the generic here.
var dog = FromPostedData<string>(bindingContext, item);
}
InputParameters userInput = new InputParameters();
return userInput;
}
// Dino Esposito code
private T FromPostedData<T>(ModelBindingContext context, string id)
{
if (String.IsNullOrEmpty(id)) return default(T);
var key = String.Format("{0}.{1}", context.ModelName, id);
var result = context.ValueProvider.GetValue(key);
if (result == null && context.FallbackToEmptyPrefix)
{
result = context.ValueProvider.GetValue(id);
if (result == null) return default(T);
}
context.ModelState.SetModelValue(id, result);
T valueToReturn = default(T);
try
{
valueToReturn = (T)result.ConvertTo(typeof(T));
}
catch { }
return valueToReturn;
}
}
編輯 我提到的是,在列表中的項目在運行時確定?
編輯 這是報告生成工具的前端。後端服務提供可用報告的列表以及運行每個報告所需的參數。在編譯時這些都不是已知的,並且報告定義甚至可能隨着需要重新編譯的門戶網站而改變。
我可以有一個可變數量和類型的輸入參數。
你所有的類對於你的參數模型來說都是什麼樣的? –
@ErikPhilips第二個代碼塊顯示提示/參數視圖模型類。雖然在我回顧整個問題時,我似乎從我的代碼中演化出來了。 – THBBFT