ASP.NET MVC2 Не удается получить полный идентификатор элемента - PullRequest
2 голосов
/ 05 сентября 2011

У меня есть строго типизированная форма просмотра для моей модели.Проблема в том, что я не могу получить правильные идентификаторы.В моей модели представления есть модели форм, поэтому я должен вызывать некоторые элементы, такие как:

<%: Html.TextBoxFor(m => m.Business.Business2)%>

Проблема заключается в следующем коде:

viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(partialFieldName)

Если для моего partFieldName указано «Business2»,возвращает «Business_Business2», но возвращает только «Business2».Однако, если я использую

<%: Html.EditorFor(x => x.Business) %>

, возвращается «Business_Business2».Я не могу использовать Html.EditorFor, так как у меня есть классы CSS для размещения на моих элементах формы.Я не могу сделать большую часть моих проверок на стороне клиента без правильного идентификатора, так что это действительно беспокоило меня.Есть идеи?

Вот мои коды:

Модели

public class BusinessModel
    {
        public string Business1 { get; set; }
        public string Business2 { get; set; }
    }

    public class AccountModel
    {
        public string Account1 { get; set; }

        [MustMatch("Account1")]
        public string Account2 { get; set; }
    }

    public class SampleWrappedModel
    {
        public BusinessModel Business { get; set; }
        public AccountModel Account { get; set; }
    }

Проверки

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public sealed class MustMatchAttribute : ValidationAttribute
    {
        private const string DefaultErrorMessage = "Must match {0}";

        public MustMatchAttribute(string propertyToMatch)
            : base(DefaultErrorMessage)
        {
            PropertyToMatch = propertyToMatch;
        }

        public string PropertyToMatch { get; private set; }

        public override string FormatErrorMessage(string name)
        {
            return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString, PropertyToMatch);
        }

        public override bool IsValid(object value)
        {
            throw new Exception("MustMatchAttribute requires the DataAnnotationsMustMatchValidator adapter to be registered"); 
        }
    }

    //Adapter class
    public class DataAnnotationsMustMatchValidator : DataAnnotationsModelValidator<MustMatchAttribute>
    {
        public DataAnnotationsMustMatchValidator(ModelMetadata metadata, ControllerContext context, MustMatchAttribute attribute)
            : base(metadata, context, attribute)
        {
        }

        public override System.Collections.Generic.IEnumerable<ModelValidationResult> Validate(object container)
        {
            var propertyToMatch = Metadata.ContainerType.GetProperty(Attribute.PropertyToMatch);
            if (propertyToMatch != null)
            {
                var valueToMatch = propertyToMatch.GetValue(container, null);
                var value = Metadata.Model;

                bool valid = Equals(value, valueToMatch);
                if (!valid)
                {
                    yield return new ModelValidationResult { Message = ErrorMessage };
                }
            }
        }

        public override System.Collections.Generic.IEnumerable<ModelClientValidationRule> GetClientValidationRules()
        {
            string propertyIdToMatch = GetFullHtmlFieldId(Attribute.PropertyToMatch);
            yield return new ModelClientMustMatchValidationRule(ErrorMessage, propertyIdToMatch);
        }

        private string GetFullHtmlFieldId(string partialFieldName)
        {
            ViewContext viewContext = (ViewContext)ControllerContext;
            return viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(partialFieldName);
        }
    }

    public class ModelClientMustMatchValidationRule : ModelClientValidationRule
    {
        public ModelClientMustMatchValidationRule(string errorMessage, string propertyIdToMatch)
        {
            ErrorMessage = errorMessage;

            ValidationType = "mustMatch";

            ValidationParameters.Add("propertyIdToMatch", propertyIdToMatch);
        }
    }

Ответы [ 2 ]

0 голосов
/ 06 сентября 2011

Я не могу использовать Html.EditorFor, так как у меня есть классы css для размещения на элементах формы.

Тогда вы могли бы написать собственный шаблон редактора. Итак, на ваш взгляд:

<%: Html.EditorFor(x => x.Business) %>

, а затем внутри ~/Views/Shared/EditorTemplates/BusinessModel.ascx:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BusinessModel>" %>
<%: Html.TextBoxFor(m => m.Business1) %>
<%: Html.TextBoxFor(m => m.Business2) %>
...

или, если вам не нравятся обычные места и названия для шаблонов, вы также можете настроить это:

<%: Html.EditorFor(x => x.Business, "MyBusinessTemplate") %>

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

Я бы порекомендовал вам всегда использовать EditorFor вместо TextBoxFor.

0 голосов
/ 05 сентября 2011

То, что TemplateInfo делает с методами GetFullHtmlFieldName и GetFullHtmlFieldId, просто предвосхищает HtmlFieldPrefix переданной частичной частоте имени. Если я правильно понял, вам нужен помощник, способный вернуть имя поля html из выражения labmda

 public static string GetHtmlFieldName<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
 {
     return ExpressionHelper.GetExpressionText(expression);
 }

И тогда вы можете использовать

Html.GetHtmlFieldName(m => m.Business.Business2)

Это вернет Business.Business2

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