如何在ASP.NET MVC 5控制器上从JSON反序列化为抽象参数

移位

我有一个抽象对象BaseObject(示例名称),该对象具有2个特定于国家/地区的实现,即UsaObject和CanadaObject,它们都扩展了BaseObject。

public abstract class BaseObject...
public class UsaObject : BaseObject...
public class CanadaObject : BaseObject...

在我的控制器中,我有一个动作

public void UpdateObject(BaseObject object) {
   ...
}

该操作仅在BaseObject上调用方法,并且不需要强制转换。

我使用Json.NET执行序列化,当我序列化对象时,我使用JsonSerializationSettings.TypeNameHandling.Objects将类的类型添加到对象中。这使我可以轻松地将数据正确地发送到UI并根据国家/地区更改显示的内容,而不必担心直到需要的确切时间。

但是,我在将此数据发布回UpdateObject方法时遇到问题。它在反序列化时失败,并显示以下错误(请注意,尽管我根本不怀疑这是引起问题的原因,但我们正在使用Glimpse对应用程序执行性能分析),该错误被IExceptionFilter.OnException调用捕获:

System.MissingMethodException: Cannot create an abstract class.
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
   at System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
   at System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
   at Castle.Proxies.DefaultModelBinderProxy.BindModel_callback(ControllerContext controllerContext, ModelBindingContext bindingContext)
   at Castle.Proxies.Invocations.DefaultModelBinder_BindModel.InvokeMethodOnTarget()
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Glimpse.Core.Extensibility.CastleInvocationToAlternateMethodContextAdapter.Proceed()
   at Glimpse.Core.Extensions.AlternateMethodContextExtensions.TryProceedWithTimer(IAlternateMethodContext context, TimerResult& timerResult)
   at Glimpse.Core.Extensibility.AlternateMethod.NewImplementation(IAlternateMethodContext context)
   at Glimpse.Core.Extensibility.AlternateTypeToCastleInterceptorAdapter.Intercept(IInvocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.DefaultModelBinderProxy.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
   at System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
   at System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass1e.<BeginInvokeAction>b__16(AsyncCallback asyncCallback, Object asyncState)

有没有办法修改MVC 5处理反序列化的方式,如果是,我应该在页面生命周期的哪一点完成此操作?

移位

原来,我做出了一个错误的假设,即MVC使用Json.NET进行反序列化(对我感到羞耻)。MVC有其自己的ModelBinder,默认情况下DefaultModelBinder请耐心等待解决方案,这有点仓促,需要测试。我能够扩展DefaultModelBinder,

public class AbstractModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        if (modelType.IsAbstract)
        {
            var typeName = bindingContext.ValueProvider.GetValue("$type");
            if (typeName == null)
                throw new Exception("Cannot create abstract model");

            var type = Type.GetType(typeName);
            if (type == null)
                throw new Exception("Cannot create abstract model");

            if (!type.IsSubclassOf(modelType))
                throw new Exception("Incorrect model type specified");

            var model = Activator.CreateInstance(type);

            // this line is very important.
            // It updates the metadata (and type) of the model on the binding context,
            // which allows MVC to properly reflect over the properties
            // and assign their values. Without this,
            // it will keep the type as specified in the parameter list,
            // and only the properties of the base class will be populated
            bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);

            return model;
        }

        return base.CreateModel(controllerContext, bindingContext, modelType);
    }
}

并在启动时将其注册为我的默认活页夹。

// in Global.asax.cs on application start
ModelBinders.Binders.DefaultBinder = new AbstractModelBinder();

我仅在模型类型为抽象时更改行为,否则为默认值。如果它是抽象的,但是我无法创建该类型的实例,或者类型名称不可用,等等,那么现在我抛出一个异常,但这是一个细节,以后我可以弄清楚。这样,我就不需要在Actions的参数上使用任何属性,而目前我能弄清楚的是,Json.NET类型说明符得到了最好的利用。只需让Json.NET为我反序列化模型,将是很好的选择,但这是到目前为止我发现的最佳解决方案。

我想参考有助于我找到答案的帖子。更改ASP.NET MVCASP.NET MVC 3中的默认模型绑定程序:具有继承/多态性的DefaultModelBinder

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

无法将json反序列化为ASP.Net MVC中的抽象类

来自分类Dev

Asp.net MVC在控制器中反序列化Kendo Grid数据

来自分类Dev

如何在控制器ASP.NET MVC 5上禁用默认路由

来自分类Dev

如何在ASP.NET MVC中将多个参数从jquery发布到控制器?

来自分类Dev

如何在ASP.NET MVC中使用routeValue参数调用控制器操作

来自分类Dev

