Модель ASP.NET MVC, связывающая дочерние объекты - PullRequest
3 голосов
/ 17 мая 2011

Я работаю над приложением ASP.NET MVC 3.У меня есть класс Comment, который инкапсулирует класс Post (каждый комментарий связан с публикацией в блоге), есть метод действия для редактирования комментария, как показано ниже:

    [HttpPost]
    [Authorize(Users = admin)]
    public string EditComment(Comment comment)
    {
        //update the comment by calling NHiberante repository methods
    }

Из javascript, который я публикуютолько значения объекта комментария, такие как идентификатор комментария, описание к серверу, поэтому при привязке я вижу свойство Post внутри объекта комментария как нулевое, а при выполнении ModelState.IsValid я получаю пустые ошибки.У меня вопрос, как я могу привязать объект публикации к комментарию?Я могу передать идентификатор записи на сервер вместе с другими значениями.

Спасибо Виджая Ананд

Ответы [ 2 ]

4 голосов
/ 17 мая 2011

Укажите дополнительные поля

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

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

предположим, у вас есть классы:

public class Post
{
    public int Id { get; set; }

    [Required]
    public string Title { get; set; }

    public string Content { get; set; }
}

public class Comment
{
    public int Id { get; set; }

    [Required]
    public string Author { get; set; }

    [Required]
    public string Content { get; set; }

    public Post Post { get; set; }
}

Обычный браузер POST

Что вам нужно сделать, это добавить поля постов (скрытого типа) в вашу форму. Я не знаю, как вы создали свою форму, используете ли вы строгие представления или нет ... Во всяком случае. Ваши входные данные должны иметь имена:

  • Post.Id (для добавления нового комментария к конкретному сообщению
  • Post.Title (потому что я установил его как требуется, но вы можете поместить сюда любой фиктивный текст, если все, что вы будете использовать, это Post.Id; заголовок просто необходимо установить, чтобы проверка модели не выполнялась обязательно)
  • Автор - видимый (это комментарий автора)
  • Контент - видимый (это комментарий)

Не важно, создаете ли вы эти поля с помощью Html-помощников или вручную. Связыватель модели по умолчанию сможет создать экземпляр объекта post, и проверка вашей модели не завершится неудачей.

Ajax POST

Если вы публикуете свои комментарии с помощью Ajax, вы можете сделать то же, что описано в предыдущем примере, и просто использовать функцию jQuery .serialize(), которая сериализует поля формы при вызове $.ajax().

Но вы также можете программно собрать все поля, используя Javascript, и точно так же отправить эти данные на сервер. Вы можете просто создать объект JSON:

var comment = {
    Author: $("#Author").val(),
    Content: $("#Content").val(),
    Post: {
        Id: $("#Post_Id").val(),
        Title: $("#Post_Title").val()
    }
};

$.ajax({
    url: "someURL",
    type: "POST",
    data: $.toDictionary(comment),
    success: function(data) {
        // probably get a partial view with comment you can append it to comments
    },
    error: function(xhr, status, err) {
        // process error
    }
});

Здесь используются две вещи, требующие пояснения:

  1. Обработка ошибок Ajax также может потреблять недопустимые ошибки состояния модели (ошибка проверки модели) и может быть выполнена таким образом .

  2. Преобразование сложного (многоуровневого) объекта JSON было выполнено с помощью специального плагина $.toDictionary(), который можно найти здесь и предоставляет возможность просто использовать сложные объекты JSON, которые Понимается Asp.net MVC по умолчанию модель связующего. Также подходит для дат и списков.

0 голосов
/ 17 мая 2011

Я думаю, что вы ищете методы TryUpdateModel или UpdateModel на контроллере. Вы можете связать, передав Комментарий в качестве аргумента (как вы делаете в вашем примере) или вызвав методы UpdateModel.

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

Я бы не выглядел примерно так:

       [HttpPost]
       [Authorize(Users = admin)]
        public string EditComment(int id, FormCollection form)
        {
               //update the comment by calling NHiberante repository methods

               // Fetch comment from DB
                var comment =  NHibernateHelper.Get<Comment>(id);

                // Update the comment from posted values
                TryUpdateModel(comment);

                // Handle binding errors etc.
                if (!ModelState.IsValid)
                {
                    // On error
                }

            // Commit to DB
            NHibernateHelper.Update<Comment>(comment);


            //Done!



        }

Я также использую NHibernate, и он прекрасно работает с этой реализацией.

...