ASP.NET Web API操作使用接口而不是具体类

前端之家收集整理的这篇文章主要介绍了ASP.NET Web API操作使用接口而不是具体类前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我的团队需要使用此框架为我们的公司和产品开发框架.
其中一个要求是可以为特定客户定制产品,但应该使用同一产品的其他版本(不是自动)轻松更新.

我们正在使用ASP.NET MVC 4 Web API(目前,基于我们的框架,将在明年创建桌面产品),NHibernate,使用Autofac作为DI容器和N层的IoC.

因此,在WebApp的某些方面,我们将viewmodels用作具有一个默认实现的接口,并使用Autofac链接它们,并且在期货自定义中很容易更改.

在ASP.NET MVC中,我们实现了这个实现IModelBinderProvider并创建一个自定义类来激活DefaultModelBinder:

像这样的东西:

public class MyCustomMVCModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(Type modelType)
    {
        if (modelType.IsInterface)
            return new MyCustomMVCModelBinder();

        return new DefaultModelBinder();
    }
}
public class MyCustomMVCModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext,ModelBindingContext bindingContext)
    {
        var context = new ModelBindingContext(bindingContext);
        var item = DependencyResolver.Current.GetService(bindingContext.ModelType);

        Func<object> modelAccessor = () => item;
        context.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(),bindingContext.ModelMetadata.ContainerType,modelAccessor,item.GetType(),bindingContext.ModelName);

        return base.BindModel(controllerContext,context);
    }
}

在我的控制器中,我只使用接口作为参数.因此,它工作正常,因为值正确填充.

但是,如何在Web API中使用正确绑定的值执行相同操作?
我尝试实现IModelBinder并继承ModelBinderProvider.我可以获得接口实现的实例,但不会填充值.

这是WebAPI中的尝试实现:

public class MyCustomWebAPIModelBinderProvider : ModelBinderProvider
{
    public override IModelBinder GetBinder(System.Web.Http.HttpConfiguration configuration,Type modelType)
    {
        return new MyCustomWebAPIModelBinder();
    }
}

public class MyCustomWebAPIModelBinder : IModelBinder
{
    public bool BindModel(System.Web.Http.Controllers.HttpActionContext actionContext,ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType.IsInterface)
        {
            var item = GlobalConfiguration.Configuration.DependencyResolver.GetService(bindingContext.ModelType);

            if (item != null)
            {
                Func<object> modelAccessor = () => item;
                var a = bindingContext.ModelMetadata.ContainerType;
                var b = modelAccessor;
                var c = item.GetType();
                var d = bindingContext.ModelName;

                bindingContext.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(),a,b,c,d);

                bindingContext.Model = item;

                return true;
            }
        }

        return false;
    }
}

我错过了什么?
有可能做我们想要的吗?

解决方法

而不是使用ModelBinder,使用MediaTypeFormatter的实现.

您可以覆盖方法“ReadFromStreamAsync”并将类型更改为您需要的任何类型.

在下面的示例中,通过使用MVC的DependencyResolver解析具体类型来更改类型,对WebAPI可以正常工作.

public class CustomFormUrlEncodedMediaTypeFormatter : FormUrlEncodedMediaTypeFormatter
    {
        public CustomFormUrlEncodedMediaTypeFormatter() : base() { }

        public override Task ReadFromStreamAsync(Type type,Stream readStream,HttpContent content,IFormatterLogger formatterLogger)
        {
            if (type.IsInterface)
                type = GetConcreteType(type);

            return base.ReadFromStreamAsync(type,readStream,content,formatterLogger);
        }

        public override Task WriteToStreamAsync(Type type,object value,Stream writeStream,TransportContext transportContext)
        {
            if (type.IsInterface)
                type = GetConcreteType(type);

            return base.WriteToStreamAsync(type,value,writeStream,transportContext);
        }

        private Type GetConcreteType(Type type)
        {
            object concrete = System.Web.Mvc.DependencyResolver.Current.GetService(type);
            return concrete.GetType();
        }
    }

如果你想用JsonFormatter做到这一点,那么为Json.NET创建一个“CustomCreationConverter”是一个更好的方法,而不是解决你的界面中所有子对象的依赖性.

public class DomainConverter : CustomCreationConverter
    {
            public DomainConverter() { }

            public override bool CanConvert(Type objectType)
            {
                return objectType.IsInterface;
            }

            public override object Create(Type objectType)
            {
                return System.Web.Mvc.DependencyResolver.Current.GetService(objectType);
            }
    }

猜你在找的asp.Net相关文章