Нельзя использовать TypeConverter и пользовательский шаблон отображения/редактора вместе?

Сценарий

Предположим, у меня есть следующие два класса моделей:

public class ProductColor
{
    public long Id { get; set; }
    public string Name { get; set; }
}

public class Product
{
    public long Id { get; set; }
    public string Name { get; set; }

    public long ProductColorId { get; set; }
    public virtual ProductColor ProductColor { get; set; }
}

Теперь в форме для создания нового продукта у меня может быть эта строка для поля цвета...

@Html.EditorFor(model => model.ProductColor)

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

@model MyProject.Models.ProductColor
@using (var db = new MyProject.Models.MyDbContext())
{
    @Html.DropDownList("", new SelectList(db.ProductColors, "Id", "Name", Model))
}

До сих пор это работает. Но теперь, если я отправляю эту форму создания, я получаю эту ошибку проверки:

Преобразование параметра из типа «System.String» в тип «MyProject.Models.ProductColor» завершилось неудачно, так как ни один преобразователь типов не может преобразовать эти типы.

Конечно, это связано с тем, что HTTP-запрос содержит идентификатор цвета в виде строки (например, "1"), и потребуется некоторый код, чтобы превратить его в фактический экземпляр ProductColor. Поэтому я написал TypeConverter...

[TypeConverter(typeof(ProductColor.PCTypeConverter))]
public class ProductColor
{
    public long Id { get; set; }
    public string Name { get; set; }

    public class PCTypeConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string) ? true : base.CanConvertFrom(context, sourceType);
        }
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (value.GetType() == typeof(string))
                using (var db = new MyDbContext())
                    return db.ProductColors.Find(Convert.ToInt64(value));
            return base.ConvertFrom(context, culture, value);
        }
    }
}

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

Проблема

Я не могу заставить оба работать. Либо у меня есть преобразователь типов, и в этом случае я не получаю раскрывающийся список (поскольку шаблон пользовательского редактора никогда не вызывается), либо у меня нет преобразователя типов, и в этом случае проверка не выполняется при отправке запроса. .

Каково правильное решение этого?


person Timwi    schedule 15.02.2012    source источник


Ответы (1)


  • Вместо

    @Html.EditorFor(model => model.ProductColor)
    

    обратитесь к полю ID:

    @Html.EditorFor(model => model.ProductColorId)
    
  • Аннотируйте это поле идентификатора атрибутом UIHint, содержащим имя типа (точнее, имя пользовательского шаблона редактора):

    public class Product
    {
        public long Id { get; set; }
        public string Name { get; set; }
    
        [UIHint("ProductColor")]
        public long ProductColorId { get; set; }
        public virtual ProductColor ProductColor { get; set; }
    }
    
  • Измените шаблон пользовательского редактора, чтобы он использовал long? в качестве типа модели:

    @model long?
    @using (var db = new MyProject.Models.MyDbContext())
    {
        @Html.DropDownList("",
            new SelectList(db.ProductColors, "Id", "Name", Model))
    }
    
  • Избавьтесь от TypeConverter.

person Timwi    schedule 15.02.2012