0

I am trying to code in asp net MVC and my code looks:

Controller:

public class ReservationsController : Controller
{
    private AppDbContext db = new AppDbContext();

    // GET: Reservations
    public ActionResult Index()
    {
        return View(db.Reservations.ToList());
    }

    // GET: Reservations/Create
    public ActionResult Create()
    {
        ViewBag.ScreeningId = new SelectList(db.Screenings, "Id", "Description");

        HashSet<int> seats = new HashSet<int>(db.Reservations.Select(x => x.SeatNumber));
        ViewBag.Seats = seats;
        return View();
    }

View:

<div class="form-group">
    @Html.LabelFor(model => model.Screening, "Seans", htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.DropDownList("ScreeningId", null, htmlAttributes: new { @class = "form-control" })
        @Html.ValidationMessageFor(model => model.Screening, "", new { @class = "text-danger" })
    </div>
</div>

Model:

public class Reservation
{
    public int Id { get; set; }
    [DisplayName("Imię")]
    public string FirstName { get; set; }
    [DisplayName("Nazwisko")]
    public string SecondName { get; set; }
    [DisplayName("Telefon")]
    public string Phone { get; set; }
    public int? ScreeningId { get; set; }
    [DisplayName("Seans")]
    public Screening Screening { get; set; }
    [DisplayName("Numer miejsca")]
    public int SeatNumber { get; set; }
}

And I get error:

There is no ViewData item of type 'IEnumerable< SelectListItem >' that has the key 'ScreeningId'.

Someone know what could be wrong?

Create.cshtml FULL

    @model CinemaTicketReservation.Models.Reservation

@{
    ViewBag.Title = "Rezerwacja filmu";
}

<h2>Zarezerwuj film</h2>


@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

<div class="form-horizontal">
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.SecondName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.SecondName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.SecondName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Phone, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Phone, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Phone, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.SeatNumber, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.SeatNumber, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.SeatNumber, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Screening, "Seans", htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownList("ScreeningId", null, htmlAttributes: new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.Screening, "", new { @class = "text-danger" })
        </div>
    </div>

    <table class="table table-bordered w400">
        @for (var i = 0; i < 5; i++)
        {
            <tr>
                @for (var j = 0; j < 5; j++)
                {
                    var k = i * 5 + j + 1;
                        if (((HashSet<int>) ViewBag.Seats).Contains(k))
                        {
                            <td class="red">@k</td>
                        }
                        else
                        {
                            <td class="green">@k</td>
                        }

                }
            </tr>
        }
     </table>

    <br />

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Rezerwuj" class="btn btn-default" />
        </div>
    </div>


</div>
}

@if (Session["Login"] != null)
{
    <div>
        @Html.ActionLink("Powrót", "Index")
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

ReservationController FULL:

public class ReservationsController : Controller
{
    private AppDbContext db = new AppDbContext();

    // GET: Reservations
    public ActionResult Index()
    {
        return View(db.Reservations.ToList());
    }

    // GET: Reservations/Create
    public ActionResult Create()
    {
        ViewBag.ScreeningId = new SelectList(db.Screenings, "Id", "Description");

        HashSet<int> seats = new HashSet<int>(db.Reservations.Select(x => x.SeatNumber));
        ViewBag.Seats = seats;
        return View();
    }

    // POST: Reservations/Create
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "Id,FirstName,SecondName,Phone,SeatNumber")] Reservation reservation)
    {
        if (ModelState.IsValid)
        {
            // sprawdzamy czy miejsce bylo juz zajete
            if (db.Reservations.Select(x => x.SeatNumber).Contains(reservation.SeatNumber))
            {
                return View(reservation);
            }
            db.Reservations.Add(reservation);
            db.SaveChanges();

            if (Session["Login"] != null)
            {
                return RedirectToAction("Index");
            }
            return RedirectToAction("Success");
        }

        return View(reservation);
    }

    public ActionResult Success()
    {
        return View();
    }

    // GET: Reservations/Edit/5
    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Reservation reservation = db.Reservations.Find(id);
        if (reservation == null)
        {
            return HttpNotFound();
        }
        return View(reservation);
    }

    // POST: Reservations/Edit/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "Id,FirstName,SecondName,Phone,SeatNumber")] Reservation reservation)
    {
        if (ModelState.IsValid)
        {
            db.Entry(reservation).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(reservation);
    }

    // GET: Reservations/Delete/5
    public ActionResult Delete(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Reservation reservation = db.Reservations.Find(id);
        if (reservation == null)
        {
            return HttpNotFound();
        }
        return View(reservation);
    }

    // POST: Reservations/Delete/5
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public ActionResult DeleteConfirmed(int id)
    {
        Reservation reservation = db.Reservations.Find(id);
        db.Reservations.Remove(reservation);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

This is what you wanted? Model is in first post.

Frihu
  • 43
  • 9
  • This might be helpful, https://stackoverflow.com/questions/16594958/how-to-use-a-viewbag-to-create-a-dropdownlist – Bharadwaj Jan 16 '18 at 15:30
  • 1
    Use that.. @Html.DropDownList("ScreeningId ", (IEnumerable)ViewBag.ScreeningId, "Select Screen Id") – MMK Jan 16 '18 at 15:46
  • Honestly, I would rather use JavaScript to render a dropdown from a model. That way you can do client side validation, easier to work with, and avoid Razor. Since you can use a JSX Template or something to inject the values. – Greg Jan 16 '18 at 15:48
  • Can you show us complete `Create` and only `Create` action code ? with file name, posted action and model declaration please. – GGO Jan 16 '18 at 16:00
  • 1
    @Greg if you've annotated your server-side model correctly then using `EditorFor` and similar razor helpers can generate both client-side and server-side validation logic, keeping it in one place and therefore slightly more manageable. – Zhaph - Ben Duguid Jan 16 '18 at 16:49
  • @Zhaph-BenDuguid More manageable? Client side validation would be to assign a marker to the input, then your Validation.js would automatically point to the type of validation from one file. No post back, no extra attributes on your entity, and in a single location. The only pitfall, would be extra data sanitizing potentially on the server to trust the validated input. But you still have to do that server side anyway. – Greg Jan 16 '18 at 17:10
  • @Greg - indeed - and the razor helpers will assign the correct markers to the input elements to be picked up by your Validation.js with no post back. Then when the form is submitted, the server side validation will use the exact same rules to confirm the model. Much less chance of having a minor but annoying difference between the rules on the client and server. What I'm getting at is that you can get both from one set of attributes on the entity - they are only "extra" if you have custom "markers" on the input that have to be kept in sync. – Zhaph - Ben Duguid Jan 16 '18 at 17:21
  • @Zhaph-BenDuguid Fair enough, but both approaches are almost identical but you have traditional markup vs razor, which is often easier to deal with. All I was trying to say. – Greg Jan 16 '18 at 17:35
  • Because you do not populate the `SelectList` in the POST method when you return the view –  Jan 16 '18 at 21:30
  • @StephenMuecke Added, right now I have another issue, which I described in answer below. – Frihu Jan 17 '18 at 18:57
  • If you have another question, then ask another question. –  Jan 17 '18 at 21:34

1 Answers1

0

In your controller, don't forget to populate ViewBag.ScreeningId in POST action too :

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,FirstName,SecondName,Phone,SeatNumber")] Reservation reservation)
{
     ViewBag.ScreeningId = new SelectList(db.Screenings, "Id", "Description");
     [...]
GGO
  • 2,678
  • 4
  • 20
  • 42
  • Even I tried this, now its throwing same error but with "Screening".. With 4 arguments applications is not starting. – Frihu Jan 16 '18 at 15:37
  • Yes, I am using only DropDownList – Frihu Jan 16 '18 at 15:45
  • @Frihu `DropDownList` and `DropDownListFor` are two different code structures. – Greg Jan 16 '18 at 15:46
  • it's create.cshtml, Index.cshtml have differenct structure – Frihu Jan 16 '18 at 15:51
  • Helped, but right now there is another error: `There is already an open DataReader associated with this Command which must be closed first.` In line: `@Html.DropDownList("ScreeningId", null, htmlAttributes: new { @class = "form-control" })` – Frihu Jan 17 '18 at 18:43
  • This is another topic https://stackoverflow.com/questions/6062192/there-is-already-an-open-datareader-associated-with-this-command-which-must-be-c – GGO Jan 18 '18 at 08:40