ASP.NET MVC Переполнение форм - PullRequest
6 голосов
/ 04 января 2009

У меня есть контроллер с двумя действиями:

[AcceptVerbs("GET")]
    public ActionResult Add()
    {
        PrepareViewDataForAddAction();
        return View();
    }


[AcceptVerbs("POST")]
    public ActionResult Add([GigBinderAttribute]Gig gig, FormCollection formCollection)
    {
        if (ViewData.ModelState.IsValid)
        {
            GigManager.Save(gig);
            return RedirectToAction("Index", gig.ID);
        }
        PrepareViewDataForAddAction();
        return View(gig);
    }

Как вы видите, когда форма публикует свои данные, действие Add использует GigBinder (реализация IModelBinder)

В этом переплете у меня есть:

 if (int.TryParse(bindingContext.HttpContext.Request.Form["StartDate.Hour"], out hour))
        {
           gig.StartDate.Hour = hour;
        }
        else
        {
            bindingContext.ModelState.AddModelError("Doors", "You need to tell us when the doors open");
        }

Форма содержит текстовое поле с идентификатором «StartDate.Hour».

Как вы можете видеть выше, GigBinder проверяет, что пользователь ввел целое число в текстовое поле с идентификатором "StartDate.Hour". Если нет, то ошибка модели добавляется в состояние модели с помощью AddModelError.

Поскольку свойство gigs gigs.StartDate.Hour строго типизировано, я не могу установить его значение, например, "TEST", если пользователь ввел его в текстовое поле форм.

Следовательно, я не могу установить значение gigs.StartDate.Hour, поскольку пользователь ввел строку, а не целое число.

Поскольку действие Add возвращает представление и передает модель (возвращает View (gig);), если состояние модели недопустимо, когда форма повторно отображается с сообщениями проверки, значение «TEST» не отображается в текстовом поле , Вместо этого это будет значение по умолчанию gig.StartDate.Hour.

Как мне обойти эту проблему? Я действительно застрял!

Ответы [ 3 ]

2 голосов
/ 29 апреля 2010

Я думаю, что проблема в том, что ваша ViewModel недостаточно близко совпадает с вашим View. В MVC очень важно, чтобы ваша ViewModel максимально соответствовала вашему View.

В вашей ViewModel вы предполагаете целое число, но в вашем View вы используете TextBox для рендеринга свойства, которое разрешает любой вид текста. Здесь есть несоответствие, и трудности, с которыми вы сталкиваетесь, пытаясь отобразить их, являются признаком несоответствия.

Я думаю, вы должны либо:
1. Измените тип свойства ViewModel на string, а затем выполните проверку в контроллере, чтобы убедиться, что введенная строка фактически является числом или:
2. Измените элемент управления, который представление отображает, на элемент управления, который позволяет вводить число только через пользовательский элемент управления или проверку Javascript (как рекомендует @Qun Wang)

Лично я бы порекомендовал вариант 1. Таким образом, ViewModel не зависит от реализации View.

1 голос
/ 10 апреля 2010

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

1 голос
/ 06 января 2009

Не могли бы вы сделать это в вашем методе PrepareViewDataForAddAction? ..

if (!ViewData.ModelState.IsValid)
    {
        ViewData["StartDate.Hour"] = "Error";
    }

Другие поля в форме по-прежнему будут заполняться в зависимости от свойств объекта Gig.

...