【发布时间】:2015-01-18 21:54:39
【问题描述】:
我尝试配置 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 一个 chrome 应用程序' 现在我尝试在 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));
} }
【问题讨论】:
-
请不要在您的问题中添加带有堆栈跟踪的屏幕截图。只需将完整的异常信息(堆栈跟踪、异常消息、类型和内部异常)作为文本粘贴到您的问题中。
-
在调用验证之前请致电
container.RegisterWebApiControllers()。这让您的生活变得更加轻松,因为这将允许 Simple Injector 也可以验证您的控制器,从而允许应用程序在调用Verify时崩溃,而不是稍后在应用程序运行时崩溃。跨度> -
@Steven 我从昨天晚上开始就这样做了......在 StackOverflow 上进行了编辑之后。我在“ExceptionHandlerFilter add”之前进行了调用,当我在验证之前尝试时,我得到一个类似这样的错误“在第一次调用 GetInstance、GetAllInstances 和验证后无法更改容器。”
-
要了解为什么会出现该异常,请阅读this part of the documentation。
标签: c# asp.net-mvc-5 asp.net-web-api simple-injector