How can I validate the result in an ASP.NET MVC editor template?
-
23-09-2019 - |
문제
I have created an editor template for representing selecting from a dynamic dropdown list and it works as it should except for validation, which I have been unable to figure out. If the model has the [Required]
attribute set, I want that to invalidate if the default option is selected.
The view model object that must be represented as the dropdown list is Selector
:
public class Selector
{
public int SelectedId { get; set; }
public IEnumerable<Pair<int, string>> Choices { get; private set; }
public string DefaultValue { get; set; }
public Selector()
{
//For binding the object on Post
}
public Selector(IEnumerable<Pair<int, string>> choices, string defaultValue)
{
DefaultValue = defaultValue;
Choices = choices;
}
}
The editor template looks like this:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<select class="template-selector" id="<%= ViewData.ModelMetadata.PropertyName %>.SelectedId" name="<%= ViewData.ModelMetadata.PropertyName %>.SelectedId">
<%
var model = ViewData.ModelMetadata.Model as QASW.Web.Mvc.Selector;
if (model != null)
{
%>
<option><%= model.DefaultValue %></option><%
foreach (var choice in model.Choices)
{
%>
<option value="<%= choice.Value1 %>"><%= choice.Value2 %></option><%
}
}
%>
</select>
I sort of got it to work by calling it from the view like this (where Category
is a Selector
):
<%= Html.ValidationMessageFor(n => n.Category.SelectedId)%>
But it shows the validation error for not supplying a proper number and it does not care if I set the Required
attribute.
해결책
I found a solution where validation is done against hidden fields using custom validation rules, here. Using this approach you can easily add custom validation to arbitrary types.
다른 팁
Why is not your editor template strongly typed?
<%@ Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<QASW.Web.Mvc.Selector>" %>
Why not use the DropDownListFor helper:
<%= Html.DropDownListFor(
x => x.SelectedId,
new SelectList(Model.Choices, "Value1", "Value2")
)%>
To avoid the magic strings you could add a ChoicesList property to your view model:
public IEnumerable<SelectListItem> ChoicesList
{
get
{
return Choices.Select(x => new SelectListItem
{
Value = x.Value1.ToString(),
Text = x.Value2
});
}
}
and bind your helper to it:
<%= Html.DropDownListFor(x => x.SelectedId, Model.ChoicesList) %>