MVC 3: свойство списка сообщений AJAX модели - PullRequest
0 голосов
/ 23 октября 2011

У меня проблемы с публикацией вызова ajax с моей моделью, у которой есть список.

Моя модель:

public class MyListItem
{
    public int Id { get; set; }
    public string Value { get; set; }
}

public class MyModel
{
    public int Integer { get; set; }
    public string Str { get; set; }
    public List<MyListItem> MyList { get; set; }        

    public MyModel()
    {
        Str = "Initial";
        Integer = 1;
    }
}

, на мой взгляд, я пытаюсь отобразитьперечислить элементы MyList как:

    <div>
    @{
            if (Model.MyList != null)
            { 
                int i = 0;
                foreach (var item in Model.MyList)
                {                       
                    <label>@item.Value</label>
                    @Html.Hidden("MyList[" + i + "].Id", item.Id);
                    @Html.TextArea("MyList[" + i + "].Value", item.Value, 1, 10, new { Value = item.Value });
                    <div />

                    i++;
                }
            }
    }
</div>

это представление является частичным и вызывается из "основного" представления следующим образом:

<form id="mine2">
    @{Html.RenderPartial("Test2", Model);}
</form>

Моя запись на ajax:

    function OnAddToListAjax() {
    var actionUrl = '@Url.Action("AddToList", "Test1")';
    var alist = @Html.Raw(Json.Encode(Model));

    try
    {
        $.ajax(
        {
            url: actionUrl,
            type: "POST",
            dataType: "HTML",
            contentType: 'application/json',
            processData: false,
            //data: JSON.stringify({myModel: existing, list: alist}),
            data: JSON.stringify({myModel: alist}),
            traditional: true,
            success: function(result) {
                //alert(result);
                $('#mine2').html(result);
            },
            error: function (req, status, error) {
                HandleError(req);
            }
        });
    }
    catch (err)
    {
        alert(err);
    }
}

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

        [HttpPost]
    public ActionResult AddToList(MyModel myModel)//, MyList list)
    {
        try
        {

            //var list = new MyList();
            if (myModel.MyList == null)
                myModel.MyList = new MyList();
            myModel.Str += " Changed";

            //throw new Exception("This is broken!");
            myModel.MyList.Add(new MyListItem { Id = myModel.MyList.Count, Value = string.Format("Item {0}", myModel.MyList.Count) });
            //myModel.MyList = list;

            return PartialView("Test2", myModel);
        }
        catch (Exception ex)
        {
            myModel.ErrorModel = new ErrorModel() { ErrorDetails = "Error adding to list", ErrorString = ex.Message };
            return PartialView("Test2", myModel);

        }
    }

эта концепция отлично работает для меня при использовании прямого свойства моей модели.например, если я пытаюсь установить / получить свойство Str.Однако для элементов MyList они, кажется, никогда не сериализуются должным образом в команде Json.Он сохраняет значения, которые были частью оригинальной модели.т.е. когда я в первый раз вызываю это, MyList имеет значение null, поэтому я создаю его и возвращаю как часть результата действия.Это показывает значения в порядке.Однако, если я вручную отредактирую значение и повторно отправлю его, то публикуемое значение будет таким же, как первоначально было получено.

Я полагаю, что это возможно связано с именем, которое я даю TextArea, иэто не может быть решено должным образом.Используя Firebug, источником для одной из указанных текстовых областей является:

<textarea id="MyList_0__Value" rows="1" name="MyList[0].Value" cols="10" value="Item 0">Item 0</textarea>

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

ТИА

1 Ответ

7 голосов
/ 23 октября 2011

Я бы порекомендовал вам использовать шаблоны редактора.Таким образом, вы можете заменить цикл foreach, который вы написали в частичном представлении, следующим образом:

@model MyModel
<div>
    @if (Model.MyList != null)
    {
        @Html.EditorFor(x => x.MyList)
    }
</div>

, а затем определить шаблон редактора для него, который будет отображаться для каждого элемента списка (~/Views/Test1/EditorTemplates/MyListItem.cshtml или~/Views/Shared/EditorTemplates/MyListItem.cshtml):

@model MyListItem
@Html.LabelFor(x => x.Value, Model.Value)
@Html.HiddenFor(x => x.Id);
@Html.TextAreaFor(x => x.Value, 1, 10);

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

Теперь на главном экране вы можететакже используйте шаблон редактора вместо частичного:

@model MyModel
@using (Html.BeginForm("AddToList", "Test1", FormMethod.Post, new { id = "myForm" }))
{
    @Html.EditorForModel()
}

, и тогда шаблон редактора, который я показал ранее, будет помещен по соглашению в ~/Views/Test1/EditorTemplates/MyModel.cshtml или ~/Views/Shared/EditorTemplates/MyModel.cshtml.

OK, поэтомупока все хорошо.Последний шаг - отправить запрос AJAX.Это можно сделать в отдельном файле JavaScript:

var myForm = $('#myForm');
$.ajax({
    url: myForm.attr('action'),
    type: myForm.attr('method'),
    data: myForm.serialize(),
    success: function(result) {
        $('#mine2').html(result);
    },
    error: function (req, status, error) {
        HandleError(req);
    }
});

Чистота и простота.

Теперь, когда мы очистили представление и JavaScript, мы должны очистить действие контроллера, где вашеИсходная проблема исходит от.Таким образом, в вашем действии контроллера вы пытаетесь изменить значения POST.Проблема в том, что HTML-помощники используют значения ModelState при связывании, а после этого они используют модель.Это по замыслу.Таким образом, значения, введенные в вашу модель, полностью игнорируются помощниками, и вы видите старые значения , которые были отправлены в действие контроллера.Сначала вам придется удалить их из состояния модели.

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