Почему это свойство не сериализуется в моем проекте MVC? - PullRequest
0 голосов
/ 01 февраля 2019

Конечная цель заключается в сериализации типа abstract из моего View для использования моим Controller.

Мой абстрактный тип имеет свойство enum, имена которого соответствуют именамконкретные производные типы;так я определю, какой конкретный тип выбрать.Значение этого enum устанавливается в конструкторе абстрактного типа с помощью отражения:

[JsonConverter(typeof(BlockJsonConverter)]
public abstract class Block{

   [NotMapped, JsonProperty]
   public BlockType BlockType {get; set;}
   public string Name {get;set:}
   public int Height{get;set;}
   public int Width {get;set;}
   public int Depth {get;set;}

   protected Block(){
      BlockType = Enum.TryParse(GetType().Name, out BlockType blocktype)
             ?? blocktype : BlockType.Unknown
   }
}

public enum BlockType {
   Long, Short, Tall, Unknown
}

public class Long    : Block { /*...*/ }
public class Short   : Block { /*...*/ }
public class Tall    : Block { /*...*/ }
public class Unknown : Block { /*...*/ }

Класс Block используется Entity Framework, но свойство BlockType не сохраняется в базе данных.поэтому свойство BlockType помечено атрибутом [NotMapped];однако, поскольку я хочу, чтобы свойство было подвергнуто циклическому переключению из представления в контроллер, я пометил его атрибутом [JsonProperty].

Я создал TestModelBinder для обработки десериализации из представленияКонтроллеру:

public class TestModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, 
       ModelBindingContext bindingContext, Type modelType)
    {
        return base.CreateModel(controllerContext, bindingContext,
            GetModelType(controllerContext, bindingContext, modelType));
    }

    protected override ICustomTypeDescriptor GetTypeDescriptor(
      ControllerContext controllerContext,ModelBindingContext bindingContext)
    {
        var modelType = GetModelType(controllerContext, bindingContext, bindingContext.ModelType);
        return new AssociatedMetadataTypeTypeDescriptionProvider(modelType)
                      .GetTypeDescriptor(modelType);
    }

    private static Type GetModelType(ControllerContext controllerContext, ModelBindingContext bindingContext,
        Type modelType)
    {
        if (modelType.Name == "Block")
        {
• breakpoint
           // get the value from bindingContext for BlockType
           // and return the concrete type based on that
        }
        return modelType;
    }
}

Когда я достигаю этой точки останова выше, bindingContext не имеет BlockType в ValueProvider.FormValueProvider для моего свойства BlockType - но * 1027Свойства *, Height, Width и Depth перечислены в соответствии с ожиданиями.

Все они перечислены одинаково в EditorTemplate:

@model Block
<div class="form-row">
    <div class="col">
        @Html.BootstrapEditorGroupFor(m => m.Name)
    </div>        
    <div class="col">
        @Html.BootstrapEditorGroupFor(m => m.BlockType)
    </div>
</div>
<div class="form-row">
    <div class="col">
        @Html.BootstrapEditorGroupFor(m => m.Height)
    </div>
    <div class="col">
        @Html.BootstrapEditorGroupFor(m => m.Width)
    </div>
    <div class="col">
        @Html.BootstrapEditorGroupFor(m => m.Depth)
    </div>
</div>

... а помощник BootstrapEditorGroupFor просто генерирует обычную метку, редактор на основе типа (enum, string и т. д.) и сообщение проверки.Шаблон Editor для перечислений приведен ниже:

@model Enum

@{
    var type = Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType) 
               ?? ViewData.ModelMetadata.ModelType;
}

<div class="form-group">
    <select class="form-control">
        @if (ViewData.ModelMetadata.IsNullableValueType)
        {
            <option selected="@ReferenceEquals(Model, null)">Not Specified</option>
        }
        @foreach (var value in Enum.GetValues(type))
        {
            <option selected="@value.Equals(Model)">@value</option>
        }
    </select>
</div>

1 Ответ

0 голосов
/ 04 февраля 2019

Ваш элемент select не отображает name элемента.Без атрибута name данные не будут сопоставлены с соответствующим свойством в вашей модели.Вы можете дважды проверить его, просто отредактировав HTML в вашем браузере и добавив атрибут name="BlockType" к выбранным данным и попробуйте опубликовать форму, чтобы проверить, работает ли она.

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