For a project at work I'm trying to create a process that lets a user dynamically create a form that other users could then fill out the values for. I'm having trouble figuring out how to go about getting this to play nice with the built in model binding and validation with ASP MVC 3, though.
Our view model is set up something like this. Please note that I've over simplified the example code:
public class Form
{
public FieldValue[] FieldValues { get; set; }
}
public class Field
{
public bool IsRequired { get; set; }
}
public class FieldValue
{
public Field Field { get; set; }
public string Value { get; set; }
}
And our view looks something like:
@model Form
@using (Html.BeginForm("Create", "Form", FormMethod.Post))
{
@for(var i = 0; i < Model.Fields.Count(); i++)
{
@Html.TextBoxFor(_ => @Model.Fields[i].Value)
}
<input type="submit" value="Save" name="Submit" />
}
I was hoping that we'd be able to create a custom ModelValidatorProvider or ModelMetadataProvider class that would be able to analyze a FieldValue instance, determine if its Field.IsRequired property is true, and then add a RequiredFieldValidator to that specific instance's validators. I'm having no luck with this, though. It seems that with ModelValidatorProvider(and ModelMetadataProvider) you can't access the parent container's value(ie: GetValidators() will be called for FieldValue.Value, but there's no way from there to get the FieldValue object).
Things I've tried:
In the ModelValidatorProvider, I've tried using ControllerContext.Controller.ViewData.Model, but that doesn't work if you have nested types. If I'm trying to figure out the validators Form.FieldValues[3], I have no idea which FieldValue to use.
I tried using a custom ModelMetadata that tries to use the internal modelAccessor's Target property to get the parent, but this also doesn't work if you have a nested type. Somewhere internal to MVC, an expression like the one in my example will result in the Target being the Model's type(Form), not FieldValue. So I get the same problem as above where I have no idea what instance of FieldValue to compare against.
A class-level validation attribute that I could put on the FieldValue class itself, but this only gets called during server validation. I need client-side validation, too.
Is what I'm trying to do even possible in MVC? Or is there something I'm missing entirely?