如何在ASP.NET MVC控制器参数中将毫秒转换为DateTime

来自分类Dev

如何在ASP.NET MVC / Web控制器中返回JSON?

来自分类Dev

如何在JSON.NET中将其作为ASP.NET MVC控制器的模型绑定器?

来自分类Dev

如何在ASP.NET 5 MVC中访问缓存?

来自分类Dev

如何在 ASP.NET MVC 5 中使用 applozic

来自分类Dev

如何从ASP.NET MVC控制器上的HTML5 Web表单获取数据?

来自分类Dev

ASP.NET MVC4将带有'ExtraElements'的JSON反序列化为c#ViewModel

来自分类Dev

如何在URL中更改ASP.NET MVC控制器名称?

来自分类Dev

如何在asp.net-mvc控制器中集中授权逻辑?

来自分类Dev

如何在ASP.NET MVC控制器中获取过帐的表单数据

来自分类Dev

如何在ASP.Net的MVC控制器中使用File类?

来自分类Dev

如何在asp.net mvc中的URL中更改控制器名称

来自分类Dev

ASP.NET MVC EntityFramework:如何在ActionResult控制器方法中使用LINQ?

来自分类Dev

如何在ASP.NET MVC控制器中获取URL

来自分类Dev

如何在ASP.NET MVC控制器中使用Automapper配置

来自分类Dev

如何在ASP.NET MVC控制器中编写HTML代码

来自分类Dev

如何在ASP.NET MVC中的控制器中调用模型方法

来自分类Dev

如何在使用ASP .NET MVC的方法之间正确共享控制器中的对象?

来自分类Dev

ASP.Net MVC如何在控制器操作中从布局访问隐藏字段

来自分类Dev

如何在ASP.NET MVC 6中添加基本控制器

来自分类Dev

ASP.NET MVC EntityFramework:如何在ActionResult控制器方法中使用LINQ?

来自分类Dev

如何在ASP.NET MVC的控制器方法中“不要重复自己”?

来自分类Dev

如何在ASP .NET MVC中将特定行的值传递给控制器方法

来自分类Dev

如何在ASP.NET MVC中的控制器中使用自定义方法

Related 相关文章

  1. 1

    无法将json反序列化为ASP.Net MVC中的抽象类

  2. 2

    Asp.net MVC在控制器中反序列化Kendo Grid数据

  3. 3

    如何在控制器ASP.NET MVC 5上禁用默认路由

  4. 4

    如何在ASP.NET MVC中将多个参数从jquery发布到控制器?

  5. 5

    如何在ASP.NET MVC中使用routeValue参数调用控制器操作

  6. 6

    如何在ASP.NET MVC控制器参数中将毫秒转换为DateTime

  7. 7

    如何在ASP.NET MVC / Web控制器中返回JSON?

  8. 8

    如何在JSON.NET中将其作为ASP.NET MVC控制器的模型绑定器?

  9. 9

    如何在ASP.NET 5 MVC中访问缓存?

  10. 10

    如何在 ASP.NET MVC 5 中使用 applozic

  11. 11

    如何从ASP.NET MVC控制器上的HTML5 Web表单获取数据?

  12. 12

    ASP.NET MVC4将带有'ExtraElements'的JSON反序列化为c#ViewModel

  13. 13

    如何在URL中更改ASP.NET MVC控制器名称?

  14. 14

    如何在asp.net-mvc控制器中集中授权逻辑?

  15. 15

    如何在ASP.NET MVC控制器中获取过帐的表单数据

  16. 16

    如何在ASP.Net的MVC控制器中使用File类?

  17. 17

    如何在asp.net mvc中的URL中更改控制器名称

  18. 18

    ASP.NET MVC EntityFramework:如何在ActionResult控制器方法中使用LINQ?

  19. 19

    如何在ASP.NET MVC控制器中获取URL

  20. 20

    如何在ASP.NET MVC控制器中使用Automapper配置

  21. 21

    如何在ASP.NET MVC控制器中编写HTML代码

  22. 22

    如何在ASP.NET MVC中的控制器中调用模型方法

  23. 23

    如何在使用ASP .NET MVC的方法之间正确共享控制器中的对象?

  24. 24

    ASP.Net MVC如何在控制器操作中从布局访问隐藏字段

  25. 25

    如何在ASP.NET MVC 6中添加基本控制器

  26. 26

    ASP.NET MVC EntityFramework:如何在ActionResult控制器方法中使用LINQ?

  27. 27

    如何在ASP.NET MVC的控制器方法中“不要重复自己”?

  28. 28

    如何在ASP .NET MVC中将特定行的值传递给控制器方法

  29. 29

    如何在ASP.NET MVC中的控制器中使用自定义方法

热门标签

归档