SimpleInjector和SDammann WebAPI版本控制

时间:2015-01-14 07:23:44

标签: c# asp.net-mvc-5 asp.net-web-api simple-injector

我尝试将SimpleInjector容器与SDammann WebAPI版本配合使用

我在我的WebAPI配置中有这个..

public static class WebApiConfig
{
    public sealed class AcceptHeaderRequestVersionDetector : SDammann.WebApi.Versioning.Request.AcceptHeaderRequestVersionDetector 
    {
        protected override ApiVersion GetVersionFromSingleHeader(MediaTypeWithQualityHeaderValue headerValue)
        {
            string rawVersion = headerValue.Parameters.First(x => x.Name == "version").Value;
            int version = Convert.ToInt32(rawVersion);

            return new SemVerApiVersion(
                new Version(version, 0)
            );
        }
    }

    public static void Register(HttpConfiguration config)
    {
        Container container = new Container();
        container.Register<DefaultControllerIdentificationDetector>();
        container.Register<DefaultRequestControllerIdentificationDetector>();
        container.Register<HttpConfiguration>(() => config);

        config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

        container.Verify();

        config.Services.Replace(typeof(IHttpControllerSelector), new VersionedApiControllerSelector(config));

        ApiVersioning.Configure()
                     .ConfigureRequestVersionDetector<AcceptHeaderRequestVersionDetector>();

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
     }
}

我的控制器可在以下文件夹中找到....

enter image description here

当我测试测试控制器时,一切正常 - &GT; HTTP:本地主机/ VDB.Service.WebAPI /阿比/测试

以下代码

public class TestController : ApiController
{
    [HttpGet]
    public string Version()
    {
        return "Version 1";
    }
}

当我尝试下面的其他一些东西时,我得到一个错误.... 见下面这段代码的图片

public class OilTypesController : ApiController
{
    private readonly IRequestHandler<FindOilTypesQuery,FindOilTypesQueryResult>  _findOilTypesQueryHandler;
    private readonly IRequestHandler<CreateOilTypeCommand, CreateOilTypeCommandResult> _createOilTypeCommandHandler;

    public OilTypesController(FindOilTypesQueryHandler findOilTypesQueryHandler, CreateOilTypeCommandHandler createOilTypeCommandHandler)
    {
        _findOilTypesQueryHandler = findOilTypesQueryHandler;
        _createOilTypeCommandHandler = createOilTypeCommandHandler;
    }

    [HttpPost]
    public CreateOilTypeCommandResult CreateOilType(CreateOilTypeCommand command)
    {
        var result = _createOilTypeCommandHandler.Execute(command);
        return result;
    }

    [HttpGet]
    public IQueryable<OilTypeSummaryModel> GetOilTypes(ODataQueryOptions<OilType> oDataQuery)
    {
        var query = new FindOilTypesQuery(oDataQuery);
        return _findOilTypesQueryHandler.Execute(query).OilTypes.ToOilTypeSummaryModel();
    }
}

enter image description here

BTW我的Global.asax看起来像这样......

 public class WebApiApplication : HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        Container container = new Container();
        container.RegisterManyForOpenGeneric(typeof(IRequestHandler<,>), Assembly.GetExecutingAssembly());
        container.Register<IVdbCommandContext, VdbCommandContext>(Lifestyle.Transient);
        container.Register<IVdbQueryContext, VdbQueryContext>(Lifestyle.Transient);

        GlobalConfiguration.Configuration.Filters.Add(new ExceptionHandlerFilter());

        // Force code first migrations to check database and migrate if required
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<VdbCommandContext, Configuration>());

        VdbCommandContext vdbCommandContext = new VdbCommandContext();
        vdbCommandContext.Database.Initialize(true);
    }
}

这可能是一些基本的东西。但我不熟悉Webdevelopment和那些东西。 在我的日常工作中,我正在使用BizTalk和那些东西。 :) 但我想学习新东西。 :)

从这一点编辑

我现在收到以下错误,但我不知道为什么......

