user6096770
user6096770

Reputation:

MVC5 Cannot use two models in one view

Theres links already on how to use multiple models for a view with different ways to do it, however, I tried those and could not get them to work, what am I doing wrong?

I simply want two form inputs in 1 view, and one model, but one of the form inputs uses a list<'model'> and the other uses 'model', here's what I mean:

UPDATE: copy/paste this code, if you select and submit any check box items you will get an error at @Model.input.passWord and I have no idea why, checkbox items wont show either, need help.

View (Index.cshtml):

@using stupidassTests.Models
@model  MyViewModel


@{
ViewBag.Title = "Index";


}

<h2>Password Input</h2>

<div>
<p>Enter Password</p>
@using (Html.BeginForm("Index", "Home", FormMethod.Get))
{
    @Html.TextBox("password")

    <button type="submit" value="Search"></button>
}

<p>@Model.input.passWord</p> <!--passWord is underlined with red because it conflicts with the List'model'-->

</div>

<h2>Checkbox</h2>

<div>

@using (Html.BeginForm())
{
    for (var i = 0; i < Model.inputCollection.Count; i++)
    {
        <p>
            @Html.HiddenFor(n => n.inputCollection[i].Id)
            @Html.DisplayFor(n => n.inputCollection[i].Name)
            @Html.HiddenFor(n => n.inputCollection[i].Name)
            @Html.CheckBoxFor(n => n.inputCollection[i].Checked)
        </p>

    }

    <input id="Submit1" type="submit" value="submit" />


    if (ViewBag.Values != null)
    {
        foreach (var item in ViewBag.Values)
        {
            <p>@item</p>
        }
    }



}

So as you can see, copy/paste my code and try to run it, 'password' form input is being shoved out by 'checkbox' input, it seems the two '@model' are conflicting under one model class, how do I fix this?

Controller (HomeController.cs):

public ActionResult Index() {

        return View();
    }



    [HttpGet, ActionName("Index")]
    public ActionResult PasswordInput(string password)
    {
        FormInputs pss = new FormInputs();

        pss.passWord = password;

        MyViewModel mvm = new MyViewModel() { input = pss, isList = false };

return this.View("Index", mvm);

    }





    [HttpGet]
    public ActionResult CheckBoxGet()
    {


        var list = new List<FormInputs>
        {
             new FormInputs { Id = 1, Name = "Aquafina", Checked = false },
        new FormInputs { Id = 2, Name = "Mulshi Springs", Checked = false },
         new FormInputs { Id = 3, Name = "Alfa Blue", Checked = false },
         new FormInputs { Id = 4, Name = "Atlas Premium", Checked = false },
         new FormInputs { Id = 5, Name = "Bailley", Checked = false },
         new FormInputs { Id = 6, Name = "Bisleri", Checked = false },
         new FormInputs { Id = 7, Name = "Himalayan", Checked = false },
         new FormInputs { Id = 8, Name = "Cool Valley", Checked = false },
         new FormInputs { Id = 9, Name = "Dew Drops", Checked = false },
         new FormInputs { Id = 10, Name = "Dislaren", Checked = false },

 };
        MyViewModel mvm = new MyViewModel() { inputCollection = list, isList = true };
return this.View("Index", mvm);

    }


    [HttpPost]
    public ActionResult CheckBoxPost(List<FormInputs> list)
    {


        var selected = list.Where(x => x.Checked).Select(x => x.Name);

        ViewBag.Values = selected;

        MyViewModel mvm = new MyViewModel() { inputCollection = list, isList = true };

        return this.View("Index", mvm);
    }

Model (FormInputs.cs):

public class MyViewModel
{
    public FormInputs input;
    public List<FormInputs> inputCollection;
    public bool isList;
}
public class FormInputs
{
    public string passWord = "";


    public int Id { get; set; }
    public string Name { get; set; }
    public bool Checked { get; set; }

    public List<string> checkBox = new List<string>();


}

So just as a summary, because I'm a beginner at MVC, how do I re-work this code (btw copy/paste it) so that both form inputs can co-exist in 1 view?

Upvotes: 2

Views: 2119

Answers (2)

SamGhatak
SamGhatak

Reputation: 1493

This might be a good example to use the Composite Pattern. You can have a ViewModel with two properties:

public class MyViewModel{
    public FormInputs input;
    public List<FormInputs> inputCollection;
    public bool isList;
}

And arrange the data accordingly:

public ActionResult PasswordInput(string password)
{
    FormInputs pss = new FormInputs();

    pss.passWord = password;

    MyViewModel mvm = new MyViewModel(){input = pss, isList = false}
    return this.View("Index", mvm); 
}

AND

public ActionResult CheckBoxGet()
{
    var list = new List<FormInputs>
    {
         new FormInputs { Id = 1, Name = "Aquafina", Checked = false },
    new FormInputs { Id = 2, Name = "Mulshi Springs", Checked = false },
     new FormInputs { Id = 3, Name = "Alfa Blue", Checked = false },
     new FormInputs { Id = 4, Name = "Atlas Premium", Checked = false },
     new FormInputs { Id = 5, Name = "Bailley", Checked = false },
     new FormInputs { Id = 6, Name = "Bisleri", Checked = false },
     new FormInputs { Id = 7, Name = "Himalayan", Checked = false },
     new FormInputs { Id = 8, Name = "Cool Valley", Checked = false },
     new FormInputs { Id = 9, Name = "Dew Drops", Checked = false },
     new FormInputs { Id = 10, Name = "Dislaren", Checked = false },

    };
    MyViewModel mvm = new MyViewModel(){inputCollection = list , isList = true}
    return this.View("Index", mvm); 

}

AND in view, use this:

@model MyViewModel

Check the isList property before using the input/inputCollection

Upvotes: 1

Mairaj Ahmad
Mairaj Ahmad

Reputation: 14604

You can use viewmodel.

Use ViewModel

For view model you have to create a class and in this class you will define all models as properties of this class.Here are two classes.

public class EmployeeDetails
{
    [Required]
    [Display(Name = "Name")]
    public string Name { get; set; }

}

public class Employee
{
    public int Id { get; set; }
}

Here is viewmodel

public class ViewModel
{
    public Employee emp { get; set; }
    public EmployeeDetails empdet{ get; set; }
}

Now in Controller you will do like this

public ActionResult About()
{
        ViewModel vm = new ViewModel();
        vm.emp = new Employee();
        vm.empdet = new EmployeeDetails();
        return View(vm);
}

And in view you will receive it like this

@model ViewModel

Upvotes: 1

Related Questions