Как я могу поддержать условную проверку свойств модели - PullRequest
1 голос
/ 06 апреля 2010

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

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

Некоторые подходы, о которых я могу подумать, аналогичны частичной проверке Стива Сандерсона .

Где бы я очищал ошибки модели в фильтре OnActionExecuting, основываясь на том, какая версия формы была активной.

Другой подход, о котором я думал, состоит в том, чтобы разбить модель на части, используя что-то вроде

class FormModel
{

public Form1 Form1Model {get; set;}
public Form2 FormModel {get; set;}
}

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

У кого-нибудь есть хорошее предложение по этому поводу?

1 Ответ

3 голосов
/ 06 апреля 2010

У меня был достаточный успех при использовании ModelBinders для удаления ненужных ошибок из ModelState.

Вот пример для подшивки модели Address. В пользовательском интерфейсе у меня есть <SELECT> для штатов США, но это скрыто, когда страна не является 'США' в пользу текстового поля <INPUT ID=StateOrProvince>.

Связыватель моделей смотрит на страну и удаляет ненужные значения.

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

Подсказка: У вас может быть столько связывателей моделей, сколько вы хотите скрыть от деталей вашей общей модели. Например - в моей модели 2 Address объекта, и каждый из них автоматически применяет это поведение.

Регистрация:

ModelBinders.Binders[typeof(UI.Address)] = new AddressModelBinder();

ModelBinder:

public class AddressModelBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        base.OnModelUpdated(controllerContext, bindingContext);

        // get the address to validate
        var address = (Address)bindingContext.Model;

        // remove statecd for non-us
        if (address.IsUSA)
        {
            address.StateOrProvince = string.IsNullOrEmpty(address.StateCd) ? null : CountryCache.GetStateName(address.StateCd);
            bindingContext.ModelState.Remove(bindingContext.ModelName + ".StateOrProvince");
        }
        else
        {
            address.StateCd = null;
            bindingContext.ModelState.Remove(bindingContext.ModelName + ".StateCd");
        }


        // validate US zipcode
        if (address.CountryCode == "US")
        {
            if (new Regex(@"^\d{5}([\-]\d{4})?$", RegexOptions.Compiled).Match(address.ZipOrPostal ?? "").Success == false)
            {
                bindingContext.ModelState.AddModelError(bindingContext.ModelName + ".ZipOrPostal", "The value " + address.ZipOrPostal + " is not a valid zipcode");
            }
        }

        // all other modelbinding attributes such as [Required] will be processed as normal
    }
}
...