无法同时将Autofac集成至Web API 2与MVC环境
Web API Autofac集成失败排查与解决方案
我已经花了一周时间尝试多种方法解决Autofac集成问题,目前MVC部分已经成功集成Autofac,但Web API始终无法完成集成。以下是我的相关实现代码:
AutofacDi 实现
public static class AutofacDi { public static ValueTuple<IContainer, HttpConfiguration> Initialize() { var assembly = Assembly.GetExecutingAssembly(); var builder = new ContainerBuilder(); var config = GlobalConfiguration.Configuration; builder.RegisterControllers(assembly); builder.RegisterApiControllers(assembly).PropertiesAutowired(); builder.RegisterHttpRequestMessage(config); builder.RegisterAssemblyModules(assembly); builder.RegisterAssemblyTypes(assembly).PropertiesAutowired(); builder.RegisterFilterProvider(); builder.RegisterWebApiFilterProvider(config); builder.RegisterModelBinders(assembly); builder.RegisterWebApiModelBinderProvider(); builder.RegisterModelBinderProvider(); builder.RegisterModule<AutofacWebTypesModule>(); builder.RegisterSource(new ViewRegistrationSource()); builder.RegisterType<T4MVC.Dummy>().AsSelf(); builder.RegisterType<FoodDbContext>() .As<IUnitOfWork>() .InstancePerLifetimeScope(); builder.Register(context => (FoodDbContext)context.Resolve<IUnitOfWork>()) .As<FoodDbContext>() .InstancePerLifetimeScope(); builder.RegisterType<ApplicationDbContext>().As<DbContext>().InstancePerLifetimeScope(); builder.RegisterType<UserStore<ApplicationUser>>().As<IUserStore<ApplicationUser>>(); builder.RegisterType<ApplicationUserManager>(); builder.RegisterType<ApplicationSignInManager>(); builder.Register(c => new IdentityFactoryOptions<ApplicationUserManager>() { DataProtectionProvider = new DpapiDataProtectionProvider("FoodBaMa") }); builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).InstancePerLifetimeScope(); builder.RegisterType<RoleStore<IdentityRole>>().As<IRoleStore<IdentityRole, string>>(); builder.RegisterAssemblyTypes(typeof(MvcApplication).Assembly) .Where(t => t.Name.EndsWith("Service")) .AsImplementedInterfaces() .InstancePerLifetimeScope(); var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); config.DependencyResolver = new AutofacWebApiDependencyResolver(container); return new ValueTuple<IContainer, HttpConfiguration>(container, config); } }
OWIN Startup 代码
[assembly: OwinStartup(typeof(FoodBaMa.Startup))] namespace FoodBaMa { public partial class Startup { public void Configuration(IAppBuilder app) { var iOc = AutofacDi.Initialize(); app.UseAutofacMiddleware(iOc.Item1); app.UseAutofacMvc(); app.UseWebApi(iOc.Item2); app.UseAutofacWebApi(iOc.Item2); WebApiConfig.Register(iOc.Item2); app.UseCors(CorsOptions.AllowAll); ConfigureAuth(app); } } }
Global.asax 代码
public class MvcApplication : HttpApplication { protected void Application_Start() { RouteConfig.RegisterRoutes(RouteTable.Routes); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); BundleConfig.RegisterBundles(BundleTable.Bundles); ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(new RazorViewEngine()); ModelBinders.Binders.Add(typeof(string), new PersianModelBinder()); MvcHandler.DisableMvcResponseHeader = true; DbInterception.Add(new ElmahEfInterceptor()); DbInterception.Add(new YeKeInterceptor()); GlobalConfiguration.Configuration.EnsureInitialized(); } }
ApiController 实现
[AutofacControllerConfiguration] [WebApiCompress] [RoutePrefix("api/v1")] public class AppController : ApiController { private readonly IApiV1Service _apiService; public AppController(IApiV1Service apiService ) { _apiService = apiService; } [HttpPost] [Route("app/mainview")] public virtual async Task<IHttpActionResult> MainView([FromBody] Request model) { var Result = new Models.API.V1.App.MainView.Response { Status = CheckTokenEnum.Error }; try { if (ModelState.IsValid) Result = await _apiService.MainView(model).ConfigureAwait(false); } catch (Exception ex) { ErrorLog.GetDefault(null).Log(new Error(ex)); } return Json(Result, R8.Json.Setting); } }
WebApiConfig 代码
public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.JsonIntegration(); config.EnableCors(new EnableCorsAttribute("*", "*", "*")); config.MessageHandlers.Add(new CachingHandler(new InMemoryCacheStore())); config.MessageHandlers.Add(new PreflightRequestsHandler()); config.Filters.Add(new ElmahHandleErrorApiAttribute()); config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
RouteConfig 代码(片段)
public class RouteConfig { public static void RegisterRoutes(RouteCollec
问题排查与解决方案
从你的代码来看,Web API集成失败大概率是初始化顺序冲突和配置重复导致的,我整理了几个关键修复点:
调整OWIN Startup中的Web API注册顺序
你当前先将Web API加入OWIN管道,再配置WebApiConfig,这会导致路由、过滤器等配置无法生效。修改顺序如下:public void Configuration(IAppBuilder app) { var iOc = AutofacDi.Initialize(); // 先完成Web API配置,再加入管道 WebApiConfig.Register(iOc.Item2); app.UseAutofacMiddleware(iOc.Item1); app.UseAutofacMvc(); app.UseAutofacWebApi(iOc.Item2); app.UseWebApi(iOc.Item2); app.UseCors(CorsOptions.AllowAll); ConfigureAuth(app); }移除Global.asax中的Web API初始化代码
Global.asax里的GlobalConfiguration.Configuration.EnsureInitialized()会和OWIN的Web API初始化产生冲突,直接删除这行代码即可:protected void Application_Start() { // ... 其他保留代码 ... // 移除这行,让OWIN完全接管Web API初始化 // GlobalConfiguration.Configuration.EnsureInitialized(); }验证服务注册的正确性
确认IApiV1Service的实现类命名符合*Service的规则(你的代码里用了Where(t => t.Name.EndsWith("Service"))),如果命名不符合,需要手动注册:builder.RegisterType<ApiV1Service>().As<IApiV1Service>().InstancePerLifetimeScope();
完成这些修改后,建议在ApiController的构造函数中添加断点,测试IApiV1Service是否能被正确注入。如果仍然失败,查看Elmah日志或调试输出的异常信息,这会帮你进一步定位具体的依赖解析问题。
内容的提问来源于stack exchange,提问作者Arash Sh
相关产品推荐
相关产品推荐

