Problem
I have a list of fields that the user can edit. When the model is submitted I want to check if this items are valid. I can't use data notations because each field has a different validation process that I will not know until runtime. If the validation fails I use the ModelState.AddModelError(string key, string error)
where the key is the name of the html element you want to add the error message to. Since there are a list of fields the name that Razor generates for the html item is like Fields[0].DisplayName
. My question is there a method or a way to get the key of the generated html name from the view model?
Attempted Solution
I tried the toString()
method for the key with no luck. I also looked through the HtmlHelper
class but I didn't see any helpful methods.
Code Snippet
View Model
public class CreateFieldsModel
{
public TemplateCreateFieldsModel()
{
FreeFields = new List<FieldModel>();
}
[HiddenInput(DisplayValue=false)]
public int ID { get; set; }
public IList<TemplateFieldModel> FreeFields { get; set; }
public class TemplateFieldModel
{
[Display(Name="Dispay Name")]
public string DisplayName { get; set; }
[Required]
[Display(Name="Field")]
public int FieldTypeID { get; set; }
}
}
Controller
public ActionResult CreateFields(CreateFieldsModel model)
{
if (!ModelState.IsValid)
{
//Where do I get the key from the view model?
ModelState.AddModelError(model.FreeFields[0], "Test Error");
return View(model);
}
}
After digging around in the source code I have found the solution. There is a class called ExpressionHelper
that is used to generate the html name for the field when EditorFor()
is called. The ExpressionHelper
class has a method called GetExpressionText()
that returns a string that is the name of that html element. Here is how to use it ...
for (int i = 0; i < model.FreeFields.Count(); i++)
{
//Generate the expression for the item
Expression<Func<CreateFieldsModel, string>> expression = x => x.FreeFields[i].Value;
//Get the name of our html input item
string key = ExpressionHelper.GetExpressionText(expression);
//Add an error message to that item
ModelState.AddModelError(key, "Error!");
}
if (!ModelState.IsValid)
{
return View(model);
}