One way to do this is to create your own ModelBinder
which would be at the heart of your generated forms. A modelbinder is responsible for validating the ModelState
and rebuilding the typed ViewDataModel
(assuming your views are typed).
The DataAnnotations model binder could be a good reference for this what this custom modelbinder allows you to do is via Attributes
on your ViewDataModel
describe the attribute's validation (and hint at UI rendering). However this is all defined compile time but would be a great reference to start off writing a custom modelbinder.
In your case your model binder should get the validation for a field at runtime from an xml file/string.
If you have a route like:
routes.MapRoute(null, "Forms/{formName}/", new { action = "Index", controller = "Forms", formName = ""}),
Then you could locate the correct form xml in FormsController.Index(string formName)
and pass it to the view.
The FormsModel
should hold all the possible methods to get data I dont see any other way around this. The Xml could map to a function name (possibly even arguments) that you can invoke using reflection on the FormsModel
to fill the ViewData
or typed ViewDataModel
with data.
The view for Form Index could generate a form from that xml through an HtmlHelper
Extension that takes an XmlDocument
.
Then when you (or asp.net mvc) binds your form to your ViewData
your custom model binder is invoked it can inspect the current controller values to look for the formName and look up the corresponding xml that holds all the validation rules. The ModelBinder
is then responsible for filling up ModelState
with any runtime defined errors.
It's a hard task but when pulled off succesfully well worth it in my view :)
Update a better alternative to model data would be a very loose database schema as David Liddle suggests. I'd still go through the trouble of saving it as xml (or someother serialized format) and using that for generating the view and to hold validation rules for a custom ModelBinder
so that you have more control on layout and validation of each field.