MVC: How do you give a viewmodel a list and correc

2019-07-11 21:30发布

What I have done is search Activedirectory users with a given value being a name. I then create a viewmodel that contains the values Name,Email and description. I then display it as .cshtml on the index.

The thing is with the way I have made it, it only sends through the first user it finds- (If I search for Andrew out of multiple Andrews, it finds them all but returns the first one.)

I want to add them to a list then pretty much do the same thing, but of course on the .cshtml iterate over the list and display the results.

Here is the HomeController.cs code --

public ActionResult Index(IndexViewModel profile)
{
    if (ModelState.IsValid)
    {
        //List<Principal> users = new List<Principal>();
        using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
        {
            UserPrincipal qbeUser = new UserPrincipal(ctx);
            qbeUser.DisplayName = profile.Name + "*";

            using (PrincipalSearcher srch = new PrincipalSearcher(qbeUser))
            {
                if(!(srch.FindAll().Count() < 0))
                {
                    foreach(var found in srch.FindAll())
                    {
                        //users.Add(found);
                        IndexViewModel returnmodel = new IndexViewModel(found);
                        return View(returnmodel);
                    }
                }                       
            }
        }
    }

    return View(profile);
}

The bit to look at in that is the

foreach(var found in srch.FindAll())
{
    //users.Add(found);
    IndexViewModel returnmodel = new IndexViewModel(found);                               
    return View(returnmodel);
}

Here is the code for the IndexViewModel.cs#

public class IndexViewModel
{
    public IndexViewModel(Principal found)
    {
        Name = found.DisplayName;
        Email = found.UserPrincipalName;
        Description = found.Description;
    }

    [Required(ErrorMessage = "Please enter a name")]
    [Display(Name = "Persons Name")]
    public string Name { get; set; }
    public string Email { get; set; }
    public string Description { get; set; }
}

And here is the Index.cshtml

/ this just create the input box, validation text and submit button.

<div id="content">
@Html.ValidationSummary(true)
@using (Html.BeginForm("Index", "Home"))
{
    <fieldset>
        <div class="form-group col-md-12">
            @Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" })
            <div class="col-md-4">
                @Html.EditorFor(modelItem => Model.Name, new { htmlAttributes = new { @class = "form-control", @style = "width:280px" }, })
                @Html.ValidationMessageFor(x => x.Name)
            </div>
            <div class="col-md-2">
                <input type="submit" class="btn btn-default" value="Search">
            </div>
            <div class="col-md-3">
            </div>
        </div>
    </fieldset>
}
<br>
</div>

This here displays the single result found /

<table id="historyTable" class="table">
    <thead>
        <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>@Model.Name</td>
            <td>@Model.Email</td>
            <td>@Model.Description</td>
        </tr>
    </tbody>
</table>

2条回答
我命由我不由天
2楼-- · 2019-07-11 21:49

Andy's answer is correct but here is the code you might like to try if you're still having trouble.

First create the new user class to hold the information about the user you want to display :

public class User
{
  public string Name { get; set; }
  public string Email { get; set; }
  public string Description { get; set; }
}

Then amend your IndexViewModel to utilize this new class :

public class IndexViewModel
{
  public List<User> FoundUsers {get; set;}

  public string Name {get; set;}

  public IndexViewModel(List<User> found)
  {
    this.FoundUsers = found;
  }
}

In your controller, you're correct in identifying the problem area, and this would be one way round it :

public ActionResult Index(IndexViewModel profile)
{
    if (ModelState.IsValid)
    {
        List<User> users = new List<User>();
        using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
        {
            UserPrincipal qbeUser = new UserPrincipal(ctx);
            qbeUser.DisplayName = profile.Name + "*";

            using (PrincipalSearcher srch = new PrincipalSearcher(qbeUser))
            {
                if(!(srch.FindAll().Count() < 0))
                {
                    foreach(var found in srch.FindAll())
                    {
                        users.Add(new User() {
                          Name = found.Name,
                          Email = found.Email,
                          Description = found.Description
                        });
                    }
                }                       

                IndexViewModel returnmodel = new IndexViewModel(users);
                return View(returnmodel);
            }
        }
    }

    return View(profile);
}

So in the controller you are now populating your view model with a List<User> that you can iterate over in your view :

<table id="historyTable" class="table">
    <thead>
        <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        @foreach(var user in Model.FoundUsers)
        {
            <tr>
                <td>@user.Name</td>
                <td>@user.Email</td>
                <td>@user.Description</td>
            </tr>
        }
    </tbody>
</table>
查看更多
一纸荒年 Trace。
3楼-- · 2019-07-11 21:59

I think you want a User Model first. Then have your IndexViewModel has a List<User>. In your foreach, create a new User class and add that to your list. Create the IndexViewModel outside the foreach and return it after the foreach. Then loop through the list in your view. This is pretty common, if you google you'll find examples.

查看更多
登录 后发表回答