О получении данных формы из представления Razor в привязку контроллера и EF - PullRequest
0 голосов
/ 04 апреля 2019

По сути, у меня есть небольшое приложение .NET MVC, которое служит сайтом для бронирования гостиничных номеров.

Теперь, при создании нового отеля, в моем представлении Razor у меня сначала есть несколько полей, очевидно, необходимых для создания нового отеля, а затем динамически генерируемый список маленьких и больших кроватей для заполнения новых номеров отеля (см. блок кода в конце записи), чтобы пользователь мог нажать кнопку «плюс», чтобы получить новую строку с двумя полями ввода с количеством маленьких и больших кроватей, необходимых для создания новой комнаты.

Теперь, в моем контроллере это приводит к следующему длинному и уродливому методу, о котором я думал:

[HttpPost]
[ActionName("AddHotel")]
public ActionResult AddHotelPost()
{
     int[] amountOfBigBedsList = (Request.Form.GetValues("AmountOfBigBeds") ??
                                 throw new InvalidOperationException("The amount of beds for a room cannot be empty"))
                                 .Select(int.Parse).ToArray();

     int[] amountOfSmallBedsList = (Request.Form.GetValues("AmountOfSmallBeds") ??
                                 throw new InvalidOperationException("The amount of beds for a room cannot be empty"))
                                 .Select(int.Parse).ToArray();

     if (amountOfSmallBedsList.Length != amountOfBigBedsList.Length) return View("AddHotel");
// The amounts must match since they are both required

     Hotel newHotel = new Hotel
     {
           Name = Request.Form.Get("HotelName"),
           Location = new Location { City = Request.Form.Get("City"), Country = Request.Form.Get("Country") },
           Address = Request.Form.Get("Address"),
           Rooms = new List<HotelRoom>(),
     };

     for (int i = 0; i < amountOfSmallBedsList.Length; i++)
     {
           _uow.HotelRepository.AddRoom(newHotel, new HotelRoom
           {
                 AmountOfSmallBeds = amountOfSmallBedsList[i],
                 AmountOfBigBeds = amountOfBigBedsList[i],
                 HotelRefId = newHotel.Id,
                 Hotel = newHotel,
           });
     }

     _uow.HotelRepository.Add(newHotel);
     _uow.Save(); // Unit of Work

     return RedirectToAction("../Hotel/AllHotels", new { hotel_id = newHotel.Id });
}

Я хотел бы воспользоваться преимуществами привязки Entity Framework, чтобы просто взять в сигнатуре метода что-то вроде AddHotelPost(Hotel newHotel, List<HotelRoom> newHotelRooms) и чтобы инфраструктура выполняла всю работу без всего этого длинного уродливого кода, который я написал, чтобы вручную получить форму данные и назначить их новым объектам Hotel и List.

Кстати, имена, используемые для атрибутов в моих моделях, совпадают с полями 'name', которые я использовал в моих тегах ввода html.

Я только начал работать с .NET несколько недель назад, так что будьте осторожны, ха-ха. Любые рекомендации приветствуются.

Код вида бритвы:

<form method="post" action="/Hotel/AddHotel" class="form-inline my-2 my-lg-0 hotelForm">
    <div class="form-group">
        <input name="HotelName" class="form-control mr-sm-2" type="text" placeholder="AccommodationName" aria-label="AccommodationName" required>
        <input name="City" class="form-control mr-sm-2" type="text" placeholder="City" aria-label="City" required>
        <input name="Country" class="form-control mr-sm-2" type="text" placeholder="Country" aria-label="Country" required>
        <input name="Address" class="form-control mr-sm-2" type="text" placeholder="Address" aria-label="Address" required>
    </div>

    <br />
    <hr />

    <div class="form-group" id="addRoomAndSubmitSection">
        <button type="button" class="btn btn-default btn-sm" id="addRoomField"> <span class="glyphicon glyphicon-plus"></span></button>
        <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Add Accommodation</button>
    </div>

    <script>document.getElementById('addRoomField').click();</script>
</form>

@section scripts
{
    <script>
        $(document).ready(function () {
            $("#addRoomField").click(function (event) {
                event.preventDefault();

                $(`<div class="form-group roomForm">
                    <input name="AmountOfBigBeds" class="form-control mr-sm-2" type="number" min="0" max="4" placeholder="Amount of big beds"
                    aria-label="Amount of big beds" style="width: 13em;" required>
                    <input name="AmountOfSmallBeds" class="form-control mr-sm-2" type="number" min="0" max="4" placeholder="Amount of small beds"
                    aria-label="Amount of small beds" style="width: 13em;" required>
                    </div>
                    <br />
                    <hr />`).insertBefore($(`#addRoomAndSubmitSection`));
            });
        });
    </script>
}

