Multiple models in a view

前端 未结 12 1832
太阳男子
太阳男子 2020-11-21 23:07

I want to have 2 models in one view. The page contains both LoginViewModel and RegisterViewModel.

e.g.

pub         


        
相关标签:
12条回答
  • 2020-11-21 23:27

    I want to say that my solution was like the answer provided on this stackoverflow page: ASP.NET MVC 4, multiple models in one view?

    However, in my case, the linq query they used in their Controller did not work for me.

    This is said query:

    var viewModels = 
            (from e in db.Engineers
             select new MyViewModel
             {
                 Engineer = e,
                 Elements = e.Elements,
             })
            .ToList();
    

    Consequently, "in your view just specify that you're using a collection of view models" did not work for me either.

    However, a slight variation on that solution did work for me. Here is my solution in case this helps anyone.

    Here is my view model in which I know I will have just one team but that team may have multiple boards (and I have a ViewModels folder within my Models folder btw, hence the namespace):

    namespace TaskBoard.Models.ViewModels
    {
        public class TeamBoards
        {
            public Team Team { get; set; }
            public List<Board> Boards { get; set; }
        }
    }
    

    Now this is my controller. This is the most significant difference from the solution in the link referenced above. I build out the ViewModel to send to the view differently.

    public ActionResult Details(int? id)
            {
                if (id == null)
                {
                    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
                }
    
                TeamBoards teamBoards = new TeamBoards();
                teamBoards.Boards = (from b in db.Boards
                                     where b.TeamId == id
                                     select b).ToList();
                teamBoards.Team = (from t in db.Teams
                                   where t.TeamId == id
                                   select t).FirstOrDefault();
    
                if (teamBoards == null)
                {
                    return HttpNotFound();
                }
                return View(teamBoards);
            }
    

    Then in my view I do not specify it as a list. I just do "@model TaskBoard.Models.ViewModels.TeamBoards" Then I only need a for each when I iterate over the Team's boards. Here is my view:

    @model TaskBoard.Models.ViewModels.TeamBoards
    
    @{
        ViewBag.Title = "Details";
    }
    
    <h2>Details</h2>
    
    <div>
        <h4>Team</h4>
        <hr />
    
    
        @Html.ActionLink("Create New Board", "Create", "Board", new { TeamId = @Model.Team.TeamId}, null)
        <dl class="dl-horizontal">
            <dt>
                @Html.DisplayNameFor(model => Model.Team.Name)
            </dt>
    
            <dd>
                @Html.DisplayFor(model => Model.Team.Name)
                <ul>
                    @foreach(var board in Model.Boards)
                    { 
                        <li>@Html.DisplayFor(model => board.BoardName)</li>
                    }
                </ul>
            </dd>
    
        </dl>
    </div>
    <p>
        @Html.ActionLink("Edit", "Edit", new { id = Model.Team.TeamId }) |
        @Html.ActionLink("Back to List", "Index")
    </p>
    

    I am fairly new to ASP.NET MVC so it took me a little while to figure this out. So, I hope this post helps someone figure it out for their project in a shorter timeframe. :-)

    0 讨论(0)
  • 2020-11-21 23:31
    1. Create one new class in your model and properties of LoginViewModel and RegisterViewModel:

      public class UserDefinedModel() 
      {
          property a1 as LoginViewModel 
          property a2 as RegisterViewModel 
      }
      
    2. Then use UserDefinedModel in your view.

    0 讨论(0)
  • 2020-11-21 23:35

    This is a simplified example with IEnumerable.

    I was using two models on the view: a form with search criteria (SearchParams model), and a grid for results, and I struggled with how to add the IEnumerable model and the other model on the same view. Here is what I came up with, hope this helps someone:

    @using DelegatePortal.ViewModels;
    
    @model SearchViewModel
    
    @using (Html.BeginForm("Search", "Delegate", FormMethod.Post))
    {
    
                    Employee First Name
                    @Html.EditorFor(model => model.SearchParams.FirstName,
    new { htmlAttributes = new { @class = "form-control form-control-sm " } })
    
                    <input type="submit" id="getResults" value="SEARCH" class="btn btn-primary btn-lg btn-block" />
    
    }
    <br />
        @(Html
            .Grid(Model.Delegates)
            .Build(columns =>
            {
                columns.Add(model => model.Id).Titled("Id").Css("collapse");
                columns.Add(model => model.LastName).Titled("Last Name");
                columns.Add(model => model.FirstName).Titled("First Name");
            })
    

    ... )

    SearchViewModel.cs:

    namespace DelegatePortal.ViewModels
    {
        public class SearchViewModel
        {
            public IEnumerable<DelegatePortal.Models.DelegateView> Delegates { get; set; }
    
            public SearchParamsViewModel SearchParams { get; set; }
    ....
    

    DelegateController.cs:

    // GET: /Delegate/Search
        public ActionResult Search(String firstName)
        {
            SearchViewModel model = new SearchViewModel();
            model.Delegates = db.Set<DelegateView>();
            return View(model);
        }
    
        // POST: /Delegate/Search
        [HttpPost]
        public ActionResult Search(SearchParamsViewModel searchParams)
        {
            String firstName = searchParams.FirstName;
            SearchViewModel model = new SearchViewModel();
    
            if (firstName != null)
                model.Delegates = db.Set<DelegateView>().Where(x => x.FirstName == firstName);
    
            return View(model);
        }
    

    SearchParamsViewModel.cs:

    namespace DelegatePortal.ViewModels
    {
        public class SearchParamsViewModel
        {
            public string FirstName { get; set; }
        }
    }
    
    0 讨论(0)
  • 2020-11-21 23:39

    Add this ModelCollection.cs to your Models

    using System;
    using System.Collections.Generic;
    
    namespace ModelContainer
    {
      public class ModelCollection
      {
       private Dictionary<Type, object> models = new Dictionary<Type, object>();
    
       public void AddModel<T>(T t)
       {
          models.Add(t.GetType(), t);
       }
    
       public T GetModel<T>()
       {
         return (T)models[typeof(T)];
       }
     }
    }
    

    Controller:

    public class SampleController : Controller
    {
      public ActionResult Index()
      {
        var model1 = new Model1();
        var model2 = new Model2();
        var model3 = new Model3();
    
        // Do something
    
        var modelCollection = new ModelCollection();
        modelCollection.AddModel(model1);
        modelCollection.AddModel(model2);
        modelCollection.AddModel(model3);
        return View(modelCollection);
      }
    }
    

    The View:

    enter code here
    @using Models
    @model ModelCollection
    
    @{
      ViewBag.Title = "Model1: " + ((Model.GetModel<Model1>()).Name);
    }
    
    <h2>Model2: @((Model.GetModel<Model2>()).Number</h2>
    
    @((Model.GetModel<Model3>()).SomeProperty
    
    0 讨论(0)
  • 2020-11-21 23:40

    you can always pass the second object in a ViewBag or View Data.

    0 讨论(0)
  • 2020-11-21 23:44

    There are lots of ways...

    1. with your BigViewModel you do:

      @model BigViewModel    
      @using(Html.BeginForm()) {
          @Html.EditorFor(o => o.LoginViewModel.Email)
          ...
      }
      
    2. you can create 2 additional views

      Login.cshtml

      @model ViewModel.LoginViewModel
      @using (Html.BeginForm("Login", "Auth", FormMethod.Post))
      {
          @Html.TextBoxFor(model => model.Email)
          @Html.PasswordFor(model => model.Password)
      }
      

      and register.cshtml same thing

      after creation you have to render them in the main view and pass them the viewmodel/viewdata

      so it could be like this:

      @{Html.RenderPartial("login", ViewBag.Login);}
      @{Html.RenderPartial("register", ViewBag.Register);}
      

      or

      @{Html.RenderPartial("login", Model.LoginViewModel)}
      @{Html.RenderPartial("register", Model.RegisterViewModel)}
      
    3. using ajax parts of your web-site become more independent

    4. iframes, but probably this is not the case

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