Ouanixi
Ouanixi

Reputation: 126

Passing data from Form with variable number of inputs - MVC 5

I've been looking for similar questions in here but still couldn't find a solution to my problem.

I have a page that contains some text and a form and they both share the same ViewModel as follows:

public class MyViewModel
 {
   public IEnumerable<WordingB> WordingBs { get; set; }
   public IEnumerable<WordingC> WordingCs { get; set; }
   public IEnumerable<Question> Questions { get; set; } 
}

Here's a bit more detail about WordingB, WordingC and Question:

public class WordingB
    {           
        public string EOW { get; set; }
    }



public class WordingC
    {           
        public string EOW { get; set; }
    }




public class Question
    {           
        public string QuestionText { get; set; }
        public string Answer {get; set;}
    }

And this is the page in question:

@model MyProject.ViewModels.MyViewModel   

<div class="col-md-6 masonry listview-block">
    @foreach (var wording in Model.WordingBs)
    {
        <div class="block">                
            <p>@Html.Raw(@wording.EOW)</p>
        </div>
    }
    @foreach (var wording in Model.WordingCs)
    {
        <div class="block">              
            <p>@Html.Raw(@wording.EOW)</p>
        </div>
    }

</div>


@using (Ajax.BeginForm("Routing", "Partials", new AjaxOptions { UpdateTargetId = "Target", LoadingElementId = "spinner", HttpMethod = "POST", InsertionMode = InsertionMode.Replace }))
{


            <div id="quick-post" class="block-body form-validation">
                @foreach (var question in Model.Questions)
                {
                    <div class="form-group">
                        <label for="QuestionText">@question.QuestionText</label>
                        <input type="text" class="form-control input-sm input-sm" name="Answer">
                    </div>
                }
                <div class="form-group">
                    <label for="postcode">PostCode</label>
                    <input type="text" class="form-control input-sm validate[required] input-sm" name="postcode" [email protected]["postcode"]>

                </div>

                <div class="form-group">
                    <label>Loss Description</label>
                    <textarea></textarea>
                </div>

                <input type="submit" class="btn btn-primary btn-xs" value="Route">

            </div>

        </div>
    </div>

}

The idea is that some Admin person is able to add questions to the form. (questions are stored in a table) There's a controller that uses the MyViewModel and returns the model that I need to the view.

 public ActionResult EOW()
        {
            QuestionsandWording viewModel = new QuestionsandWording();

            viewModel.Questions = // first query

            viewModel.WordingBs = // second query

            viewModel.WordingCs = // third query

            return View(viewModel);
        }

The problem that I am facing now is passing the data from my form to a controller. The form can have zero to 30 or 40 questions as far as I'm concerned! I feel like I've hit the limit of my knowledge and I'm in serious need of advice.

Upvotes: 1

Views: 5904

Answers (3)

Ouanixi
Ouanixi

Reputation: 126

With the help of cosset and Derek, I managed to find a workaround as follows:

1) I gave a name to my input element like this:

<input type="text" name="Answer">

I didn't need to iterate with Answer[i] as suggested on one of the answers as the framework automatically binds all inputs with same name into a List element that my method can take as an argument. Like this:

public ActionResult Routing(List<string> Answer){} 

2) I also needed to use the value of my label tags in my Routing method and had no clue how to do it. Again, Cosset suggested that I use a hidden field and give it a value of the label text. This worked perfectly.

<label for="Answer">@question.QuestionText</label>
<input type="hidden" name="QuestionText" [email protected] />

And the method now looks like this :

public ActionResult Routing(List<string> Answer, List<string> QuestionText){} 

Now I've got what I needed. To pass all data from my form to the controller (Both labels and inputs) without having to worry about the MyViewModel.

For the sake of learning, I would quite like to know if there are any other ways of achieving this at all.

Upvotes: 6

vborutenko
vborutenko

Reputation: 4443

At first use Html helpers

@{int i = 0;}
@foreach (var question in Model.Questions)
            {
                <div class="form-group">
                    <label for="QuestionText">@question.QuestionText</label>
                    <input type="text" class="form-control input-sm input-sm" name="Answer[i]">
                </div>
i++;
            }

And viewmodel

public class Question
{           
    public string QuestionText { get; set; }
    public IEnumerable<string> Answer {get; set;}
}

And read this tutorials

1 2 3

Upvotes: 0

Derek Hackett
Derek Hackett

Reputation: 200

What you should do is create a post back method that binds to the ViewModel in the view so that the MVC framework returns the model data for you.

The Method would look something like this

[Post]
public ActionResult EOW(MyViewModel viewModel)
    {
       //Do something  
        return View();
    }

Upvotes: 1

Related Questions