MVC 5 Создание объектов внешнего ключа при создании первичной сущности

#c# #asp.net-mvc #entity-framework

#c# #asp.net-mvc #entity-framework

Вопрос:

Я совершенно новичок в MVC и asp.net с Entity Framework, поэтому я уверен, что большая часть моих проблем связана с незнанием надлежащей терминологии для того, что я пытаюсь сделать.

У меня есть таблица / объект базы данных «Address», которая является адресом улицы. Вместо того, чтобы иметь поля уличного адреса в каждой сущности, с которой связан адрес, у меня просто есть столбец внешнего ключа, который указывает на правильный адрес в таблице адресов.

Для моей модели представления создания местоположения у меня есть следующее

 public class LocationCreationViewModel
{
    public address Address { get; set; }
    [Key]
    public location Location { get; set; }

}
  

Вероятно, стоит отметить, что эта модель представления «создана вручную», в то время как объекты-члены address и location управляются entity framework

Мое созданное представление содержит все данные о местоположении, а затем включает представление с частичным адресом, которое отображается с Html.Partial("_AddressCreate", Model.Location)

В данный момент происходит то, что LocationCreationViewModel, возвращаемый в Create(model) функции, является LocationCreationViewModel равным null, или каждое из полей равно null. В любом случае, ни один из данных из представления не заполняется в модели представления.

Чего я хочу, так это чтобы я вернул 2 адреса, добавил их в таблицу адресов в базе данных, затем добавил свой заказ в базу данных заказов с полями адресов FK, указывающими на 2 вновь созданных адреса.

Я использую MVC5 и EF6 в Visual Studio 2017

Create.cshtml

 @model MyWeb.Models.LocationCreationViewModel

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

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

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

    <div class="form-group">
        @Html.LabelFor(model => model.Location.address, "address", htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownList("address", null, htmlAttributes: new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.Location.address, "", new { @class = "text-danger" })
        </div>
    </div>
    @Html.Partial("_AddressPartial", Model.Address)

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

<div>
    @Html.ActionLink("Back to List", "Index")
</div>
  

_AddressPartial.cshtml

 @model MyWeb.Data.address

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


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

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


    </div>
  

LocationController::Создать

 [MyWebAuthorize(MyWebRole = MyWebRole.Admin)]
        public ActionResult Create()
        {
            ViewBag.address = new SelectList(db.addresses, "id", "country");
            ViewBag.id = new SelectList(db.inventories, "locationID", "locationID");

            LocationCreationViewModel model = new LocationCreationViewModel();
            return View(model);
        }


[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Create( LocationCreationViewModel location)
        {
            if (ModelState.IsValid)
            {
                db.addresses.Add(location.Address); //null reference exception here
                db.locations.Add(location.Location);

                await db.SaveChangesAsync();
                return RedirectToAction("Index");
            }

            ViewBag.address = new SelectList(db.addresses, "id", "country", location.Location.address);
            ViewBag.id = new SelectList(db.inventories, "locationID", "locationID", location.Location.id);
            return View(location);
        }
  

Комментарии:

1. Показать _AddressCreate.cshtml и просмотреть, где ShipmentViewModel создается. И действие контроллера Create , при котором вы return View("...", new ShipmentViewModel());

2. @AlexanderYakushev я добавил немного кода.

Ответ №1:

Autobinder не удалось связать данные формы из-за имени поля Location в модели представления. Я предполагаю, что это связано с тем, что Location является частью маршрута страницы. Т.е. для LocationController маршрут будет /Location/Create

В любом случае переименование LocationCreationViewModel::Location в LocationCreationViewModel::Locus все исправило.