代码之家  ›  专栏  ›  技术社区  ›  Scott Baker

为什么我的mvc项目中没有序列化此属性?

  •  0
  • Scott Baker  · 技术社区  · 7 年前

    abstract 从我的 View Controller

    我的抽象类型有一个 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 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 块状 在其 ValueProvider.FormValueProvider 块状 财产——但是 Name 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 helper只生成通常的标签、基于类型(枚举、字符串等)的编辑器和验证消息。枚举的EditorTemplate如下所示:

    @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 回复  |  直到 7 年前
        1
  •  0
  •   IPValverde    7 年前

    您的select元素似乎没有呈现 name 元素的属性。没有 只需在浏览器中编辑HTML并添加一个属性,即可对其进行双重检查 name="BlockType" 选择输入,然后尝试发布表单以查看其是否有效。