Using View model instead of data to create

I am trying to use viewmodels instead of using data directly for most of the things i am trying to do.

One such thing is trying to book a Passenger/Customer on a flight. The data uses two keys/IDs, the passenger Id and the Flight Id.

now the view model looks something like this:

namespace WebSite.Models.PassengerViewModels
    {
        public class FlightBookingViewModel
        {
            [Display(Name = "Passenger ID ")]
            public int IdC { get; set; }

            [Display(Name = "E-mail Address ")]
            [Required]
            [DataType(DataType.EmailAddress)]
            public string Email { get; set; }

            [Display(Name = "Flight ID ")]
            public int IdF { get; set; }

            [Display(Name = "Flight Name ")]
            public int Name { get; set; }

        }
    }

But the scaffold code to create a booking looks something like this:

public IActionResult Create()
        {
            ViewData["IdC"] = new SelectList(_context.Passengers, "Id", "Email");
            ViewData["IdF"] = new SelectList(_context.Flights, "Id", "Name");

            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("IdC,IdF,Attended")] FlightBooking model)
        {
            if (ModelState.IsValid)
            {
                _context.Add(model);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            ViewData["IdC"] = new SelectList(_context.Customers, "Id", "Email", model.IdF);
            ViewData["IdF"] = new SelectList(_context.Events, "Id", "Name", model.IdE);
            return View(model);
        }

Then the view page for the create is this:

@model WebSite.Data.FlightBooking

@{
    ViewData["Title"] = "Create";
}

<h2>Create</h2>

<h4>FlightBooking</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="IdC" class="control-label"></label>
                <select asp-for="IdC" class ="form-control" asp-items="ViewBag.IdC"></select>
            </div>
            <div class="form-group">
                <label asp-for="IdF" class="control-label"></label>
                <select asp-for="IdF" class ="form-control" asp-items="ViewBag.IdF"></select>
            </div>
            <div class="form-group">
                <div class="checkbox">
                    <label>
                        <input asp-for="Attended" /> @Html.DisplayNameFor(model => model.Attended)
                    </label>
                </div>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Now i tried to implement the viewmodel into this but it just wouldnt bring the data into the dropdown list. and i am unsure how to get that working.

Answers 1

  • So i finally gotten help with this from my tutor, so the first bit of the controller code which is this:

    public IActionResult Create()
            {
                ViewData["PassengerId"] = new SelectList(_context.Passengers, "Id", "Email");
                ViewData["FlightId"] = new SelectList(_context.Flights, "Id", "Name");
    
                return View();
            }
    

    Is already a viewmodel in a sense and protects the data.

    now the work in the second bit of code of the controller:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("PassengerId,IdF,Attended")] FlightBookingViewModel model)
            {
                if (ModelState.IsValid)
                {
                    FlightBooking flightBooking = new FlightBooking
                    {
                        PassengerId = model.PassengerId,
                        FlightId = model.FlightId,
                        Attended = model.Attended
                    }
                    await _context.Guests.AddAsync(flightBooking);
                    await _context.SaveChangesAsync();
                    return RedirectToAction(nameof(Index));
                }
                ViewData["PassengerId"] = new SelectList(_context.Customers, "Id", "Email", model.PassengerId);
                ViewData["FlightId"] = new SelectList(_context.Events, "Id", "Name", model.FlightId);
                return View(model);
            }
    

    This way i can get the drop down menu working when the viewmodel id's are named the same as the data id's

    The problem seemed like it was in the id names not being recognised. so once the viewmodels id names are the same as that of the data the issues went away and i am still using viewmodels


Related Articles