MVC3 EnumDropdownList selected value - c#

There are some helpful extension methods for using displaying enums in dropdown lists. For example here and here.
But there is one problem that I encounter, which is that these helpers do not work if the enum is decorated with the Description attribute. The first example works perfectly with the Description attribute, but it doesn't set the selected value. The second example sets the selected value, but it doesn't use the description attribute. So I need to combine both methods into a working helper that does both correctly. I've a lot of variations to get it working but, no success so far. I've tried several ways to create a selectlist, but somehow it ignores the Selected property. In all my tests, the Selected property was set to true on one item, but this property is just ignored.
So any ideas are most welcome!
This is the latest code that I've tried:
public static IEnumerable<SelectListItem> ToSelectList(Type enumType, string selectedItem)
{
List<SelectListItem> items = new List<SelectListItem>();
foreach (var item in Enum.GetValues(enumType))
{
FieldInfo fi = enumType.GetField(item.ToString());
var attribute = fi.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault();
var title = attribute == null ? item.ToString() : ((DescriptionAttribute)attribute).Description;
var listItem = new SelectListItem
{
Value = ((int)item).ToString(),
Text = title,
Selected = selectedItem == item.ToString()
};
items.Add(listItem);
}
return items;
}
public static HtmlString EnumDropDownList2For<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> modelExpression)
{
var typeOfProperty = modelExpression.ReturnType;
if (!typeOfProperty.IsEnum)
throw new ArgumentException(string.Format("Type {0} is not an enum", typeOfProperty));
var value = htmlHelper.ViewData.Model == null
? default(TProperty)
: modelExpression.Compile()(htmlHelper.ViewData.Model);
return htmlHelper.DropDownListFor(modelExpression, ToSelectList(modelExpression.ReturnType, value.ToString()));
}

I had the same issue with enums which actually had custom value set
public enum Occupation
{
[Description("Lorry driver")] LorryDriver = 10,
[Description("The big boss")] Director = 11,
[Description("Assistant manager")] AssistantManager = 12
}
What I found is that when I use DropDownListFor(), it doesn't use the selected item from the SelectListItem collection to set the selected option. Instead it selects an option with a value which equals to the property I'm trying to bind to (m => m.Occupation) and for this it uses the enum's .ToString() not the enum's actual integer value. So what I ended up with is setting the SelectListItem's Value like so:
var listItem = new SelectListItem
{
Value = item.ToString(), // use item.ToString() instead
Text = title,
Selected = selectedItem == item.ToString() // <- no need for this
};
The helper method:
public static class SelectListItemsForHelper
{
public static IEnumerable<SelectListItem> SelectListItemsFor<T>(T selected) where T : struct
{
Type t = typeof(T);
if (t.IsEnum)
{
return Enum.GetValues(t).Cast<Enum>().Select(e => new SelectListItem { Value = e.ToString(), Text = e.GetDescription() });
}
return null;
}
public static string GetDescription<TEnum>(this TEnum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
if (fi != null)
{
var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
return attributes[0].Description;
}
return value.ToString();
}
}
In the view:
#Html.DropDownListFor(m => m.Occupation, SelectListItemsForHelper.SelectListItemsFor(Model.Occupation), String.Empty)

To summarize the solution that does work (at least for me):
I use the following set of helper methods
public static IEnumerable<SelectListItem> ToSelectList(Type enumType, string selectedItem)
{
List<SelectListItem> items = new List<SelectListItem>();
foreach (var item in Enum.GetValues(enumType))
{
var title = item.GetDescription();
var listItem = new SelectListItem
{
Value = item.ToString(),
Text = title,
Selected = selectedItem == item.ToString()
};
items.Add(listItem);
}
return items;
}
public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) where TModel : class
{
string inputName = GetInputName(expression);
var value = htmlHelper.ViewData.Model == null
? default(TProperty)
: expression.Compile()(htmlHelper.ViewData.Model);
return htmlHelper.DropDownList(inputName, ToSelectList(typeof(TProperty), value.ToString()));
}
public static string GetInputName<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
{
if (expression.Body.NodeType == ExpressionType.Call)
{
MethodCallExpression methodCallExpression = (MethodCallExpression)expression.Body;
string name = GetInputName(methodCallExpression);
return name.Substring(expression.Parameters[0].Name.Length + 1);
}
return expression.Body.ToString().Substring(expression.Parameters[0].Name.Length + 1);
}
private static string GetInputName(MethodCallExpression expression)
{
MethodCallExpression methodCallExpression = expression.Object as MethodCallExpression;
if (methodCallExpression != null)
{
return GetInputName(methodCallExpression);
}
return expression.Object.ToString();
}
Usage:
#Html.EnumDropDownListFor(m => m.MyEnumType)
This works for enums with or without a description attribute, and sets the correct selected value.

