Advice with Dynamic Forms in ASP.NET MVC

前端 未结 4 1735
隐瞒了意图╮
隐瞒了意图╮ 2021-02-06 03:34

I am working on rendering a dynamic form in an ASP.NET MVC view that will meet these requirements:

  • Fields can be validated
  • State is preserved when the for
相关标签:
4条回答
  • 2021-02-06 03:40

    How dynamic are your field definitions? If they dont change very often you could use code dom to generate the model and controller once the definition is created. I have not tried this in ASP.NET MVC but it might be a good way.

    http://msdn.microsoft.com/en-us/library/y2k85ax6.aspx

    This article uses code dom for ActionLink generation.

    http://blogs.msdn.com/davidebb/archive/2009/06/01/a-buildprovider-to-simplify-your-asp-net-mvc-action-links.aspx#comments

    0 讨论(0)
  • 2021-02-06 03:53

    I am by no means an expert, but if you are very new to ASP.NET MVC, then I recommend you start with the built-in functionality before rolling your own. It does most of what you have described, except does not encourage UI to be defined/constructed in the controller, since that is the job of the view.

    Through the ModelStateDictionary you can add model errors and set model values which will then get bound to your form inputs on validation fail.

    Update: Another way to look at it: ask yourself why you are using MVC over classic ASP.NET construction techniques, and then see if your proposed approach aligns with those reasons. For me separation of concerns was a huge reason, as well as granular control over the HTML generated, and I feel like your approach may subvert those things.

    To address your edit specifically:

    Steps 1 through through are against the MVC paradigm. Step 4, fine. Steps 5 through 7 are pretty much standard MVC practice and fully supported by the framework. E.g., Performing Simple Validation (C#) shows example of validation and presentation of error messages.

    0 讨论(0)
  • 2021-02-06 03:54

    Although not an expert I had to create a solution where my main object had a list of values. Lets call it Object A has a list of ApplicationValues that are mapped in the database. The ApplicationValues have a Key (the form field e.g. PhoneNumber) and the Value.

    As the ApplicationValues were an EntitySet I had to create get and set methods to correctly handle setting a specific ApplicationValue. I also had a list of ApplicationRules in my database that defined what these application values could take.

    Here is a snippet of code that may help you develop a solution for your needs.

    public partial ApplicationValue
    {
        public string Key;
        public string Value;
    }
    
    public partial ApplicationRule
    {
        public string ValidationFormat;
        public string ValidationError;
        public bool Required;
    }
    
    public partial class A
    {
        public void SetValue(string key, string value)
        {
            //ApplicationValues is the list of values associated to object A
            ApplicationValue v = ApplicationValues.SingleOrDefault
            (k => k.Key == key);
    
            //if we already have this value
            if (v != null)
            {   //...then we can simply set and return
                v.Value = value;
                return;
            }
    
            //else we need to create a new ApplicationValue
            v = new ApplicationValue
                {
                    AffinityID = this.ID,
                    Key = key,
                    Value = value
                };
    
            ApplicationValues.Add(v);
        }
    
        public string GetValue(ApplicationField key)
        {
            return GetValue(key, String.Empty);
        }
    
        public string GetValue(ApplicationField key, string defaultValue)
        {
            if (ApplicationValues == null)
                return defaultValue;
    
            ApplicationValue value = ApplicationValues.SingleOrDefault
            (f => f.Key == key.ToString());
    
            return (value != null) ? value.Value : defaultValue;
        }
    

    And then to do the form validation I loop through ApplicationRules (which defines if a field is required, contains a regex etc) and match it to the FormCollection.

    public ActionResult Details(FormCollection form)
    {
        IList<ApplicationRule> applicationRules = //get my rules from the DB
    
        if (!(ValidateApplication(applicationRules, form, a)))
        {
            ModelState.AddModelError("message", "Please review the errors below.");
            return View(a);
        }
        ...
    }
    
    private bool ValidateApplication(IList<ApplicationRule> applicationRules,
                                     FormCollection form, A a)
        {
            //loop through the application rules
            foreach (ApplicationRule ar in applicationRules)
            {
                //try and retrieve the specific form field value using the key
                string value = form[ar.Key];
    
                if (value == null)
                    continue;
    
                //set the model value just in case there is an error
                //so we can show error messages on our form
                ModelState.SetModelValue(ar.Key, ValueProvider[ar.Key]);
    
                //if this rule is required
                if (ar.Required)
                {   //...then check if the field has a value
                    if (String.IsNullOrEmpty(value))
                    {
                        ModelState.AddModelError(ar.Key, "Field is required");
                        continue;
                    }
                }
    
                //if this rule has a validation format
                if (!String.IsNullOrEmpty(ar.ValidationFormat))
                {   //...then check the value is of the correct format
                    Regex re = new Regex(ar.ValidationFormat);
    
                    if (!re.IsMatch(value))
                    {
                        ModelState.AddModelError(ar.Key, ar.ValidationError);
                        continue;
                    }
                }
    
                a.SetValue(ar.Key, value);
            }
    
            return ModelState.IsValid;
        }
    
    0 讨论(0)
  • 2021-02-06 03:55

    I wrote a class library that basically does exactly what my psuedocode in my question describes. It works great.

    EDIT:

    I finally got around to cleaning up my class library. I have added some new features and created a fairly well documented demo web application.

    All of this is hosted here on CodePlex. I hope this helps someone.

    0 讨论(0)
提交回复
热议问题