Search code examples
c#htmlasp.net-coreasp.net-core-mvcviewmodel

Deleting piece of data from two different view-models


so i am wanting to delete a piece of data that is in a list. such an example to explain it better is:

A passenger has a list of booked flights. now on the passengers page i have the option to check their details. so i enter there and i see the list of the booked flights. but then i need to delete one of his bookings.

Here is the issue. im unsure how to do that since the data needs two different data sets.

The details page has the details of the passenger and also it calls out a partial view of all his bookings. here is some code.

The Passenger Details View:

@model WebSite.Models.PassengerViewModels.PassengerDetialsViewModel

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

<h2>Details</h2>

<div>
    <h4>PassengerDetailsViewModel</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.IdC)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.IdC)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Surname)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Surname)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.FirstName)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.FirstName)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Email)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Email)
        </dd>
    </dl>
</div>

<h4>Number of Flight: @Model.Flight.Count()</h4>

<partial name="_Flights" for="Flights" />

<div>
    @Html.ActionLink("Edit", "Edit", new { id = Model.IdC }) |
    <a asp-action="Index">Back to List</a>
</div>

Then my partial view is this:

@model IEnumerable<WebSite.Models.PassengerViewModels.FlightsViewModel>

<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.IdF)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.FNumber)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Date)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Duration)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Destination)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Attended)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.IdF)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FNumber)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Date)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Duration)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Destination)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Attended)
            </td>
            <td>
                @Html.ActionLink("Delete", "DeleteF", new { Id = item.IdF })
            </td>
        </tr>
}
    </tbody>
</table>

Then here is the Delete operation in the controller called DeleteF:

public async Task<IActionResult> DeleteF(int? IdC, int? IdF)
        {
            if (IdC == null && IdF == null)
            {
                return NotFound();
            }

            var flightBooking = await _context.Flights
                .Select(a => new FlightsViewModel
                {
                    IdC = a.IdC,
                    Email = a.Passenger.Email,
                    IdE = a.IdF,
                    Title = a.Flight.FNumber,
                    Attended = a.Attended
                }).FirstOrDefaultAsync(e => e.IdC == IdC);


            if (flightBooking == null)
            {
                return NotFound();
            }

            return View(flightBooking);
        }

        [HttpPost, ActionName("DeleteF")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmedF(int? IdC, int? IdF)
        {
            var flightBooking = await _context.Flights.FindAsync(IdC, IdF);
            _context.Guests.Remove(flightBooking);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }

I know i need to pass two id's into the delete operation but i am not sure how to pass the passenger ID through the partial view.

Edit:

The data for the flight bookings is in a list of its own that has a composite key of the passenger and the flight. thats why i need to pass in the passenger Id with the Flight Id.

Also here is the Delete page if it helps at all:

@model WebSite.Models.PassengerViewModels.FlightsViewModel

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

<h2>DeleteB</h2>

<h3>Are you sure you want to delete this?</h3>
<div>
    <h4>FlightsViewModel</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.IdC)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.IdC)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Email)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Email)
        </dd>
        <dd>
            @Html.DisplayFor(model => model.IdF)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.IdE)
        </dt>
        <dt>
            @Html.DisplayNameFor(model => model.FNumber)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.FNumber)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Attended)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Attended)
        </dd>
    </dl>

    <form asp-action="Delete">
        <input type="hidden" asp-for="IdC" />
        <input type="hidden" asp-for="IdF" />
        <input type="submit" value="Delete" class="btn btn-default" /> |
        <a asp-action="Index">Back to List</a>
    </form>
</div>

To clarify things. I have technically 3 tables of data im working with. one is the passenger table that has IdC as its primary key, Two is the flights table which has IdF as its primary key and the last table is the Flights booking table(i know i should word that in my code) which has a composite key which is IdC and IdF.

Edit 2:

Here is the viewmodel for the passenger:

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

        [Display(Name ="Surname ")]
        [Required]
        public string Surname { get; set; }

        [Display(Name ="First Name ")]
        [Required]
        public string FirstName { get; set; }

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

        public IEnumerable<FlightsViewModel> Events { get; set; }
    }
}

Solution

  • I know i need to pass two id's into the delete operation but i am not sure how to pass the passenger ID through the partial view.

    The <partial> tag helper has view-data attribute to pass data to partial view. So in your Passenger Details View, modify the call to partial view:

    <partial name="_Flights" model=" @Model.Flights" view-data='@new ViewDataDictionary(ViewData) { { "IdC", Model.IdC } }' />
    

    In your partial view, you could have an access to IdCusing ViewBag.IdC or ViewData["IdC"].

    Pass IdC to DeleteF action:

    @Html.ActionLink("Delete", "DeleteF", new {IdC = ViewBag.IdC, IdF = item.IdF })