Related

Create dropdown list for enum with description C#

I want to create a dropdown list using description of enum instead of its value.
I'd like to know how to get descriptions instead of values in the following code which creates a dropdown list for enum :
public static MvcHtmlString DropDownListForEnum<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
{
// get expression property description
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
IEnumerable<TEnum> values = Enum.GetValues(typeof(TEnum)).Cast<TEnum>();
IEnumerable<SelectListItem> items =
values.Select(value => new SelectListItem
{
Text = value.ToString(),
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
});
return htmlHelper.DropDownListFor(
expression,
items
);
}
First, make a new method to get the description like shown below:
public static string GetDescription<T>(string value)
{
Type type = typeof(T);
if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = Nullable.GetUnderlyingType(type);
}
T enumerator = (T)Enum.Parse(type, value);
FieldInfo fi = enumerator.GetType().GetField(enumerator.ToString());
DescriptionAttribute[] attributtes =
(DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributtes != null && attributtes.Length > 0)
return attributtes[0].Description;
else
return enumerator.ToString();
}
And then use it in your helper:
public static MvcHtmlString DropDownListForEnum<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
{
// get expression property description
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
IEnumerable<TEnum> values = Enum.GetValues(typeof(TEnum)).Cast<TEnum>();
IEnumerable<SelectListItem> items =
values.Select(value => new SelectListItem
{
Text = value.ToString(),
Value = GetDescription<TEnum>(value.ToString()),
Selected = value.Equals(metadata.Model)
});
return htmlHelper.DropDownListFor(
expression,
items
);
}
Use Enum getnames to get the names
http://msdn.microsoft.com/en-us/library/system.enum.getnames(v=vs.110).aspx

Access Enum custom attributes whilst looping over values

I have added a custom attribute to some enum values (to give them a screen friendly string value). I am trying to build a list of SelectListItems for use on an MVC page, but I am running into trouble accessing the custom attribute.
My enum looks like this.
public enum MyEnum
{
[StringValue("None")] None = 0,
[StringValue("First Value")] FirstValue = 1,
[StringValue("Second Value")] SecondValue = 2
}
The attribute looks like this.
public class StringValueAttribute : Attribute
{
public StringValueAttribute(string value)
{
this.StringValue = value;
}
public string StringValue { get; protected set; }
}
I created a helper class so that I can easily access the StringValue attribute from an instance of the Enum.
public static string GetStringValue(this Enum value)
{
Type type = value.GetType();
FieldInfo fieldInfo = type.GetField(value.ToString());
StringValueAttribute[] attribs = fieldInfo.GetCustomAttributes(typeof(StringValueAttribute), false) as StringValueAttribute[];
return attribs != null && attribs.Length > 0 ? attribs[0].StringValue : null;
}
I could call it like this.
MyEnum test = MyEnum.FirstValue;
string stringValue = test.GetStringValue();
Finally, onto the code I am stuck with. I can loop over the Enum Values easily, but the values are not instances of MyEnum so I cannot call my helper function. And when I try to access the FieldInfo it always returns null. Here is what I have so far.
public static List<SelectListItem> GetFlagsSelectList<T>(int? selectedValue)
{
List<SelectListItem> items = new List<SelectListItem>();
foreach (int value in Enum.GetValues(typeof(T)))
{
items.Add(new SelectListItem
{
Text = Enum.GetName(typeof(T), value),
Value = value.ToString(),
Selected = selectedValue.HasValue && selectedValue.Value == value
});
}
return items;
}
Is it possible to access the custom attribute within the foreach loop?
EDIT:
I think I asked this unclearly. I would like to access the custom attribute inside the foreach loop. Calling Enum.GetName(typeof(T), value) simply returns the name of the property (e.g. FirstValue) which I do NOT want.
I would like to do something like:
foreach (int value in Enum.GetValues(typeof(T)))
{
string name = Enum.ToObject(typeof (T), value).GetStringValue();
}
But T could be any type so I can't call my GetStringValue() method there.
I have tried doing this:
foreach (int value in Enum.GetValues(typeof(T)))
{
FieldInfo fieldInfo = typeof(T).GetField(value.ToString());
StringValueAttribute[] attribs = fieldInfo.GetCustomAttributes(typeof(StringValueAttribute), false) as StringValueAttribute[];
string name = attribs != null && attribs.Length > 0 ? attribs[0].StringValue : Enum.GetName(typeof(T), value),;
items.Add(new SelectListItem
{
Text = name,
Value = value.ToString(),
Selected = selectedValue.HasValue && selectedValue.Value == value
});
}
But I always get an exception because the FieldInfo object always returns null.
Try
static string GetStringValue2(Enum value) {
....
}
public static List<SelectListItem> GetFlagsSelectList<T>(int? selectedValue) where T : struct {
var items = new List<SelectListItem>();
foreach (T value in Enum.GetValues(typeof(T))) {
var stringValue = GetStringValue2((Enum)(object)value);
items.Add(new SelectListItem {
Text = Enum.GetName(typeof(T), value),
Value = Convert.ToInt32(value).ToString(),
Selected = selectedValue.HasValue && selectedValue.Value == Convert.ToInt32(value)
});
}
return items;
}
I wrote a blog post about this a while back (for the XmlEnumAttribute, but the same applies here).
public static string ConvertToString(Enum e)
{
// Get the Type of the enum
Type t = e.GetType();
// Get the FieldInfo for the member field with the enums name
FieldInfo info = t.GetField(e.ToString("G"));
// Check to see if the XmlEnumAttribute is defined on this field
if (!info.IsDefined(typeof(XmlEnumAttribute), false))
{
// If no XmlEnumAttribute then return the string version of the enum.
return e.ToString("G");
}
// Get the XmlEnumAttribute
object[] o = info.GetCustomAttributes(typeof(XmlEnumAttribute), false);
XmlEnumAttribute att = (XmlEnumAttribute)o[0];
return att.Name;
}
Hope that helps.

