【问题标题】:IDictionary Property on model throwing System.InvalidCastException模型抛出 System.InvalidCastException 上的 IDictionary 属性
【发布时间】:2019-08-08 15:24:30
【问题描述】:

我有一个数据库模型,它使用.HasFlag 将设置存储为 32 位整数上的位。前端使用 AngularJs (1),可悲的是 does not allow bit-wise operations in expressions。因此,我创建了一个扩展方法来从 Enum 转换为每个标志的字典,以及它是否打开:

public static IDictionary<TEnum, bool> GetAllFlags<TEnum>(this TEnum obj) where TEnum: Enum
{
    return Enum.GetValues(typeof(TEnum))
        .Cast<TEnum>()
        .ToDictionary(flag => flag, flag => obj.HasFlag(flag));
}

我还创建了一个扩展方法来设置值,但它依赖于其他扩展方法并且它不会被调用(如下所述),所以为了简洁起见,我将它们排除在外。

这是一个使用枚举的示例(注意它的类型默认为 int 并且选项很少,但它确实为 0 定义了一个,这很奇怪)

public enum Settings
{
    None = 0,
    Setting1 = 1,
    Setting2 = 2,
    Setting3 = 4,
}

所有这些都暴露为像这样的对象上的属性

// SettingsFlags comes from another partial and is a Settings enum persisted to the database as an `INT`
public parital class Options
{
    IDictionary<Settings, bool> Flags {
        get { return SettingsFlags.GetAllFlags(); }
        set { SettingsFlags.SetAllFlags(value); } // this never gets called
    }
}

当为客户端序列化为JSON 时,这非常有用。但是,当在请求中收到它时,它会引发以下异常:

System.InvalidCastException: Specified cast is not valid.
   at System.Web.Mvc.DefaultModelBinder.CollectionHelpers.ReplaceDictionaryImpl[TKey,TValue](IDictionary`2 dictionary, IEnumerable`1 newContents)

当进入调试器时,get 块被调用并返回预期的字典。之后,在调试器中无需额外步骤即可引发错误。

这是端点外观的示例(它不符合 REST):

public JsonResult UpdateSingleItem(Options options, ...)
{ // breakpoint here is never called.
    ....
}`

使用ReSharperDotPeak 来检查代码会为我提供以下引发错误的方法:

// System.Web.Mvc.DefaultModelBuilder.CollectionHelpers
private static void ReplaceDictionaryImpl<TKey, TValue>(
  IDictionary<TKey, TValue> dictionary,
  IEnumerable<KeyValuePair<object, object>> newContents)
{
  dictionary.Clear();
  foreach (KeyValuePair<object, object> newContent in newContents)
    {
    TKey key = (TKey) newContent.Key;
    TValue obj = newContent.Value is TValue ? (TValue) newContent.Value : default (TValue);
    dictionary[key] = obj;
  }
}

【问题讨论】:

    标签: c# asp.net .net asp.net-mvc enums


    【解决方案1】:

    我不能确定,但​​我猜客户端正在将枚举作为字符串值发送?

    {
    "Setting1":true,
    "Setting2":false
    }
    

    这将失败,因为默认绑定正在尝试将该字符串转换回枚举。如果它传回枚举的整数值而不是字符串,我认为这会起作用。如果您正在获取一个字符串值,那么您可能需要创建一个自定义模型绑定器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-07-18
      • 1970-01-01
      • 2022-07-19
      • 1970-01-01
      • 2016-08-27
      • 1970-01-01
      • 2015-04-26
      相关资源
      最近更新 更多