Reputation: 181
I'm using Visual Studio 2015 community edition for ASP.net MVC project testing, Here is my simple model:
public class TestModel
{
[Required]
public string Name { get; set; }
[UIHint("EnumList")]
public TestState State { get; set; }
}
public enum TestState
{
eNone,
eNew,
eFinished,
}
Here is a generic html - EnumList.cshtml
@model Enum
@Html.DropDownListFor(m => m, Enum.GetValues(Model.GetType()).OfType<Enum>()
.Select(m =>
{
string enumVal = Enum.GetName(Model.GetType(), m);
return new SelectListItem()
{
Selected = (Model.ToString() == enumVal),
Text = enumVal,
Value = enumVal
};
})
)
it works fine if below is used in Test view which accepts TestModel as model.
@Html.EditorForModel()
However when I try to use above EnumList.cshtml via specific action as below:
@Html.Action("Enum", new { pState = Model.State }); <-- used in View html
// below action will be called by above method
[ChildActionOnly]
public PartialViewResult Enum(TestState? pState)
{
return PartialView("~/Views/Shared/EditorTemplates/EnumList.cshtml", pState.HasValue ? pState.Value : TestState.eNone);
}
I got following errors:
Value cannot be null or empty. Parameter name: name
below is from the stack trace:
[ArgumentException: Value cannot be null or empty.
Parameter name: name]
System.Web.Mvc.Html.SelectExtensions.SelectInternal(HtmlHelper htmlHelper, ModelMetadata metadata, String optionLabel, String name, IEnumerable1 selectList, Boolean allowMultiple, IDictionary
2 htmlAttributes) +589
System.Web.Mvc.Html.SelectExtensions.DropDownListFor(HtmlHelper1 htmlHelper, Expression
1 expression, IEnumerable1 selectList, String optionLabel, IDictionary
2 htmlAttributes) +95
System.Web.Mvc.Html.SelectExtensions.DropDownListFor(HtmlHelper1 htmlHelper, Expression
1 expression, IEnumerable`1 selectList) +60
ASP._Page_Views_Shared_EditorTemplates_EnumList_cshtml.Execute() in c:\visual studio 2015\Projects\Test\Test1\Views\Shared\EditorTemplates\EnumList.cshtml:3
System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +197
System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +105
It works if above DropDownListFor() is called directly in Test view with changes like "m => m.State", so I believe this error to do with "m => m", but what is the correct expression then?
thanks in advance.
Upvotes: 0
Views: 411
Reputation: 8781
First of all your usage of DropDownListFor is wrong (from the MSDN description of DropDownListFor helpers ):
Returns an HTML select element for each property in the object that is represented by the specified expression using the specified list items.
You are using it for the model itself and not for model properties!
Explanation why your approach works with view which accepts TestModel as model and doesn't work as a separate partial view:
By default editor templates generate id and name properties for it's inputs as a combination of parent prefix(see examples) with the current model property name. For example when you use TestModel
as the main model for your view and the use @Html.EditorForModel()
, the name and the id of you select will be State
:
<select name="State" id="State">....
If for example your TestModel
is a property of ParentTestModel
:
public class ParentTestModel
{
public TestModel TestModelProperty {get;set;}
}
Then your editor template will be rendered as
<select name="TestModelProperty.State" id="TestModelProperty_State">...
When you render a template as a partial view with Enum
as model both
m => m
expression which basically doesn't select any propertyso FullHtmlFieldName
is null
. So this code (internal implementation of SelectList helpers ) throws an exception:
private static MvcHtmlString SelectInternal(this HtmlHelper htmlHelper, ModelMetadata metadata,
string optionLabel, string name, IEnumerable<SelectListItem> selectList, bool allowMultiple,
IDictionary<string, object> htmlAttributes)
{
string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
if (String.IsNullOrEmpty(fullName))
{
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name");
} ...
Upvotes: 0