Как получить имена ключей модели / свойства модели для совпадения? - PullRequest
3 голосов
/ 20 мая 2011

У меня есть приложение MVC3, я использую EF4.1 Code First и POCO классы.

Мой вопрос состоит в том, чтобы избавиться от жестко запрограммированных «PropertyNames» в моем классе POCO, а также предварительно исправить его с соответствующими значениями в ModelState, чтобы сообщение проверки появилось правильно.

В моем классе POCO есть метод, который выглядит следующим образом. Вы заметите, что я также использую код «DataAnnotations.Validator» для повторного использования проверки аннотаций данных.

public class TaxCode : ModelBusinessObjectBase
{
    //...

    [Required]
    [DataType(DataType.Date)]
    [DisplayName("Effective Date")]        
    public DateTime EffectiveDate
    {
        get { return _effectiveDate; }
        set { _effectiveDate = value; }
    }    

    [Required]
    [DataType(DataType.Date)]
    [DisplayName("Expiry Date")]        
    public DateTime ExpiryDate
    {
        get { return _expiryDate; }
        set { _expiryDate = value; }
    }    

    //...

    public override IEnumerable<ValidationResult> GetValidationResults()
    {
        //---- data annotation validation ----
        ValidationContext validationContext = new ValidationContext(this, null, null);
        IList<ValidationResult> dataAnnotationValidationResults = new List<ValidationResult>();
        bool isValid = Validator.TryValidateObject(this, validationContext, dataAnnotationValidationResults, true);


        foreach (ValidationResult dataAnnotationValidationResult in dataAnnotationValidationResults)
            yield return new ValidationResult(dataAnnotationValidationResult.ErrorMessage, dataAnnotationValidationResult.MemberNames);

        //---- custom business rule validation ----
        // expiry date must be greater than effective date
        if (ExpiryDate <= EffectiveDate)
        {   
            yield return new ValidationResult("Expiry Date must be after Effective Date", new [] {"EffectiveDate", "ExpiryDate"});
        }

        yield break;
    }

В моем слое обслуживания я в конце концов назову что-то вроде этого:

    public bool TryValidate(TaxCode domainObject)
    {
        if (!domainObject.IsValid) 
        {   
            _validationDictionary.AddValidationResults(domainObject.GetValidationResults());
            isValid = false;
        }
        return isValid;
    }

И используя «ModelStateWrapper», код делает это:

    public virtual void AddValidationResults(IEnumerable<ValidationResult> validationResults)
    {

        foreach (ValidationResult validationResult in validationResults)
        {
            _modelState.AddModelError(validationResult.MemberNames.First(), validationResult.ErrorMessage);
        }
    }

Моя модель просмотра такова:

public class TaxCodeViewModel : IPersistantBusinessObjectViewModel<TaxCode>
{
    public TaxCodeViewModel()
    {
    }

    public TaxCodeViewModel(TaxCode domainObj)
    {
        this.BusinessObject = domainObj;
    }
}

И мой взгляд выглядит примерно так:

   <%@ Control Language="C#" AutoEventWireup="true"               Inherits="System.Web.Mvc.ViewUserControl<TaxCodeViewModel>" %>

   //...

    <% using (Html.BeginForm()) {%>

        <%:Html.ValidationSummary(false, "Unable to save. Please correct the errors and try again.")%>


        //...

        <div class="editor-label">
            <%:Html.LabelFor(model => model.BusinessObject.EffectiveDate)%>
        </div>
        <div class="editor-field">
            <%: Html.EditorFor(model => model.BusinessObject.EffectiveDate)%>
            <%: Html.ValidationMessageFor(model => model.BusinessObject.EffectiveDate)%>
        </div>
        <br />  
        <div class="editor-label">
            <%: Html.LabelFor(model => model.BusinessObject.ExpiryDate)%>
        </div>
        <div class="editor-field">
            <%: Html.EditorFor(model => model.BusinessObject.ExpiryDate)%>
            <%: Html.ValidationMessageFor(model => model.BusinessObject.ExpiryDate)%>
        </div>
        <br />  
        //...

Мой вопрос:

  1. Как избежать использования жестко закодированных строк с именами свойств «Дата истечения срока действия»?

  2. Из-за ViewModel ожидает, что ключ ModelState будет "BusinessObject.ExpiryDate". Как мне сделать так, чтобы мои свойства соответствовали? Как добавить префикс или удалить автоматически добавленный префикс?

  3. Обратите внимание, что в настоящее время я использую validationResult.MemberNames.First ()). В моем случае я хочу только одно сообщение в сводке проверки, но я бы хотел выделить ОБА свойства. то есть только одно сообщение для «.validation-summary-errors», но оба поля выделены для элементов «.input-validation-error» и «.field-validation-error» в DOM.

Спасибо,

1 Ответ

0 голосов
/ 28 июня 2011

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

Для выделения проблемы вы можете использовать java-скрипт или реализовать некоторую полезную функцию, чтобы проверить, есть ли у модели ошибка в каком-либо поле, и вернуть какое-нибудь имя класса css.Что-то вроде пара.

 <div class="editor-field <%: Html.HasValidationMessage(model => model.BusinessObject.ExpiryDate)%>">
            <%: Html.EditorFor(model => model.BusinessObject.ExpiryDate)%>
            <%: Html.ValidationMessageFor(model => model.BusinessObject.ExpiryDate)%>
 </div>
...