Click here to Skip to main content
15,892,575 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm very new to MVC (MVC4 in VS2012) and would need some advice on the following.
I'm using the Entity Framework.

I have a view that will display the selected user details (Title, first name, etc...).
Under that it will display the user's hobbies.
Under the user's hobbies there is a dropdown listbox and a add button next to it.
This add button will add the selected hobby from the dropdown listbox.

I'm using strongly typed View.

I had a problem that once I've selected a hobby and clicked the add button I would only get the selected hobby Id "userHobby.SelectedId", in the AddHobby() section in the controller, but the "userHobby.User" would be null. I need the user Id.
I resorted to use a hidden Htmlhelper "@Html.Hidden("userId", Model.User.Id)" to retrieve the user Id. This worked.

The two questions is:
1) Why am I getting a null in the "userHobby.User"?
2) Is there a better and a cleaner way of doing this?

This is the code:
The User and Hobby Model
C#
public partial class User
{
    public User()
    {
        this.Hobbies = new HashSet<Hobby>();
    }

    public int Id { get; set; }
    public string title { get; set; }
    public string firstName { get; set; }
    public string lastName { get; set; }
    public string emailAddress { get; set; }

    public virtual ICollection<Hobby> Hobbies { get; set; }
}

public partial class Hobby
{
    public Hobby()
    {
        this.Users = new HashSet<User>();
    }

    public int Id { get; set; }
    public string hobbyName { get; set; }
    public string hobbyType { get; set; }
    
    public virtual ICollection<User> Users { get; set; }

}

// This is the one that I pass through to the view as a strong typed.
public class ViewModelHobby
{
    public int SelectedId { get; set; }
    public User User { get; set; }

    public IEnumerable<Hobby> Hobbies { get; set; }

}


The code in the View
C#
@model Multiple_Lists.ViewModels.ViewModelHobby

@{
    ViewBag.Title = "User Details";
}

<h2>Details</h2>
@using (Html.BeginForm("AddHobby", "User", Model, FormMethod.Post))
{
<fieldset>
    <legend>User</legend>

    @Html.Hidden("userId", Model.User.Id)

    <div class="display-label">
         @Html.DisplayNameFor(model => model.User.title)
    </div>
    <div class="display-field">
        @Html.DisplayFor(model => model.User.title)
    </div>

    <div class="display-label">
         @Html.DisplayNameFor(model => model.User.firstName)
    </div>
    <div class="display-field">
        @Html.DisplayFor(model => model.User.firstName)
    </div>

    <div class="display-label">
         @Html.DisplayNameFor(model => model.User.lastName)
    </div>
    <div class="display-field">
        @Html.DisplayFor(model => model.User.lastName)
    </div>

    <div class="display-label">
         @Html.DisplayNameFor(model => model.User.emailAddress)
    </div>
    <div class="display-field">
        @Html.DisplayFor(model => model.User.emailAddress)
    </div>

    <table class="display-table">
        <thead>
            <tr>
                <th>Hobby Name</th>
                <th>Hobby Type</th>
                <th>Delete</th>

            </tr>

        </thead>

        <tbody>
            @foreach (var item in Model.User.Hobbies)
            {
                <tr>
                    <td>
                        @item.hobbyName
        
                    </td>

                    <td>
                        @item.hobbyType

                    </td>
    
                    <td>
                        @Html.ActionLink(" ", "DeleteHobby", "User", new { hobbyId = item.Id, userId = Model.User.Id}, new {  @class = "delete-pic" })

                    </td>

                </tr>

            }
            
        </tbody>

    </table>

    <div>
        @Html.DropDownListFor(model => model.SelectedId, new SelectList(Model.Hobbies, "Id", "hobbyName"))

        <input type="submit" value="Add" />

    </div>

</fieldset>

}


The code in the controller to view the user details
C#
public ActionResult Details(int userId = 0)
{
    ViewModelHobby userHobbies = new ViewModelHobby();

    User user = db.Users.Find(userId);
    List<Hobby> hobbies = db.Hobbies.ToList();

    userHobbies.User = user;
    userHobbies.Hobbies = hobbies;
    userHobbies.SelectedId = 0;

    return View(userHobbies);

}


The code in the controller to insert the newly selected hobby to the user.
C#
public ActionResult AddHobby(ViewModelHobby userHobby, int userId)
{
    // --------------------------------------------------------
    // Do database work to insert the new hobby for the user.
    // --------------------------------------------------------

    return RedirectToAction("Details", "User", new { userId = userId});

}
Posted
Comments
Volker Keil 13-Jun-13 4:35am    
Thanks Zoltán, your article has helped me a lot.

1 solution

If you don't want to do a postback on adding every and each hobby, you can either:
- use a session variable to store the edited user's state and add the hobbies with an ajax call
- use a multiselect listbox instead of dropdowns
- use a "array" to keep the hobby list and post at once (see my article: Dynamic tabular input with unobstructive validation in ASP.NET MVC3[^])
Be aware, that the list of all hobbies is not part of your user model, it is part of your domain model. You mislead yourself if you use userHobbies.Hobbies for that. You should either use a viewmodel that encapsulates the user and the related domain model, or the ViewData/ViewBag capability to pass the additional data, or get the additional data directly in the view - since that is a presentation concern.
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900