Search code examples
c#asp.net-mvcentity-frameworkmodel-view-controlleref-code-first

Passing a view-model to view, saving data from text-boxes into the view-model, then transferring that data from the view-model to my models


I don't know if I am going about this the correct way but basically I'm creating an MVC application for a club where I have a Members class, and an Events class. I have a view that displays all the events below

@model IEnumerable<Application.Models.Event>
@{
    Layout = null;
}

<h1>Events For this Month!</h1>
<table>


    @foreach (var events in Model)

    {

        <tr>
            <td><h2>@events.Name</h2></td>

            <td>
                @Html.ActionLink("Sign-Up", "SignUpEvent", "User", new { id = events.Id }, null)
            </td>
        </tr>


    }

</table>

when they select, signup next to the event they wish to attend, it takes them to this Action. I created a viewmodel called "MemberEventViewModel that has a member, and an event in it.

    public ActionResult SignUpEvent(int id)
    {
        var Vmodel = new MemberEventViewModel() 
        {


        };




        return View(Vmodel);
    }

the view returned is where the member enters their pin


@model Application.ViewModels.MemberEventViewModel
@{
    Layout = null;
}


<h2>Sign-Up</h2>

@using (Html.BeginForm("SignUp", "User")) 
{
    @Html.LabelFor(c => c.Member.PIN)
    @Html.TextBoxFor(c => c.Member.PIN)


    @Html.HiddenFor(c => c.Events.Id)

    <button type="submit">Save</button>
}

then finally goes to this controller so I can save and see the event that a member has signed up for

    [HttpPost]
    public ActionResult SignUp(MemberEventViewModel Vmodel) 
    {

        var EventinDB = _context.Events.SingleOrDefault(c => c.Id == Vmodel.Events.Id);
        var MemberinDB = _context.Members.SingleOrDefault(c => c.PIN == Vmodel.Member.PIN);
        MemberinDB.Events.Add(EventinDB);
        EventinDB.Members.Add(MemberinDB);


        return View("ViewEvents", "User");

I'm confused on how to get this working. I want to view what events a member is signed up for, and vice versa. A bridge table called MemberEvents was created when I created the many to many relationship between Events and Members.

also here is my View model class

    public class MemberEventViewModel
    {
        public Member Member { get; set; }
        public Event Events { get; set; }


    }

here is the events class

    public class Event
    {

        public int Id { get; set; }
        [Required]
        public string Name { get; set; }
        [Required]
        [Display(Name = "Date")]
        public DateTime? EventDate { get; set; }
        [Required]
        [Display(Name = "Start Time")]
        public TimeSpan EventStartTime { get; set; }
        [Required]
        [Display(Name = "End Time")]
        public TimeSpan EventEndTime { get; set; }
        public int EventTotalTime{ get; set; }
        public virtual ICollection<Member> Members { get; set; }


    }

and members class


    public class Member
    {
        public int Id { get; set; }
        [Required]
        [MaxLength(4, ErrorMessage = "PIN must be 4 numbers long"), MinLength(4, ErrorMessage = "PIN must be 4 numbers long")]
        public string PIN { get; set; }
        [Required]
        [Display(Name ="First Name")]
        public string FirstName { get; set; }
        [Required]
        [Display(Name = "Last Name")]
        public string LastName { get; set; }
        [Display(Name = "Date of Birth")]
        public DateTime? Birthdate { get; set; }
        public virtual ICollection<Event> Events { get; set; }

    }

Solution

  • Looks like there's nothing wrong with how you're adding it but I think you missed context.SaveChanges() after you're adding the MemberEvents object.

    [HttpPost]
    public ActionResult SignUp(MemberEventViewModel Vmodel) 
    {
       var EventinDB = _context.Events.SingleOrDefault(c => c.Id == Vmodel.Events.Id);
       var MemberinDB = _context.Members.SingleOrDefault(c => c.PIN == Vmodel.Member.PIN);
    
       // try using one only
       MemberinDB.Events.Add(EventinDB);
       // EventinDB.Members.Add(MemberinDB);
    
       // you should save here   
       _context.SaveChanges();
    
       return View("ViewEvents", "User");
    }
    

    Also be sure that you're assigning the properties here;

    public ActionResult SignUpEvent(int id)
    {
       var Vmodel = new MemberEventViewModel() 
       {
          Member = // find the member _context.Members.Where(...)
          Events = _context.Events.FirstOrDefault(e=>e.Id == id)
       };
       return View(Vmodel);
    }