Связанный объект данных в нулевом EF - PullRequest
2 голосов
/ 16 апреля 2019

Здравствуйте, недавно я обновил свой проект с ядра 2.1 до 2.2, после этого, когда объект с дочерним элементом отправляется из формы (Редактировать), приходит объект с нулевым значением (см. Изображение ниже), а ModelState.IsValid всегдаfalse, потому что проверяет нулевое значение в дочернем классе, ПОМОГИТЕ!

https://i.ibb.co/hsmpc43/Screen-Shot-2019-04-16-at-11-03-17-AM.png

вот мой класс:

public class New : BaseEntity
{
    public string Title { get; set; }
    public string Message { get; set; }
    [ForeignKey("TowerID"), Display(Name = "Edificio")]
    public virtual Tower Tower { get; set; }
    public int TowerID { get; set; }

}

мой контроллер:

[BreadCrumb(Title = "Editar", Order = 1)]
public IActionResult Edit(int id)
{
    var news = _newBL.GetById(id);
    PopulateDropDowns();
    return View(news);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(New value)
{
    if (ModelState.IsValid)
    {
        value.Resources = _files;
        await _newBL.Update(value);
        return RedirectToAction(nameof(Index));
    }
    PopulateDropDowns();
    return View(value);
}

и моя форма встречи на высшем уровне:

<form asp-action="Edit" onsubmit="return disableButton(this);">

            <div class="form-row">
                <div class="form-group col-md-3">
                    <label asp-for="TowerID"></label>
                    <div class="custom-select">
                        <select asp-for="TowerID" class="form-control" asp-items="ViewBag.TowerID">
                            <option>Seleccione</option>
                        </select>

                    </div>
                    <span asp-validation-for="TowerID" class="text-red"></span>
                </div>
                <div class="form-group col-md-2">
                    <label asp-for="CreatedDate">Creado en</label>
                    <label asp-for="CreatedDate" class="input-readonly" readonly>@Model.CreatedDate</label>
                    <input type="hidden" asp-for="CreatedDate" />
                </div>
            </div>
            <div class="form-row">
                <div class="form-group col-md-12">
                    <label asp-for="Title"></label>
                    <input asp-for="Title" class="form-control" placeholder="@ViewData.ModelMetadata.Placeholder" />
                    <span asp-validation-for="Title" class="text-red"></span>
                </div>
            </div>
            <div class="form-row">
                <div class="form-group col-md-12">
                    <label asp-for="Message"></label>
                    <textarea id="summernote" asp-for="Message" class="form-control" rows="3"></textarea>
                    <span asp-validation-for="Message" class="text-red"></span>
                </div>
            </div>
            <div class="form-row">
                <button type="submit" class="btn green m-1" id="save"><i class="fas fa-save"></i> Guardar</button>
                <button asp-action="Index" type="submit" class="btn blue-darken-1 m-1"><i class="fa fa-arrow-left"></i> Atras</button>
                <a  class="btn red m-1" data-toggle="modal" data-target="#dangerModal">
                    <i class="fa fa-trash"></i> Eliminar
                </a>
            </div>
        </form>

Это только начинается, когда я обновляюсь до ядра 2.2 и когда я отправляю форму редактирования с новыми значениями.

спасибо заранее

ОБНОВЛЕНИЕ:

Я попытался перейти на ядро ​​2.1 и работает, но когда я переключаюсь обратно на 2.2, начало происходить, объект башни прибывает из бритвы POST со всеми нулевыми значениями, но новоститипы не (см. изображение)

Ответы [ 2 ]

2 голосов
/ 16 апреля 2019

Ну, вы публикуете идентификатор только для Tower, и это действительно заполняется.Больше ничего для Tower не публикуется, поэтому, конечно, все остальные свойства имеют значение null или значение по умолчанию.Я не уверен, почему вы думаете, что это только начинает происходить в 2.2, как это всегда было.На самом деле, это будет так, независимо от того, какую платформу вы используете.Это может быть Django или Ruby on Rails, и реквизиты Tower все равно будут нулевыми, потому что вы не публикуете ни одного из них.

HTTP - это протокол без сохранения состояния.Ничего не существует, кроме того, что приходит через сам запрос.Нет никакой памяти о том, что эти свойства использовали , потому что нет сведений о том, что был даже сделан предыдущий запрос.Вы можете вставить что-то вроде сеансов здесь, но это по сути фальшивое состояние.Сервер сохраняет данные, связанные с идентификатором сеанса, а затем передает этот идентификатор сеанса клиенту через cookie-файл.Затем клиент должен возвращать этот файл cookie, содержащий идентификатор сеанса, при каждом последующем запросе для восстановления сеанса.Даже в этом случае данные, по сути, все еще являются частью запроса, они просто приходят в качестве идентификатора для определенного набора сохраненных данных на стороне сервера, а не для всего набора данных.

В любом случае, это легко решается с помощью нескольких настроекв свой код вы должны внести независимо.Во-первых, вы никогда не должны напрямую связываться с классом сущностей.Для этого есть ряд причин, но главная проблема заключается в чрезмерной публикации.Имея код, который есть у вас сейчас, клиент может изменить отправленные данные, чтобы изменить что-то вроде идентификатора вашей сущности, и вы в конечном итоге измените сущность с этим id, а не той, которая была на самом делередактируется.Другое правило, связанное с этим, заключается в том, что вы никогда не должны напрямую сохранять что-либо, опубликованное пользователем, по многим из тех же причин.

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

public async Task<IActionResult> Edit(NewViewModel value)
{
    if (!ModelState.IsValid)
    {
        PopulateDropDowns();
        return View(value);            
    }

    var entity = await _newBL.GetById(id);
    if (entity == null)
        return NotFound();

    entity.Title = value.Title;
    entity.Message = value.Message;
    entity.TowerID = value.TowerID;
    entity.Resources = _files;

    await _newBL.Update(entity);
    return RedirectToAction(nameof(Index));
}

Об отображении можно позаботиться с помощью библиотеки, подобнойAutoMapper, если вы предпочитаете.

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

Чтобы решить эту проблему, вам нужно включить связанные данные (дочерние) в GetById (), добавив что-то вроде этого .Include(blog => blog.Posts) в свою функцию
Документация: https://docs.microsoft.com/en-us/ef/core/querying/related-data
или вам нужно активировать lazyloading (по умолчанию lazyloading отключен)
см. больше: https://www.learnentityframeworkcore.com/lazy-loading

Обновление:
В случае, еслимодель обнуляется, вам нужно добавить скрытый ввод для всех элементов модели, чтобы сохранить их значения при отправке формы.
пример:
<input type="hidden" asp-for="Tower.Id" />

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