簡體   English   中英

SimpleInjector和SDammann WebAPI版本控制

[英]SimpleInjector and SDammann WebAPI versioning

我嘗試配置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 }
        );
     }
}

我的控制器位於以下文件夾中。

在此處輸入圖片說明

當我只測試測試控制器時,一切正常-> http:localhost / VDB.Service.WebAPI / Api / Test

下面的代碼

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();
    }
}

在此處輸入圖片說明

順便說一句,我的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);
    }
}

可能這是一些基本的東西。 但是我是Web開發之類的新手。 在我的日常工作中,我正在使用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應用程序現在,當我進行測試->'PostMan a chrome app'時,我會得到一些回報。現在,我嘗試在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是默認的accountcontroller ...我的全局文件在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));

}}

異常很明顯:

FindOilTypesQueryHandler類型的構造函數包含IVdbQueryContext類型的參數,名稱為“ vdbQueryContext”,未注冊。 請確保IVdbQueryContext已在容器中注冊,或更改FindOilTypesQueryHandler的構造函數。

這意味着未注冊IVdbQueryContext 很容易理解為什么,因為您創建了兩個Container實例。 第二個(在Application_Start方法中)包含此IVdbQueryContext注冊,但是從不使用該實例。 第一個(在Register方法中)注冊為DependencyResolver ,因此由Web API使用它來解析您的控制器,但是此實例不包含IVdbQueryContext注冊。

最佳實踐是每個應用程序只有一個容器實例

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM