Dynamic form creation in asp.net c#

前端 未结 4 651
耶瑟儿~
耶瑟儿~ 2021-02-09 09:38

So, I need some input refactoring an asp.net (c#) application that is basically a framework for creating dynamic forms (any forms). From a high level point of view, there is a t

相关标签:
4条回答
  • 2021-02-09 10:27

    I have a number of similar apps for building dynamic forms that I support.

    There's a whole lot of things you could/could not do & you're right to think hard before throwing away 3 years of testing/development.

    My input for you to consider is to implement a plug-in architecture on top of what you're got. Any custom code for a form goes in the plug-in & the name of this plug-in is stored with the form. When you generate a form, the correct plug-in is called to enhance the base functionality. that way you get to move all the custom code out of the existing library. It should also mean less breaking changes, each plug-in only affects the form it's attached to.

    From that point it'll be easy to refactor the core engine as it's common functionality across all clients & forms.

    0 讨论(0)
  • 2021-02-09 10:30

    Since your application seems to have become a big ball of mud, a complete (or an almost complete rewrite) might make sense.

    You should also take into account new technologies like document-oriented databases (couchDB, MongoDB)

    Most of the form definitions could probably fit pretty well in document-oriented databases. For exemple:

    To define a customer form, you could use a document that looks like:

    {Type:"FormDefinition",
     EntityType: "Customer",
     Fields: [
       {FieldName:"CustomerName", 
        FieldType:"String", 
        Validations:[
          {ValidationType:"Required"},
          {ValidationType:"StringLength", Minimum:15, Maximum:50},
        ]},
        ...
       {FieldName:"CustomerType", 
        FieldType:"Dropdown", 
        PossibleValues: ["Standard", "Valued", "Gold"],
        DefaultValue: ["Standard"]
        Validations:[
          {ValidationType:"Required"},
          {
            ValidationType:"Custom", 
            ValidationClass:"MySystem.CustomerName.CustomValidations.CustomerStatus"
          }
        ]},
        ...
     ]
    };
    

    With this kind of document to define your forms, you could easily add forms and validations which are customer specific.

    You could easily add subforms using a fieldtype of SubForm or whatever.

    You could define FieldTypes for all common types of fields like e-mail, phone numbers, address, etc.

    namespace System.CustomerName.CustomValidations {
      class CustomerStatus: IValidator {
    
        private FormContext form;
        private List<ValidationErrors> validationErrors;
    
        CustomerStatus(FormContext fc) {
          this.validationErrors = new List<ValidationErrors>();
          this.form = fc;
        }
    
        public List<ValidationErrors> Validate() {
          if (this.formContext.Fields["CustomerType"] == "Gold" && Int.Parse(this.form.Fields["OrderCount"]) < 10) { 
            this.validationErrors.Add(new ValidationError("A gold customer must have at least 10 orders"))
          }
    
          if (this.formContext.Fields["CustomerType"] == "Valued" && Int.Parse(this.form.Fields["OrderCount"]) < 5) { 
            this.validationErrors.Add(new ValidationError("A valued customer must have at least 5 orders"))
          }
          return this.validationErrors;          
        }
      }
    }
    

    A record of a document with that definition could look like this:

    {Type:"Record",
     EntityType: "Customer",
     Fields: [
       {FieldName:"CustomerName", Value:"ABC Corp.", 
       {FieldName:"CustomerType", Value:"Gold",
       ...
     ]
    };
    

    Sure, this solution is a lot of work, but if/when realized it could be really easy to create/update/customize forms.

    0 讨论(0)
  • 2021-02-09 10:33

    My current project sounds like almost exactly the same product you're describing. Fortunately, I learned most of my hardest lessons on a former product, and so I was able to start my current project with a clean slate. You should probably read through my answer to this question, which describes my experiences, and the lessons I learned.

    The main thing to focus on is the idea that you are building a product. If you can't find a way to implement a particular feature using your current product feature set, you need to spend some additional time thinking about how you could turn this custom one-off feature into a configurable feature that can benefit all (or at least many) of your clients.

    So:

    1. If you're referring to the model of being able to create a fully customizable form that makes client-specific code almost unnecessary, that model is perfectly valid and I have a maintainable working product with real, paying clients that can prove it. Regression testing is performed on specific features and configuration combinations, rather than a specific client implementation. The key pieces that make this possible are:
      1. An administrative interface that is effective at disallowing problematic combinations of configuration options.
      2. A rules engine that allows certain actions in the system to invoke customizable triggers and cause other actions to happen.
      3. An Integration framework that allows data to be pulled from a variety of sources and pushed to a variety of sources in a configurable manner.
      4. The option to inject custom code as a plugin when absolutely necessary.
    2. Yes, clients come up with weird requests. It's usually worthwhile to suggest alternative solutions that will still solve the client's problem while still allowing your product to be robust and configurable for other clients. Sometimes you just have to push back. Other times you'll have to do what they say, but use wise architectural practices to minimize the impact this could have on other client code.
    3. Minimize use of the session to track state. Each page should have enough information on it to track the current page's state. Information that needs to persist even if the user clicks "Back" and starts doing something else should be stored in a database. I have found it useful, however, to keep a sort of breadcrumb tree on the session, to track how users got to a specific place and where to take them back to when they finish. But the ID of the node they're actually on currently needs to be persisted on a page-by-page basis, and sent back with each request, so weird things don't happen when the user is browsing to different pages in different tabs.
    4. Use incremental refactoring. You may end up re-writing the whole thing twice by the time you're done, or you may never really "finish" the refactoring. But in the meantime, everything will still work, and you'll have new features every so often. As a rule, rewriting the whole thing will take you several times as long as you think it will, so don't try to take the whole thing in a single bite.
    0 讨论(0)
  • 2021-02-09 10:45

    This is a common but (IMO) somewhat naive design approach. "Instead of solving the customer's problem, let's build a tool to let them solve their own problems!". But the reality is, that generally customers want YOU to solve their ACTUAL problems. So build things that solve their problems. If you can architect it in a way that allows you to reuse some parts for different customers, fine. But that is generally what the frameworks have done for you already - work out the common features that applications need and make them available in neat packages.

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