Не можете использовать TypeConverter и пользовательский шаблон отображения / редактирования вместе? - PullRequest
2 голосов
/ 15 февраля 2012

Сценарий

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

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);
        }
    }
}

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

Проблема

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

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

1 Ответ

2 голосов
/ 15 февраля 2012
  • Вместо

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

    см. Поле идентификатора:

    @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.

...