ListFor enum flags MVC.Net

My model contains an enum with a flags attribute
[Flags()]
public enum InvestmentAmount
{
[Description("£500 - £5,000")]
ZeroToFiveThousand,
[Description("£5,000 - £10,000")]
FiveThousandToTenThousand,
//Deleted remaining entries for size
}
I want to be able to display this in my view as a multiselectable List box.
Obviously the current helper for Listfor() doesn't support enums.
I've tried rolling my own but just receive
The parameter 'expression' must evaluate to an IEnumerable when
multiple selection is allowed.
when it executes.
public static MvcHtmlString EnumListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Type enumType = GetNonNullableModelType(metadata);
IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();
IEnumerable<SelectListItem> items = from value in values
select new SelectListItem
{
Text = GetEnumDescription(value),
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
};
// If the enum is nullable, add an 'empty' item to the collection
if (metadata.IsNullableValueType)
items = SingleEmptyItem.Concat(items);
RouteValueDictionary htmlattr = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
//htmlattr.Add("multiple", "multiple");
if (expression.GetDescription() != null)
{
htmlattr.Add("data-content", expression.GetDescription());
htmlattr.Add("data-original-title", expression.GetTitle());
htmlattr["class"] = "guidance " + htmlattr["class"];
}
var fieldName = htmlHelper.NameFor(expression).ToString();
return htmlHelper.ListBox(fieldName, items, htmlattr); //Exception thrown here
}
Check out my blog post on a helper method I created to do just this:
http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c%23
This enables you to do something like this:
//If you don't have an enum value use the type
var enumList = EnumHelper.SelectListFor<MyEnum>();
//If you do have an enum value use the value (the value will be marked as selected)
var enumList = EnumHelper.SelectListFor(myEnumValue);
...which you can then use to build your multi list.
The helper class is as follows:
public static class EnumHelper
{
//Creates a SelectList for a nullable enum value
public static SelectList SelectListFor<T>(T? selected)
where T : struct
{
return selected == null ? SelectListFor<T>()
: SelectListFor(selected.Value);
}
//Creates a SelectList for an enum type
public static SelectList SelectListFor<T>() where T : struct
{
Type t = typeof (T);
if (t.IsEnum)
{
var values = Enum.GetValues(typeof(T)).Cast<enum>()
.Select(e => new { Id = Convert.ToInt32(e), Name = e.GetDescription() });
return new SelectList(values, "Id", "Name");
}
return null;
}
//Creates a SelectList for an enum value
public static SelectList SelectListFor<T>(T selected) where T : struct
{
Type t = typeof(T);
if (t.IsEnum)
{
var values = Enum.GetValues(t).Cast<Enum>()
.Select(e => new { Id = Convert.ToInt32(e), Name = e.GetDescription() });
return new SelectList(values, "Id", "Name", Convert.ToInt32(selected));
}
return null;
}
// Get the value of the description attribute if the
// enum has one, otherwise use the value.
public static string GetDescription<TEnum>(this TEnum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
if (fi != null)
{
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute),
false);
if (attributes.Length > 0)
{
return attributes[0].Description;
}
}
return value.ToString();
}
}
The error appears to have been occurring because I was binding to just an "InvestmentAmount" where as it appears that ListFor checks if the model is a list.
I've had to change my model to a List and build in binding logic (Through AutoMapper) to convert from the flagged Enum to a List and back.
A nicer solution would be to create a generic HTML ListFor helper to do it. Which is the way I'll tackle it if I need it any more than once.

