2020-09-24 乐帮网
owin c#
使用了WebApi2和MVC5混合的项目,使用到了Microsoft.Owin 和Autofac ,着同时兼容MVC和WebApi,在写完代码后发现MVC控制器可以正常拿到Autofac的映射,但是WebApi的控制中报错:请确保控制器具有无参数的公共构造函数 An error occurred when trying to create a controller of type 'xxxController'. Make sure that the controller has a parameterless public constructor.",多方查找原因均无功而返,一个偶然的机会让我找到了原因。
1、使用VS新建一个Web项目 ,勾选MVC和WebApi的模板。
2、使用Nuget添加Owin等依赖包 同时也添加WebApi的Owin依赖包。
Install-Package Microsoft.Owin
Install-Package Microsoft.Owin.Host.SystemWeb
Install-Package Microsoft.AspNet.WebApi.Owin
3、添加Autofac的依赖包,主要包含如下
Install-Package Autofac.Mvc5
Install-Package Autofac.Mvc5.Owin
Install-Package Autofac.WebApi2
Install-Package Autofac.WebApi2.Owin
4、添加IOC注册和相关类。
4.1、映射数据库操作类
public interface ITestRepository
{
string Method1();
}
public class TestRepository : ITestRepository
{
public string Method1()
{
return "Method1 Value";
}
}
4.2、建立Startup 类如下:
[assembly: OwinStartup(typeof(OwinAutofac.Demo.Startup))]
namespace OwinAutofac.Demo
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to confffigure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
AreaRegistration.RegisterAllAreas();
//GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
var assembly = Assembly.GetExecutingAssembly();
var builder = new ContainerBuilder();
builder.RegisterApiControllers(assembly);
builder.RegisterControllers(assembly);
builder.RegisterFilterProvider();
// 注册单个实例
//builder.RegisterInstance(new NLogger()).As<ILogger>();
// 扫描assembly中的组件(类名以Repository结尾)
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
IContainer container = builder.Build();
var webApiResolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = webApiResolver;
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
app.UseWebApi(config);
}
}
}
4.3、修改HomeController 添加构造函数如下:
public class HomeController : Controller
{
public ITestRepository _testRepository;
public HomeController(ITestRepository testRepository)
{
_testRepository = testRepository;
}
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
4.4、添加apiContoller如下:
public class TestController : ApiController
{
public ITestRepository _testRepository;
public TestController(ITestRepository testRepository)
{
_testRepository = testRepository;
}
// GET: api/Test
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
4.5、去掉Global.asax中的逻辑如下
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
//AreaRegistration.RegisterAllAreas();
//GlobalConfiguration.Configure(WebApiConfig.Register);
//FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
//RouteConfig.RegisterRoutes(RouteTable.Routes);
//BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
5、此进访问HomeController 发现首页能正常打开,一切都正常。再访问我们写的TestApi
发现autofac没有正常工作报以下的错误:
An error has occurred
An error occurred when trying to create a controller of type 'TestController'. Make sure that the controller has a parameterless public constructor.
类型“OwinAutofac.Demo.Controllers.api.TestController”没有默认构造函数
6、解决办法引起这个问题的排查如下:
6.1 排查Autofac写的注册是不是确定注册过构造函数中引用的类。比如我上面写的ITestRepository 和主项目都是在一起,如果映射的类不在一个项目中,那你的这部分需要改动
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
assembly 至少是丢了一部分,需要修改一下。具体怎么修改需要自行决定。
6.2 WebApi的注册IOC容器和MVC的不一样,需要分别替换,看一下漏了下面这一段不。
// Set MVC DI resolver to use our Autofac container
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// Set the dependency resolver for Web API.
var webApiResolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = webApiResolver;
6.3 以上两点能排除很多问题,网上都是以上两个回答,但是最基本和最简单的一种情况还没有说。~_~ ,我写的例子一点儿也没有漏,还是不能正常工作。下面这段是我的终级解决方案。
如果有表述不对的地方欢迎指正。
我的终极解决方案请点击捐赠按钮或者直接去下载我的代码Demo。
关注我的微信公众号
在公众号里留言交流
投稿邮箱:1052839972@qq.com
庭院深深深几许?杨柳堆烟,帘幕无重数。
玉勒雕鞍游冶处,楼高不见章台路。
雨横风狂三月暮。门掩黄昏,无计留春住。
泪眼问花花不语,乱红飞过秋千去。
如果感觉对您有帮助
欢迎向作者提供捐赠
这将是创作的最大动力