Search code examples
c#asp.net-mvcgettersetterfactory-pattern

factory pattern returns UI/MVC controls


I am trying to understand the factory pattern where the factory takes a MeetingPollingQuestionType and returns the UI/MVC appropriate for the question type. I created this interface MeetingQuestionInterface and one class LongAnswerText that has a label and TextBox. When I run the program how do I send the view to the factory?

I am not sure how to pass in the MeetingPollingQuestionType and get this data populated? Should the interface take in MeetingPollingQuestionType? Any help would be great.

Goal

the factory takes a MeetingPollingQuestionType and returns the UI/MVC appropriate for the question type.

JSON Data

[
    {
        "MeetingPollingQuestionId": 2,
        "MeetingPollingQuestionType": "LongAnswerText",
        "MeetingPollingId": 3,
        "SequenceOrder": 1,
        "MeetingPollingParts": [
            {
                "MeetingPollingPartsId": 2,
                "Type": "Question",
                "MeetingPollingQuestionId": 2,
                "MeetingPollingPartsValues": [
                    {
                        "Type": "label",
                        "QuestionValue": "This is a long question",
                        "FileManagerId": 0,
                        "FileName": null,
                        "FileData": null,
                        "FileType": null
                    }
                ]
            }
        ]
    },
    {
        "MeetingPollingQuestionId": 3,
        "MeetingPollingQuestionType": "MultipleChoice",
        "MeetingPollingId": 3,
        "SequenceOrder": 2,
        "MeetingPollingParts": [
            {
                "MeetingPollingPartsId": 3,
                "Type": "Question",
                "MeetingPollingQuestionId": 3,
                "MeetingPollingPartsValues": [
                    {
                        "Type": "label",
                        "QuestionValue": "this is a multiple choice question",
                        "FileManagerId": 0,
                        "FileName": null,
                        "FileData": null,
                        "FileType": null
                    }
                ]
            },
            {
                "MeetingPollingPartsId": 4,
                "Type": "Image",
                "MeetingPollingQuestionId": 3,
                "MeetingPollingPartsValues": [
                    {
                        "Type": "Image",
                        "QuestionValue": null,
                        "FileManagerId": 14552,
                        "FileName": null,
                        "FileData": null,
                        "FileType": null
                    }
                ]
            },
            {
                "MeetingPollingPartsId": 5,
                "Type": "Answers",
                "MeetingPollingQuestionId": 3,
                "MeetingPollingPartsValues": [
                    {
                        "Type": "radio",
                        "QuestionValue": "Yes",
                        "FileManagerId": 0,
                        "FileName": null,
                        "FileData": null,
                        "FileType": null
                    },
                    {
                        "Type": "radio",
                        "QuestionValue": "No",
                        "FileManagerId": 0,
                        "FileName": null,
                        "FileData": null,
                        "FileType": null
                    },
                    {
                        "Type": "radio",
                        "QuestionValue": "Abstain",
                        "FileManagerId": 0,
                        "FileName": null,
                        "FileData": null,
                        "FileType": null
                    }
                ]
            }
        ]
    }
]

Program

 static void Main(string[] args)
    {
        LongAnswerText LongAnswerTextParts = new LongAnswerText();
        var control = LongAnswerTextParts ()

    }

    interface MeetingQuestionInterface
    {
        string Label(string target, string text);
    }
    
    public class LongAnswerText : MeetingQuestionInterface
    {
        public static string Label(string target, string text)
        {
            return String.Format("<label for='{0}'>{1}</label>", target, text);
        }
    
        public static string TextBox(string target, string text)
        {
            return String.Format("<input  for='{0}'>{1}</input>", target, text);
        }
    
    }

MVC form view

<div class="form-group">
    @Html.LabelFor(c => c.LongAnswerText)
    @Html.TextBoxFor(c => c.LongAnswerText, new { @class = "form-control" })
</div>

Sample

https://dotnetfiddle.net/j6YIPN

Solution

  • So I built a small example component for this use case, which I think works here, but depending on the data model might be optimized a bit more.

    This is the actual component doing the strategising, so I called it StrategyComponent:

    @switch (Input.Type)
    {
        case "label":
            <label for="@id">@Input.QuestionValue</label>
            break;
        case "text":
            <input id="@id" type="text"/>
            break;
    }
    
    @code {
    
        [Parameter]
        public MeetingPollingPartsValues Input { get; set; } = null!;
    
        private readonly Guid id = Guid.NewGuid(); // Because I'm not sure where to take the ID from
    }
    

    Then to use it you just do this:

    @foreach (var value in Values)
    {
        <StrategyComponent Input="value" />
    }
    
    @code {
        List<MeetingPollingPartsValues> Values { get; set; } = new(); // Put real data here
    }
    

    I hope I got the data model right, I just copied it from your fiddle. For the things around that it seems there is another model that also has its own type, I guess you can use the same pattern there.