Display enum in dropdown with Html.DropdownListFor

in a model file I have
public enum Title
{
Ms,
Mrs,
Mr
}
I would like to display on the register form's downdown box these selectable values.
But I don't know how. It doesn't necessarily require me to use an enum, provided those titles could be in use with dropdownlistfor, please you can suggest me any methods. Thank you.
you can bind it like this
ddl.DataSource = Enum.GetNames(typeof(Title));
ddl.DataBind();
if you want to get the selected value as well do the following
Title enumTitle = (Title)Enum.Parse(ddl.SelectedValue);
There are a couple of methods to this.
One is to create a method that returns a select list.
private static SelectList ToSelectList(Type enumType, string selectedItem)
{
var items = new List<SelectListItem>();
foreach (var item in Enum.GetValues(enumType))
{
var title = ((Enum)item).GetDescription();
var listItem = new SelectListItem
{
Value = ((int)item).ToString(),
Text = title,
Selected = selectedItem == item.ToString()
};
items.Add(listItem);
}
return new SelectList(items, "Value", "Text");
}
The second method is to create helper method
public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, string optionLabel, object htmlAttributes)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Type enumType = GetNonNullableModelType(metadata);
IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();
IEnumerable<SelectListItem> items = from value in values
select new SelectListItem
{
Text = GetEnumDescription(value),
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
};
// If the enum is nullable, add an 'empty' item to the collection
if (metadata.IsNullableValueType)
{
items = SingleEmptyItem.Concat(items);
}
return htmlHelper.DropDownListFor(expression, items, optionLabel, htmlAttributes);
}
public static string GetEnumDescription<TEnum>(TEnum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if ((attributes != null) && (attributes.Length > 0))
{
return attributes[0].Description;
}
return value.ToString();
}
I use a combination of things. First off, here's an extension method for Enums to get all enum items in a collection from an enum type:
public static class EnumUtil
{
public static IEnumerable<T> GetEnumValuesFor<T>()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
}
Then, I have some code to turn a List into a List. You can indicate which of the values you are passing in are already Selected (just 1 for a Dropdown list, but you can use this to power a CheckBoxList as well), as well has indicating ones to exclude too, if necessary.
public static List<SelectListItem> GetEnumsByType<T>(bool useFriendlyName = false, List<T> exclude = null,
List<T> eachSelected = null, bool useIntValue = true) where T : struct, IConvertible
{
var enumList = from enumItem in EnumUtil.GetEnumValuesFor<T>()
where (exclude == null || !exclude.Contains(enumItem))
select enumItem;
var list = new List<SelectListItem>();
foreach (var item in enumList)
{
var selItem = new SelectListItem();
selItem.Text = (useFriendlyName) ? item.ToFriendlyString() : item.ToString();
selItem.Value = (useIntValue) ? item.To<int>().ToString() : item.ToString();
if (eachSelected != null && eachSelected.Contains(item))
selItem.Selected = true;
list.Add(selItem);
}
return list;
}
public static List<SelectListItem> GetEnumsByType<T>(T selected, bool useFriendlyName = false, List<T> exclude = null,
bool useIntValue = true) where T : struct, IConvertible
{
return GetEnumsByType<T>(
useFriendlyName: useFriendlyName,
exclude: exclude,
eachSelected: new List<T> { selected },
useIntValue: useIntValue
);
}
And then in my View Model, when I need to fill a DropdownList, I can just grab the List from that helper method like so:
public class AddressModel
{
public enum OverrideCode
{
N,
Y,
}
public List<SelectListItem> OverrideCodeChoices { get {
return SelectListGenerator.GetEnumsByType<OverrideCode>();
} }
}
A little late but you can just use the Html helpers:
#Html.GetEnumSelectList<Title>()

TryUpdateModel Not Working with Prefix and IncludeProperties

