Как исправить вид модели для частичного просмотра - PullRequest
0 голосов
/ 04 апреля 2019

У меня проблема с созданием новой записи для пустых таблиц на SQLServer При попытке передать новую запись я получаю «Ссылка на объект не установлена ​​на экземпляр объекта». ошибка Когда я пытаюсь отредактировать существующую запись, таблицы отображают содержимое правильно, но сохранить изменения не получится. С таблицей «Гости» он будет перезагружать только старую запись без изменений, а для контактов он возвращает ту же ошибку, что и при создании новой записи. Приложение должно позволять создавать и редактировать записи, отображая как частичные формы редактора представления для каждой таблицы.

Я новичок в MVC.

Ниже мой код.

Столы моделей:


    [Table("GuestsTest")]
        public class Guest
        {
            [Key]
            [HiddenInput(DisplayValue = false)]
            public int GuestID { get; set; }        
            public string GuestLastName { get; set; }
            public string GuestFirstName { get; set; }
            public string GuestMiddleName { get; set; }
            public string GuestEmail { get; set; }
            public string GuestSex { get; set; }
        }

        [Table("ContactsTest")]
        public class Contact
        {        
            [Key]
            [HiddenInput(DisplayValue = false)]
            public int ContactID { get; set; }
            [HiddenInput(DisplayValue = false)]
            public int GuestID { get; set; }
            public int PostalCode { get; set; }
            public string City { get; set; }
            public string Street { get; set; }
            public string HouseNumber { get; set; }
            public string PhoneNumber { get; set; }

My view model


    public class TableViewModel
        {
            public Guest GetGuest { get; set; }
            public Contact GetContact { get; set; }
        }


My controllers 

    public class AdminController : Controller
        {
            private IGuestRepository guestRepository;
            private IContactRepository contactRepository;
            private IQRCodeRepository qrcodeRepository;

            public AdminController(IGuestRepository repoG, IContactRepository repoC, IQRCodeRepository repoQ)
            {
                guestRepository = repoG;
                contactRepository = repoC;
                qrcodeRepository = repoQ;
            }

            public ActionResult Index()
            {            
                return View(guestRepository.Guests);
            }        

            public ActionResult EditGuest(int? id)
            {
                if (id == null)
                {
                    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
                }
                TableViewModel viewModel = new TableViewModel();
                viewModel.GetGuest = guestRepository.Guests.FirstOrDefault(g => g.GuestID == id);
                viewModel.GetContact = contactRepository.Contacts.FirstOrDefault(c => c.ContactID == id);
                if (viewModel.GetGuest == null)
                {
                    return HttpNotFound();
                }
                return View(viewModel);
            }

            public ActionResult GuestForm(int? id)
            {
                var viewModel = new TableViewModel();
                viewModel.GetGuest = guestRepository.Guests.FirstOrDefault(g => g.GuestID == id);
                return PartialView("_GuestForm", viewModel.GetGuest);
            }

            [HttpPost]
            public ActionResult GuestForm(TableViewModel getGuest)
            {            
                if (ModelState.IsValid)
                {                
                    guestRepository.SaveGuest(getGuest.GetGuest);
                    qrcodeRepository.CreateQRCode(getGuest.GetGuest);
                    TempData["message"] = string.Format("Zapisano {0} {1}", getGuest.GetGuest.GuestFirstName, getGuest.GetGuest.GuestLastName);
                    return RedirectToAction("EditGuest/" + getGuest.GetGuest.GuestID);
                }
                else
                {                     
                    return PartialView(getGuest.GetGuest);
                }
            }

            public ActionResult ContactForm(int? id)
            {
                var viewModel = new TableViewModel();
                viewModel.GetContact = contactRepository.Contacts.FirstOrDefault(c => c.ContactID == id);
                return PartialView("_ContactForm", viewModel.GetContact);
            }

            [HttpPost]
            public ActionResult ContactForm(TableViewModel getGuest)
            {
                if (ModelState.IsValid)
                {
                    contactRepository.SaveContact(getGuest.GetContact);
                    TempData["message"] = string.Format("Zapisano {0} {1}", getGuest.GetGuest.GuestFirstName, getGuest.GetGuest.GuestLastName);
                    return RedirectToAction("EditGuest/" + getGuest.GetGuest.GuestID);
                }
                else
                {
                    return PartialView(getGuest.GetContact);
                }
            }

            public ActionResult Create()
            {
                return View("EditGuest", new TableViewModel());
            }


My view

    @model MSConference.WebUI.Models.TableViewModel

    @{
        if (Model.GetGuest.GuestEmail == null)
        {
            ViewBag.Title = "Tworzenie nowego użytkownika";
        }
        else
        {
            ViewBag.Title = "Edycja";
        }
        Layout = "~/Views/Shared/_AdminLayout.cshtml";
    }

    @if (Model.GetGuest.GuestEmail == null)
    {
        <h2>Tworzenie nowego użytkownika</h2>
    }
    else
    {
        <h2>Edycja - @Model.GetGuest.GuestFirstName @Model.GetGuest.GuestLastName</h2>
    }


    @using (Html.BeginForm("EditGuest", "Admin"))
    {
        @Html.AntiForgeryToken()
        <div class="container">
            <ul class="nav nav-pills">
                <li class="active"><a data-toggle="pill" href="#EditGuest">Edycja - Gość</a></li>
                <li><a data-toggle="pill" href="#EditContact">Edycja - Kontakt</a></li>
                <li><a data-toggle="pill" href="#EditBill">Edycja - Rezerwacja</a></li>
                <li><a data-toggle="pill" href="#EditPlan">Edycja - Konferencja</a></li>
            </ul>
            <div class="tab-content">
                <div id="EditGuest" class="tab-pane fade in active">@Html.Partial("_GuestForm", new MSConference.WebUI.Models.TableViewModel())</div>
                <div id="EditContact" class="tab-pane fade">@Html.Partial("_ContactForm", new MSConference.WebUI.Models.TableViewModel())</div>
                <div id="EditBill" class="tab-pane fade">sgdg</div>
                <div id="EditPlan" class="tab-pane fade">gsdgsgsgsg</div>
            </div>
        </div>    
     }

            <div>
                @Html.ActionLink("Powrót do Listy", "Index", null, new { @class = "btn btn-success" })
            </div>


I tried every method of passing model I could find and understand

EDIT

Here are my Repositories. Create error comes from if (contact.ContactID == 0)

    public class EFGuestRepository : IGuestRepository
        {
            private EfDbContext context = new EfDbContext();

            public IEnumerable<Guest> Guests
            {
                get { return context.Guests; }
            }

            public void SaveGuest(Guest guest)
            {
                if (guest.GuestID == 0)
                {
                    context.Guests.Add(guest);
                }
                else
                {
                    Guest dbEntry = context.Guests.Find(guest.GuestID);
                    if (dbEntry != null)
                    {
                        dbEntry.GuestLastName = guest.GuestLastName;
                        dbEntry.GuestFirstName = guest.GuestFirstName;
                        dbEntry.GuestMiddleName = guest.GuestMiddleName;
                        dbEntry.GuestEmail = guest.GuestEmail;
                        dbEntry.GuestSex = guest.GuestSex;
                    }
                }
                context.SaveChanges();
            }
            public Guest DeleteGuest(int guestId)
            {
                Guest dbEntry = context.Guests.Find(guestId);
                if (dbEntry != null)
                {
                    context.Guests.Remove(dbEntry);
                    context.SaveChanges();
                }
                return dbEntry;
            }
        }

        public class EFContactRepository : IContactRepository
        {
            private EfDbContext context = new EfDbContext();

            public IEnumerable<Contact> Contacts
            {
                get { return context.Contacts; }
            }

            public void SaveContact(Contact contact)
            {
                if (contact.ContactID == 0)
                {
                    contact.GuestID = contact.ContactID;
                    context.Contacts.Add(contact);
                }
                else
                {
                    Contact dbEntry = context.Contacts.Find(contact.ContactID);
                    if (dbEntry != null)
                    {
                        contact.GuestID = contact.ContactID;
                        dbEntry.PostalCode = contact.PostalCode;
                        dbEntry.City = contact.City;
                        dbEntry.Street = contact.Street;
                        dbEntry.HouseNumber = contact.HouseNumber;
                        dbEntry.PhoneNumber = contact.PhoneNumber;
                    }
                }
                context.SaveChanges();
            }

            public Contact DeleteContact(int guestId)
            {
                Contact dbEntry = context.Contacts.Find(guestId);
                if (dbEntry != null)
                {
                    context.Contacts.Remove(dbEntry);
                    context.SaveChanges();
                }
                return dbEntry;
            }


    public interface IGuestRepository
        {
            IEnumerable<Guest> Guests { get; }

            void SaveGuest(Guest guest);

            Guest DeleteGuest(int guestId);
        }

        public interface IContactRepository
        {
            IEnumerable<Contact> Contacts { get; }

            void SaveContact(Contact guest);

            Contact DeleteContact(int guestId);
        }

I've built whole project working with Adam Freeman pro asp.net mvc 5 book (SportsStore project).

Ответы [ 2 ]

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

Я решил свою проблему, заменив

@Html.Partial("PartialView", Model)

на @ {Html.RenderPartial ("PartialView", Model);}

Я также перестроил свои модели

Теперь мои модели сущностей выглядят так:

[Table("GuestsTest")]
    public class Guest
    {
        [Key]
        public int GuestID { get; set; }
        public string GuestLastName { get; set; }
        public string GuestFirstName { get; set; }
        public string GuestMiddleName { get; set; }
        public string GuestEmail { get; set; }
        public string GuestSex { get; set; }

        [Required]
        public virtual Contact Address { get; set; }
    }

    [Table("ContactsTest")]
    public class Contact
    {                
        public int ContactID { get; set; }
        [Key, ForeignKey("Guest")]
        public int GuestID { get; set; }
        public int PostalCode { get; set; }
        public string City { get; set; }
        public string Street { get; set; }
        public string HouseNumber { get; set; }
        public string PhoneNumber { get; set; }

        public virtual Guest Guest { get; set; }
    }

И мои модели представлений полностью перестроены к этому:

public class TableViewModel
    {
        public GuestViewModel GetGuest { get; set; }
        public ContactViewModel GetContact { get; set; }
    }

    public class GuestViewModel
    {
        [Key]
        [HiddenInput(DisplayValue = false)]
        public int? GuestID { get; set; }

        [MaxLength(50)]
        [Required(ErrorMessage = "Proszę podać nazwisko.")]
        [Display(Name = "Nazwisko")]
        public string GuestLastName { get; set; }

        [MaxLength(50)]
        [Required(ErrorMessage = "Proszę podać imię.")]
        [Display(Name = "Imię")]
        public string GuestFirstName { get; set; }

        [MaxLength(50)]
        [Display(Name = "Drugie imię")]
        public string GuestMiddleName { get; set; }

        [MaxLength(50)]
        [Required(ErrorMessage = "Proszę podać adres email.")]
        [RegularExpression(".+\\@.+\\..+", ErrorMessage = "Proszę podać prawidłowy adres e-mail.")]
        [Display(Name = "Email")]
        public string GuestEmail { get; set; }

        [MaxLength(1)]
        [Required(ErrorMessage = "Proszę podać płeć.")]
        public string GuestSex { get; set; }

    }

    public class ContactViewModel
    {
        [HiddenInput(DisplayValue = false)]
        public int ContactID { get; set; }

        [Key, ForeignKey("Guest")]
        [HiddenInput(DisplayValue = false)]
        public int GuestID { get; set; }

        [Required(ErrorMessage = "Proszę podać kod pocztowy.")]
        [Display(Name = "Kod pocztowy")]
        public int PostalCode { get; set; }

        [Required(ErrorMessage = "Proszę podać Miejscowość.")]
        [Display(Name = "Miejscowość")]
        public string City { get; set; }

        [Required(ErrorMessage = "Proszę podać ulicę.")]
        [Display(Name = "Ulica")]
        public string Street { get; set; }

        [Required(ErrorMessage = "Proszę podać numer domu/mieszkania.")]
        [Display(Name = "Numer domu/mieszkania")]
        public string HouseNumber { get; set; }

        [Required(ErrorMessage = "Proszę podać numer telefonu.")]
        [Display(Name = "Numer telefonu")]
        public string PhoneNumber { get; set; }
    }

Наконец, я перегрузил свою функцию сохранения для работы с новыми моделями

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

Передача сущностей в представление не является хорошей практикой, и в зависимости от того, что вы делаете с ними, когда они возвращаются из представления, это может подвергнуть вас фальсификации данных. Ваша «TableViewModel» должна состоять только из сплюснутых полей гостя и контакта или GuestViewModel и ContactViewModel, отображающих только те ключи и детали, которые необходимо отобразить / отредактировать. Объекты предназначены для связи с DbContext. Помещение ссылки на них в модель представления лишает их значения. Когда вы передаете их обратно в контроллер, они становятся просто экземплярами POCO, которые десериализованы из данных JSON, поступающих из представления. У них нет отслеживания изменений и т. Д., Чего можно ожидать от использования сущностей, пока они только что загружены из DbContext. Вы можете присоединить их к DbContext, но вам придется вручную установить состояние объекта на «Изменено», иначе контекст не будет знать, что объект был изменен.

Ваша проблема в ее нынешнем виде, вероятно, будет связана с тем, что делает ваш метод SaveGuest.

Типичный жизненный цикл MVC для данных будет примерно равен:

Просмотр:

  • Загрузка сущностей из контекста
  • Заполнение просмотра моделей
  • Перейти к просмотру.

Обновление:

  • Проверка модели представления по текущему сеансу
  • Загрузка сущностей из контекста на основе ключей
  • Убедитесь, что модель представления не устарела (дата последнего мода / отметка времени / версия строки соответствуют)
  • Проверка и копирование только тех деталей, которые можно обновить из модели представления в сущность
  • SaveChanges.

Скорее всего, если вы не видите изменений, вы, вероятно, присоединяете сущность к новому контексту, не устанавливая состояние сущности в "Изменено". Обратите внимание, что не рекомендуется, поскольку вы безоговорочно доверяете данным, поступающим от клиента. Например, вы можете намереваться видеть только то, что пользователь изменил данные, для которых вы создали элементы управления, но прикрепляя объект, вы оставляете дверь открытой для перехвата POST-вызова или воспроизведения любых / всех данных на объекте, являющемся объектом. изменено. В любом случае вам нужно будет загрузить существующую сущность, чтобы убедиться, что ничего, что не должно было быть изменено, не было изменено. Другая возможность состоит в том, что вы можете перезагрузить сущность, не осознавая, не копируя значения из сущности вашей модели представления перед вызовом SaveChanges, или добавляя сущность в контекст, думая, что она обновит существующую строку, но она сохраняет совершенно новую строку с новый ПК.

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