{
"Message": "An error has occurred.",
"ExceptionMessage": "An error occurred when trying to create a controller of type 'OilTypesController'. Make sure that the controller has a parameterless public constructor.",
"ExceptionType": "System.InvalidOperationException",
"StackTrace": " at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)\ \ at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)\ \ at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()",
"InnerException": {
"Message": "An error has occurred.",
"ExceptionMessage": "No registration for type OilTypesController could be found and an implicit registration could not be made. The constructor of type OilTypesController contains the parameter of type IRequestHandler<FindOilTypesQuery, FindOilTypesQueryResult> with name 'findOilTypesQueryHandler' that is not registered. Please ensure IRequestHandler<FindOilTypesQuery, FindOilTypesQueryResult> is registered in the container, or change the constructor of OilTypesController.",
"ExceptionType": "SimpleInjector.ActivationException",
"StackTrace": " at SimpleInjector.InstanceProducer.GetInstance()\ \ at SimpleInjector.Container.GetInstance(Type serviceType)\ \ at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)",
"InnerException": {
"Message": "An error has occurred.",
"ExceptionMessage": "The constructor of type OilTypesController contains the parameter of type IRequestHandler<FindOilTypesQuery, FindOilTypesQueryResult> with name 'findOilTypesQueryHandler' that is not registered. Please ensure IRequestHandler<FindOilTypesQuery, FindOilTypesQueryResult> is registered in the container, or change the constructor of OilTypesController.",
"ExceptionType": "SimpleInjector.ActivationException",
"StackTrace": " at SimpleInjector.Advanced.DefaultConstructorInjectionBehavior.BuildParameterExpression(ParameterInfo parameter)\ \ at SimpleInjector.ContainerOptions.BuildParameterExpression(ParameterInfo parameter)\ \ at SimpleInjector.Registration.BuildConstructorParameters(ConstructorInfo constructor)\ \ at SimpleInjector.Registration.BuildNewExpression(Type serviceType, Type implementationType)\ \ at SimpleInjector.Registration.BuildTransientExpression[TService,TImplementation]()\ \ at SimpleInjector.Registration.BuildExpression(InstanceProducer producer)\ \ at SimpleInjector.InstanceProducer.BuildExpressionInternal()\ \ at System.Lazy`1.CreateValue()\ \ --- End of stack trace from previous location where exception was thrown ---\ \ at SimpleInjector.InstanceProducer.BuildInstanceCreator()\ \ at SimpleInjector.InstanceProducer.GetInstance()"
}
}
}

我的WebApi看起来现在喜欢这个...... 控制器仍然是相同的......

public static class WebApiConfig
{
    public sealed class AcceptHeaderRequestVersionDetector : SDammann.WebApi.Versioning.Request.AcceptHeaderRequestVersionDetector 
    {
        protected override ApiVersion GetVersionFromSingleHeader(MediaTypeWithQualityHeaderValue headerValue)
        {
            string rawVersion = headerValue.Parameters.First(x => x.Name == "version").Value;
            int version = Convert.ToInt32(rawVersion);

            return new SemVerApiVersion(
                new Version(version, 0)
            );
        }
    }

    public static void Register(HttpConfiguration config)
    {
        Container container = new Container();
        container.Register<DefaultControllerIdentificationDetector>();
        container.Register<DefaultRequestControllerIdentificationDetector>();
        container.Register(() => config);

        container.RegisterManyForOpenGeneric(typeof(IRequestHandler<,>), Assembly.GetExecutingAssembly());
        container.Register<IVdbCommandContext, VdbCommandContext>();
        container.Register<IVdbQueryContext, VdbQueryContext>();

        GlobalConfiguration.Configuration.Filters.Add(new ExceptionHandlerFilter());

        config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

        container.Verify();

        config.Services.Replace(typeof(IHttpControllerSelector), new VersionedApiControllerSelector(config));

        ApiVersioning.Configure()
                     .ConfigureRequestVersionDetector<AcceptHeaderRequestVersionDetector>();

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
     }
}

第二次编辑

 public class FindOilTypesQueryHandler: IRequestHandler<FindOilTypesQuery,FindOilTypesQueryResult>
{
    private readonly IVdbQueryContext _vdbQueryContext;

    public FindOilTypesQueryHandler(IVdbQueryContext vdbQueryContext)
    {
        _vdbQueryContext = vdbQueryContext;
    }

    public FindOilTypesQueryResult Execute(FindOilTypesQuery request)
    {
        var oilTypes = request.ODataQuery.ApplyTo(_vdbQueryContext.OilTypes).Cast<OilType>();
        return new FindOilTypesQueryResult(oilTypes);
    }
}

编辑:MVC应用程序 当我做一个测试时,我现在得到一些东西 - &gt; &#39; PostMan Chrome应用程序&#39; 现在我尝试在ASP.Net MVC应用程序中这样做......

但是我得到错误......

    For the container to be able to create AccountController, it should contain exactly one public constructor, but it has 2.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: SimpleInjector.ActivationException: For the container to be able to create AccountController, it should contain exactly one public constructor, but it has 2.
Source Error: 


Line 27:             container.RegisterMvcIntegratedFilterProvider();
Line 28: 
Line 29:             container.Verify();
Line 30: 
Line 31:             DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

accountController是默认的帐户控制器... My Global文件在我的MVC应用程序中看起来像这样。

就像......上的指南一样,没有?https://simpleinjector.readthedocs.org/en/latest/mvcintegration.html

public class MvcApplication : HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            Container container = new Container();
            container.Register<IVdbService, VdbService>();
            container.Register<IRequestExecutor,RequestExecutor>();

            container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
            container.RegisterMvcIntegratedFilterProvider();

            container.Verify();

            DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

}     }

1 个答案:

答案 0 :(得分:1)

异常非常清楚:

  

FindOilTypesQueryHandler类型的构造函数包含   类型为IVdbQueryContext的参数,名称为&#39; vdbQueryContext&#39;那是   未注册。请确保在。中注册了IVdbQueryContext   容器,或者更改FindOilTypesQueryHandler的构造函数。

这意味着IVdbQueryContext尚未注册。很容易理解为什么,因为您创建了两个Container实例。第二个(在Application_Start方法中)包含此IVdbQueryContext注册,但该实例从未使用过。第一个(在Register方法中)注册为DependencyResolver,因此Web API用于解析您的控制器,但此实例不包含IVdbQueryContext注册。

最佳做法是one single container instance per application