Hi i have an entity called User with 2 properties called UserName and Role (which is a reference to another entity called Role). I'm trying to update the UserName and RoleID from a form which is posted back. Within my postback action i have the following code:
var user = new User();
TryUpdateModel(user, "User", new string[] { "UserName, Role.RoleID" });
TryUpdateModel(user, new string[] { "User.UserName, User.Role.RoleID" });
However none of these updates the Role.RoleID property. If i try the following:
TryUpdateModel(user, "User", new string[] { "UserName, Role" });
TryUpdateModel(user);
The RoleID is updated but the RoleName property is validated aswell. That's why i'm trying to be more specific on which properties to update but i can't get any of the first examples to work.
I'd appreciate if someone could help. Thanks
Here's a complete solution to work with any relationship.
First place the following line of code in your Application_Start event:
ModelBinders.Binders.DefaultBinder = new CustomModelBinder();
Now you need to add the following class somewhere in your application:
public class CustomModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (bindingContext.ModelType.Namespace.EndsWith("Models.Entities") && !bindingContext.ModelType.IsEnum && value != null)
{
if (Utilities.IsInteger(value.AttemptedValue))
{
var repository = ServiceLocator.Current.GetInstance(typeof(IRepository<>).MakeGenericType(bindingContext.ModelType));
return repository.GetType().InvokeMember("GetByID", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public, null, repository, new object[] { Convert.ToInt32(value.AttemptedValue) });
}
else if (value.AttemptedValue == "")
return null;
}
return base.BindModel(controllerContext, bindingContext);
}
}
Please note the above code may need to be modified to suit your needs. It affectively calls IRepository().GetByID(???). It will work when binding against any entities within the Models.Entities namespace and that have an integer value.
Now for the view there's one other bit of work you have to do to fix a bug in ASP.NET MVC 2. By default the Selected property on a SelectListItem is ignored so i have come up with my own DropDownListFor which allows you to pass in the selected value.
public static class SelectExtensions
{
public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string selectedValue, string optionLabel)
{
return DropDownListFor(helper, expression, selectList, selectedValue, optionLabel, null);
}
public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string selectedValue, string optionLabel, object htmlAttributes)
{
return DropDownListHelper(helper, ExpressionHelper.GetExpressionText(expression), selectList, selectedValue, optionLabel, new RouteValueDictionary(htmlAttributes));
}
/// <summary>
/// This is almost identical to the one in ASP.NET MVC 2 however it removes the default values stuff so that the Selected property of the SelectListItem class actually works
/// </summary>
private static MvcHtmlString DropDownListHelper(HtmlHelper helper, string name, IEnumerable<SelectListItem> selectList, string selectedValue, string optionLabel, IDictionary<string, object> htmlAttributes)
{
name = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
// Convert each ListItem to an option tag
var listItemBuilder = new StringBuilder();
// Make optionLabel the first item that gets rendered
if (optionLabel != null)
listItemBuilder.AppendLine(ListItemToOption(new SelectListItem() { Text = optionLabel, Value = String.Empty, Selected = false }, selectedValue));
// Add the other options
foreach (var item in selectList)
{
listItemBuilder.AppendLine(ListItemToOption(item, selectedValue));
}
// Now add the select tag
var tag = new TagBuilder("select") { InnerHtml = listItemBuilder.ToString() };
tag.MergeAttributes(htmlAttributes);
tag.MergeAttribute("name", name, true);
tag.GenerateId(name);
// If there are any errors for a named field, we add the css attribute
ModelState modelState;
if (helper.ViewData.ModelState.TryGetValue(name, out modelState))
{
if (modelState.Errors.Count > 0)
tag.AddCssClass(HtmlHelper.ValidationInputCssClassName);
}
return tag.ToMvcHtmlString(TagRenderMode.Normal);
}
internal static string ListItemToOption(SelectListItem item, string selectedValue)
{
var tag = new TagBuilder("option") { InnerHtml = HttpUtility.HtmlEncode(item.Text) };
if (item.Value != null)
tag.Attributes["value"] = item.Value;
if ((!string.IsNullOrEmpty(selectedValue) && item.Value == selectedValue) || item.Selected)
tag.Attributes["selected"] = "selected";
return tag.ToString(TagRenderMode.Normal);
}
}
Now within your view you can say:
<%= Html.DropDownListFor(m => m.User.Role, Model.Roles, Model.User.Role != null ? Model.User.Role.RoleID.ToString() : "", "-- Please Select --")%>
<%= Html.ValidationMessageFor(m => m.User.Role, "*")%>
The Role property will automatically update when you call TryUpdateModel in your controller and you have to do no additional work to wire this up. Although it's alot of code initially i've found this approach saves heaps of code in the long term.
Hope this helps.
Consider calling TryUpdateModel twice, once for the User. Once for the Role. Then assign the role to the user.
var user = new User();
var role = new Role();
TryUpdateModel(user, new string[] { "UserName" });
TryUpdateModel(role, new string[] { "RoleID" });
user.Role = role;
See if that works.

Categories

Resources