Ziad Akiki
Ziad Akiki

Reputation: 2680

Dynamic return type for Form Flow

I'm currently looking for a way to dynamically create a FormDialog from values predefined in the database. In other words, my field types, prompts and settings are all stored in a database, and what I'm trying to achieve is reading those settings and building the appropriate form dynamically.

What I tried so far is something similar to the following. Suppose I have a form with a Name (string) and an Age (int) field (FieldDefinition is a class I created to store the parameters of a field, assuming they are fetched from the database) (The code is stripped just to illustrate the idea):

    public static IForm<dynamic> BuildForm()
    {
        string FormMessage = "Welcome to demo contact form!";
        string CompletionMessage = "Thank your for your info. Our team will contact you as soon as possible.";

        var fields = new List<FieldDefinition>()
        {
            new FieldDefinition()
            {
                Name = "Name",
                FieldType = typeof(string),
                Prompts = new string[] { "What's your name?", "Please input your name" }
            },
            new FieldDefinition()
            {
                Name = "Age",
                FieldType = typeof(int),
                Prompts = new string[] { "What's your age?", "How old are you?" }
            }
        };



        var builder = new FormBuilder<dynamic>();
        builder.Message(FormMessage);

        foreach (var f in fields)
        {
            builder.Field(
                new FieldReflector<dynamic>(f.Name)
                .SetType(f.FieldType)
                );
        }

        builder.AddRemainingFields()
        .OnCompletion(async (context, order) => {
            var message = context.MakeMessage();
            message.Text = CompletionMessage;
            await context.PostAsync(message);
        });
        return builder.Build();
    }

So here's the problems:

  1. I thought I could use a dynamic type. But a method cannot return a dynamic object as it is determined at run-time. Therefore, I got an error when I tried building the form using the following:

    dynamic values; var form = new FormDialog<dynamic>(values, ContactForm.BuildForm, FormOptions.PromptInStart, null);`
    
  2. I need to create the properties of the object dynamically, therefore I looked for a way to create a Type on runtime. I ended up with something called TypeBuilder but I was a bit skeptical if it could solve my problem or not.

Therefore, I guess the ultimate start is by using the FieldReflector but I have no idea how to achieve this. I'm looking for something similar to the above but that does actually work.

Upvotes: 3

Views: 140

Answers (1)

Eric Dahlvang
Eric Dahlvang

Reputation: 8292

Have you looked at FormBuilderJson? You could dynamically construct the .json string, and build the form at runtime:

public static IForm<JObject> BuildJsonForm()
{
    string fromFlowJson = GetFormFlowJson();

    return new FormBuilderJson(schema)
         .AddRemainingFields()
         .Build();
}

See here for more information: https://learn.microsoft.com/en-us/azure/bot-service/dotnet/bot-builder-dotnet-formflow-json-schema?view=azure-bot-service-3.0

Upvotes: 0

Related Questions