patterncsharpMinor
Injecting SelectList objects into ViewData to enable using EditorFor on dropdown based properties
Viewed 0 times
injectingviewdataenableobjectsdropdownpropertiesintoeditorforusingbased
Problem
I have developed a system whereby I use an attribute to state which
Now when I use the Razor markup
All my view models derive from
In my base controller, I override the
```
protected override ViewResult View(string viewNam
SelectList to use for an 'FK' property. I would appreciate some feedback mainly on by good practice, and also on any ways to do this better. Let me start my exposition with a demo view model:public class DemoModel
{
[DropDownList("LanguageSelect")]
public int? LanguageId { get; set; }
public SelectList LanguageSelect { get; set; }
}Now when I use the Razor markup
@EditorFor(m => m.LanguageId), I get a drop-down populated from the LanguageSelect list. I get this because the DropDownListAttrbute class attaches the select list name to the LanguageId model:public class DropDownListAttribute : UIHintAttribute, IMetadataAware
{
public DropDownListAttribute(string selectListName) : base(KnownUiHints.DropDown, KnownPresentationLayers.Mvc, selectListName)
{
SelectListName = selectListName;
}
public string SelectListName { get; set; }
public void OnMetadataCreated(ModelMetadata metadata)
{
var listProp = metadata.ContainerType.GetProperty(SelectListName);
metadata.AdditionalValues[KnowMetadataKeys.SelectListName] = SelectListName;
}
}All my view models derive from
ViewModel, which offers a SelectListDictionary property:private IDictionary _selectListdictionary;
public virtual IDictionary SelectListDictionary
{
get
{
if (_selectListdictionary == null)
{
var props = GetType().GetProperties().Where(p => p.PropertyType == typeof(SelectList));
_selectListdictionary = props.ToDictionary(prop => prop.Name, prop => (SelectList)prop.GetValue(this, null));
}
return _selectListdictionary;
}
}In my base controller, I override the
View method to pull the entire select list dictionary from the view model, and insert it into the view's viewdata, making it available for the editor template:```
protected override ViewResult View(string viewNam
Solution
I'm assuming this code hasn't been reviewed yet because it's... beautiful - and I'm still searching for a better word. I mean, wow that's clever, I want that!!
The only thing I can see here, is in the
I would suggest a safe cast instead of
Other than that, I agree with your naming (except maybe
The only thing I can see here, is in the
View method:protected override ViewResult View(string viewName, string masterName, object model)
{
var result = base.View(viewName, masterName, model);
if ((model is ViewModel) && (!ViewData.ContainsKey(KnowMetadataKeys.ViewDataSelectLists)))
{
var vm = (ViewModel)model;
result.ViewData.Add(KnowMetadataKeys.ViewDataSelectLists, vm.SelectListDictionary);
}
return result;
}I would suggest a safe cast instead of
model is ViewModel followed by a cast, so it would look more like this - note that I dropped a few redundant parentheses:protected override ViewResult View(string viewName, string masterName, object model)
{
var result = base.View(viewName, masterName, model);
var vm = model as ViewModel;
if (vm != null && !ViewData.ContainsKey(KnowMetadataKeys.ViewDataSelectLists))
{
result.ViewData.Add(KnowMetadataKeys.ViewDataSelectLists, vm.SelectListDictionary);
}
return result;
}Other than that, I agree with your naming (except maybe
vm could be called viewModel, but vm is pretty descriptive in this specific context) and naming conventions, and there's nothing much left to say as far as I'm concerned - good job! :)Code Snippets
protected override ViewResult View(string viewName, string masterName, object model)
{
var result = base.View(viewName, masterName, model);
if ((model is ViewModel) && (!ViewData.ContainsKey(KnowMetadataKeys.ViewDataSelectLists)))
{
var vm = (ViewModel)model;
result.ViewData.Add(KnowMetadataKeys.ViewDataSelectLists, vm.SelectListDictionary);
}
return result;
}protected override ViewResult View(string viewName, string masterName, object model)
{
var result = base.View(viewName, masterName, model);
var vm = model as ViewModel;
if (vm != null && !ViewData.ContainsKey(KnowMetadataKeys.ViewDataSelectLists))
{
result.ViewData.Add(KnowMetadataKeys.ViewDataSelectLists, vm.SelectListDictionary);
}
return result;
}Context
StackExchange Code Review Q#23897, answer score: 6
Revisions (0)
No revisions yet.