Ответы [ 2 ]

0 голосов
/ 04 апреля 2019

Прежде всего вам нужно правильно определить класс.Класс

 public class Booking
{
    public int Id { get; set; }
    public DateTime Transdate { get; set; }
    public string HotelName { get; set; }
    public string HotelAddress { get; set; }

    public ICollection<BookingItem> BookingItems { get; set; }
}

И затем BookingItemClass

    public class BookingItem
{
    public int Id { get; set; }
    public int BookingId { get; set; }
    public int? Qty { get; set; }
    public RoomType RoomType { get; set; }

    public virtual Booking Booking { get; set; }
}

public enum RoomType { 
Small, Medium, Large, ExtraBed}

Затем создайте ViewModel для инициации типа комнаты, а также создайте процедуру сохранения

 public class BookingVM
{
    public Booking Booking { get; set; }
    public List<BookingItem> BookingItems { get; set; }
    public ApplicationDbContext db = new ApplicationDbContext();

    public void Initiate()
    {
        Booking = new Booking();
        BookingItems = new List<BookingItem>();

        // Get All Type of Room
        foreach (var item in Enum.GetValues(typeof(RoomType)))
        {
              BookingItem _item = new BookingItem
                {
                    RoomType = (RoomType)item,
                    Qty = 0,
                    BookingId = 0
                };

              BookingItems.Add(_item);
        }


    }

    public void AddBooking()
    {

        Booking.BookingItems = new List<BookingItem>();


        foreach (var item in BookingItems)
        {
            Booking.BookingItems.Add(item);
        }

        db.Bookings.Add(Booking);
    }
}

ЗатемКонтроллер будет очень простым

публичный класс HotelBookingController: Controller {

    public ActionResult Create() {
        BookingVM VM = new BookingVM();
        VM.Initiate();
        VM.Booking.Transdate = DateTime.Today.Date;

        return View(VM);
    }

    [HttpPost]
    public ActionResult Create(Booking Booking, List<BookingItem> BookingItems)
    {
        BookingVM VM = new BookingVM();
        VM.Booking = Booking;
        VM.BookingItems = BookingItems;

        VM.AddBooking();

        return View();
    }
}

Вид будет примерно таким

@model HelpingRoy.ViewModel.BookingVM
@{
    ViewBag.Title = "Create";
}


@using (Html.BeginForm())
{

    <div class="form-group">
        @Html.LabelFor(a => a.Booking.Transdate)
        @Html.TextBoxFor(a => a.Booking.Transdate, new { @class = "form-control" })
    </div>

    <div class="form-group">
        @Html.LabelFor(a => a.Booking.HotelName)
        @Html.TextBoxFor(a => a.Booking.HotelName, new {@class = "form-control" })
    </div>

    <div class="form-group">
        @Html.LabelFor(a => a.Booking.HotelAddress)
        @Html.TextBoxFor(a => a.Booking.HotelAddress, new { @class = "form-control" })
    </div>

    <table class="table table-bordered table-striped">
        <thead>
           <tr>
               <th>Room Type</th>
               <th>Qty </th>
           </tr>
        </thead>
        @for (int i = 0; i < Model.BookingItems.Count(); i++)
        {
            
            @Html.HiddenFor(a => Model.BookingItems[i].RoomType)
            <tr>
                @*use display so that use cannot amend the room type*@
                <td>@Html.DisplayFor(a => Model.BookingItems[i].RoomType)</td>
                <td>@Html.TextBoxFor(a => Model.BookingItems[i].Qty)</td>
            </tr>
        }
    </table>
    
    <input  type="submit" value="SAVE" class="btn btn-success"/>
}

Я проверил это .. Это должно работать и надеюсь, что это поможет!

0 голосов
/ 04 апреля 2019

В контроллере у нас есть действие AddHotelPost (), сделай так AddHotelPost (данные FormCollection), так как вы публикуете форму. В объекте данных вся информация будет в виде строки, поэтому преобразуйте ее в другой тип данных в соответствии с требованием, например int [] rooms = Convert.Toint32 (data ["rooms"]);

Для использования EF создайте класс с именем HotelContext (или как вам нравится)

public class HotelContext:DbContext
    {
public HotelContext():base("type the **name** as you have in the connectionString")
        {
            this.Configuration.LazyLoadingEnabled = false;

        }
      public DbSet<Hotel> Hotels { get; set; }

Затем в ActionMethod создайте объект HotelContext, затем с этим объектом вызовите свойство Отели , а с этим свойством используйте его метод Add и передайте объект HotelObject функции Add (). Также не забудьте сохранить его, например так:

HotelContext context=new HotelContext();
context.Hotels.Add(Hotel);
context.SaveChanges();

Надеюсь, это поможет вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...