Советы с динамическими формами в ASP.NET MVC - PullRequest
9 голосов
/ 24 июня 2009

Я работаю над визуализацией динамической формы в виде ASP.NET MVC, которая будет отвечать следующим требованиям:

  • Поля могут быть проверены
  • Состояние сохраняется, когда форма недействительна

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

  1. Поля формы определены с этими свойствами
    • Подсказка (метка рядом с полями)
    • Тип (текст, флажок, список рассылки и т. Д.)
    • Выбор (для полей списка)
    • IsRequired
    • RegularExpression (для текстовых полей)
    • Параметры отображения
    • Коллекция определений полей отправляется из контроллера в представление
    • Поля отображаются в HTML и отправляются в браузер
    • Форма отправляется обратно на сервер
    • A привязка пользовательской модели привязывает форму к коллекции определений полей, которая теперь содержит отправленные значения
    • Каждое поле проверено
    • При необходимости -> должно иметь значение
    • Если RegEx -> должно совпадать
    • Для каждого недопустимого поля в состояние модели добавляется сообщение об ошибке
    • Контроллер решает, что делать
    • Если все поля действительны
      • Делайте что угодно с полями и их значениями
    • Если одно или несколько полей недействительны
      • Отправить коллекцию полей обратно на просмотр
      • Снова визуализируйте поля с их ранее использованными значениями
      • Показать сводку проверки

Я не уверен, что делаю это лучше или проще. Будет ли такой подход доставить мне много проблем или даже работать? Что я могу сделать, чтобы улучшить это?

Ответы [ 4 ]

8 голосов
/ 16 сентября 2009

Я написал библиотеку классов, которая в основном делает именно то, что описывает мой psuedocode в моем вопросе. Отлично работает.

EDIT:

Я наконец-то нашел время для очистки моей библиотеки классов. Я добавил несколько новых функций и создал довольно хорошо документированное демонстрационное веб-приложение.

Все это размещено здесь на CodePlex . Надеюсь, это кому-нибудь поможет.

0 голосов
/ 25 июня 2009

Хотя я и не был экспертом, мне пришлось создать решение, в котором у моего основного объекта был список значений. Давайте назовем это Object A имеет список ApplicationValues, которые отображаются в базе данных. ApplicationValues ​​имеет ключ (поле формы, например, PhoneNumber) и значение.

Поскольку ApplicationValues ​​были EntitySet, мне пришлось создавать методы get и set для правильной обработки установки определенного ApplicationValue. У меня также был список ApplicationRules в моей базе данных, который определял, что эти значения приложения могут принимать.

Вот фрагмент кода, который может помочь вам разработать решение для ваших нужд.

public partial ApplicationValue
{
    public string Key;
    public string Value;
}

public partial ApplicationRule
{
    public string ValidationFormat;
    public string ValidationError;
    public bool Required;
}

public partial class A
{
    public void SetValue(string key, string value)
    {
        //ApplicationValues is the list of values associated to object A
        ApplicationValue v = ApplicationValues.SingleOrDefault
        (k => k.Key == key);

        //if we already have this value
        if (v != null)
        {   //...then we can simply set and return
            v.Value = value;
            return;
        }

        //else we need to create a new ApplicationValue
        v = new ApplicationValue
            {
                AffinityID = this.ID,
                Key = key,
                Value = value
            };

        ApplicationValues.Add(v);
    }

    public string GetValue(ApplicationField key)
    {
        return GetValue(key, String.Empty);
    }

    public string GetValue(ApplicationField key, string defaultValue)
    {
        if (ApplicationValues == null)
            return defaultValue;

        ApplicationValue value = ApplicationValues.SingleOrDefault
        (f => f.Key == key.ToString());

        return (value != null) ? value.Value : defaultValue;
    }

А затем для проверки формы я перебираю ApplicationRules (который определяет, является ли поле обязательным, содержит регулярное выражение и т. Д.) И сопоставляет его с FormCollection.

public ActionResult Details(FormCollection form)
{
    IList<ApplicationRule> applicationRules = //get my rules from the DB

    if (!(ValidateApplication(applicationRules, form, a)))
    {
        ModelState.AddModelError("message", "Please review the errors below.");
        return View(a);
    }
    ...
}

private bool ValidateApplication(IList<ApplicationRule> applicationRules,
                                 FormCollection form, A a)
    {
        //loop through the application rules
        foreach (ApplicationRule ar in applicationRules)
        {
            //try and retrieve the specific form field value using the key
            string value = form[ar.Key];

            if (value == null)
                continue;

            //set the model value just in case there is an error
            //so we can show error messages on our form
            ModelState.SetModelValue(ar.Key, ValueProvider[ar.Key]);

            //if this rule is required
            if (ar.Required)
            {   //...then check if the field has a value
                if (String.IsNullOrEmpty(value))
                {
                    ModelState.AddModelError(ar.Key, "Field is required");
                    continue;
                }
            }

            //if this rule has a validation format
            if (!String.IsNullOrEmpty(ar.ValidationFormat))
            {   //...then check the value is of the correct format
                Regex re = new Regex(ar.ValidationFormat);

                if (!re.IsMatch(value))
                {
                    ModelState.AddModelError(ar.Key, ar.ValidationError);
                    continue;
                }
            }

            a.SetValue(ar.Key, value);
        }

        return ModelState.IsValid;
    }
0 голосов
/ 25 июня 2009

Насколько динамичны ваши определения полей? Если они не меняются очень часто, вы можете использовать код dom для генерации модели и контроллера после создания определения. Я не пробовал это в ASP.NET MVC, но это может быть хорошим способом.

http://msdn.microsoft.com/en-us/library/y2k85ax6.aspx

В этой статье для генерации ActionLink используется код dom.

http://blogs.msdn.com/davidebb/archive/2009/06/01/a-buildprovider-to-simplify-your-asp-net-mvc-action-links.aspx#comments

0 голосов
/ 24 июня 2009

Я ни в коем случае не эксперт, но если вы новичок в ASP.NET MVC, то я рекомендую вам начать со встроенной функциональности, прежде чем переходить на собственную. Он выполняет большую часть того, что вы описали, за исключением того, что не поощряет определение / конструирование пользовательского интерфейса в контроллере, поскольку это является задачей представления.

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

Обновление: Другой способ взглянуть на это: спросите себя, почему вы используете MVC вместо классических методов построения ASP.NET, а затем посмотрите, соответствует ли предложенный вами подход этим причинам. Для меня разделение интересов было огромной причиной, а также детальный контроль над сгенерированным HTML, и я чувствую, что ваш подход может подорвать эти вещи.

Специально для вашего редактирования:

Шаги от 1 до конца противоречат парадигме MVC. Шаг 4, хорошо. Шаги с 5 по 7 в значительной степени являются стандартной практикой MVC и полностью поддерживаются платформой. Например, Выполнение простой проверки (C #) показывает пример проверки и представления сообщений об ошибках.

...