2017-03-01 74 views
1

我的项目中存在依赖项注入问题,它在实施Owin之前工作正常。在我添加Owin并开始启动课程后,问题开始出现。这个问题已经有很多文档了。但我似乎无法使用其他任何关于此事的帖子来解决它。添加Owin后,依赖注入破坏,没有为此对象定义的无参数构造函数

所涉及的服务确实具有无参数构造函数,控制器也有一个,服务保持空白。

我使用下列程序包:

  • 统一(v3.5.1404)
  • Unity.WebApi.5.1(V5.2.0)
  • Microsoft.AspNet.SignalR.Owin(V1.2.2 )
  • Microsoft.AspNet.WebApi.Owin(v5.2.3)
  • Microsoft.AspNet.WebApi.OwinSelfHost(v5.2.3)
  • Microsoft.Owin(V3.0.1)
  • Microsoft.Owin.Security(V1.0.0)
  • Microsoft.Owin.Host.SystemWeb(V3.0.1)
  • Owin(V1.0.0)
  • Microsoft.Owin.Host.SystemWeb(V3.0.1 )

每当我浏览到需要依赖注入的控制器时,都会发生以下错误。

[MissingMethodException: No parameterless constructor defined for this object.] 
       System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0 
       System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +119 
       System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +232 
       System.Activator.CreateInstance(Type type, Boolean nonPublic) +83 
       System.Activator.CreateInstance(Type type) +11 
       System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +55 

    [InvalidOperationException: An error occurred when trying to create a controller of type '_Servicebus.Controllers.AuthenticationController'. Make sure that the controller has a parameterless public constructor.] 
       System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +178 
       System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +76 
       System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +88 
       System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +194 
       System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +50 
       System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +48 
       System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16 
       System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +103 
       System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155 

我相信它与Global.asax.cs和Startup.cs有关。

的Global.asax.cs:

using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Web; 
    using System.Web.Http; 
    using System.Web.Mvc; 
    using System.Web.Optimization; 
    using System.Web.Routing; 
    using System.Timers; 
    using Microsoft.Practices.Unity; 
    using BusinessLayer.HourRegistration.Services; 
    using BusinessLayer.HourRegistration.Interfaces; 
    using DataAccessLayer.HourRegistration.Repositories; 
    using DataAccessLayer.HourRegistration.Entities; 
    using System.Data.Entity; 
    using System.IO; 

    namespace Servicebus 
    { 
     public class WebApiApplication : System.Web.HttpApplication 
     { 

      Timer timer; 
      bool firsttime; 
      protected void Application_Start() 
      { 
       AreaRegistration.RegisterAllAreas(); 
       GlobalConfiguration.Configure(WebApiConfig.Register); 
       FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
       RouteConfig.RegisterRoutes(RouteTable.Routes); 
       BundleConfig.RegisterBundles(BundleTable.Bundles); 
       /*firsttime = true; 
       timer = new Timer(); 
       timer.Elapsed += new ElapsedEventHandler(timer_Elapsed); 
       timer.Interval = 20000; 
       timer.AutoReset = false; 
       timer.Start();*/ 
      } 

      private ICrmUserFilterRepository uService 
      { 
       get 
       { 
        return GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(ICrmUserFilterRepository)) as ICrmUserFilterRepository; 
       } 
      } 

      private IHourRegistrationService hService 
      { 
       get 
       { 
        return GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IHourRegistrationService)) as IHourRegistrationService; 
       } 
      } 

      private void timer_Elapsed(object sender, ElapsedEventArgs e) 
      { 
       if (firsttime) 
       { 
        firsttime = false; 
        timer.Stop(); 
        List<CrmUserFilter> tempList = uService.GetAll().ToList(); 
        hService.setFourWeeksOldClosed(); 
        CrmFetchXml.getCrmFetchXmlInstance.reload24HoursCache(tempList); 
        timer.Interval = GetTimeUntilNextCacheRefresh(2); 
        timer.Start(); 
       } 
       else { 
        timer.Stop(); 
        List<CrmUserFilter> tempList = uService.GetAll().ToList(); 
        hService.setFourWeeksOldClosed(); 
        CrmFetchXml.getCrmFetchXmlInstance.reload24HoursCache(tempList); 
        timer.Interval = GetTimeUntilNextCacheRefresh(2); 
        timer.Start(); 
       } 
      } 

      public static double GetTimeUntilNextCacheRefresh(int hour) 
      { 
       var currentTime = DateTime.Now; 
       var desiredTime = new DateTime(DateTime.Now.Year, 
        DateTime.Now.Month, DateTime.Now.Day, hour, 0, 0); 
       var timeDifference = (currentTime - desiredTime); 
       var timePeriod = currentTime.Hour >= hour ? 
        (desiredTime.AddDays(1) - currentTime) : 
        -timeDifference; 
       return Convert.ToInt32(timePeriod.TotalMilliseconds); 
      } 
     } 
    } 

Startup.cs:

using Microsoft.AspNet.Identity; 
using Microsoft.Owin; 
using Microsoft.Owin.Security.Cookies; 
using Microsoft.Practices.Unity; 
using Owin; 
using System.Security.Claims; 
using System.Web.Helpers; 
using System.Web.Http; 
using System.Web.Mvc; 
using System.Web.Optimization; 
using System.Web.Routing; 
using Unity.WebApi; 

[assembly: OwinStartup(typeof(Servicebus.App_Start.Startup))] 

namespace Servicebus.App_Start 
{ 
    public partial class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      ConfigureAuth(app); 
     } 
     public void ConfigureAuth(IAppBuilder app) 
     { 
      //unity fix 
      HttpConfiguration config = new HttpConfiguration(); 

      UnityContainer container = WebApiConfig.Register(config); 

      // ... Configure you web api routes 
      config.DependencyResolver = new UnityDependencyResolver(container); 

      app.UseWebApi(config); 
      //GlobalConfiguration.Configure(config); 
      //app.UseWebApi(GlobalConfiguration.DefaultServer); 


      // Enable the application to use a cookie to store information for the signed in user 
      app.UseCookieAuthentication(new CookieAuthenticationOptions 
      { 
       AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 
       LoginPath = new PathString("/Authentication/Login") 
      }); 

      //app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); 

      AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; 
     } 
    } 
} 

WebApiConfig.cs:

 using System.Web.Http; 
     using Microsoft.Practices.Unity; 
     using BusinessLayer.HourRegistration.Interfaces; 
     using BusinessLayer.HourRegistration.Services; 
     using DataAccessLayer.HourRegistration.Repositories; 
     using System.Net.Http.Formatting; 
     using System.Data.Entity; 
     using Unity.WebApi; 
     using System.Web.Mvc; 
     using Servicebus.Security; 
     using System.Diagnostics; 
     using BusinessLayer.MTO.Interfaces; 
     using DataAccessLayer.MTO.Repositories.InterfaceRepositories; 
     using BusinessLayer.MTO.Services; 
     using DataAccessLayer.MTO.Repositories; 
     using DataAccessLayer.Common.DatabaseFactory; 
     using DataAccessLayer.HourRegistration.UnitOfWork; 
     using DataAccessLayer.MTO.UnitOfWork; 

     namespace Servicebus 
     { 
      public static class WebApiConfig 
      { 
       public static UnityContainer Register(HttpConfiguration config) 
       { 

        config.EnableCors(); 

        UnityContainer container = new UnityContainer(); 
container.RegisterType<IAuthenticationService, AuthenticationService>(); 
        container.RegisterType<IDatabaseFactory, DatabaseFactory>(new PerResolveLifetimeManager()); 
        container.RegisterType<IUnitOfWorkHourregistration, UnitOfWorkHourregistration>(); 
        container.RegisterType<ICrmProjectRepository, CrmProjectRepository>(); 
        container.RegisterType<ICrmOrderRepository, CrmOrderRepository>(); 
        container.RegisterType<IHourRegistrationRepository, HourRegistrationRepository>(); 
        container.RegisterType<IOverTimeHoursRepository, OverTimeHoursRepository>(); 
        container.RegisterType<IWorkhoursRepository, WorkHoursRepository>(); 
        container.RegisterType<IRoleRepository, RoleRepository>(); 
        container.RegisterType<IUserRepository, UserRepository>(); 
        container.RegisterType<IHourRegistrationService, HourRegistrationService>(); 
        container.RegisterType<IRoleProviderService, RoleProviderService>(); 
        container.RegisterType<ICrmUserFilterRepository, CrmUserFilterRepository>(); 

        //for MTO 
        container.RegisterType<IMTOService, MTOService>(); 
        container.RegisterType<IUnitOfWorkMTO, UnitOfWorkMTO>(); 
        container.RegisterType<IMtoRepository, MtoRepository>(); 
        container.RegisterType<IChapterRepository, ChapterRepository>(); 
        container.RegisterType<IQuestionRepository, QuestionRepository>(); 
        container.RegisterType<IQuestionKindRepository, QuestionKindRepository>(); 
        container.RegisterType<IAnswerRepository, AnswerRepository>(); 
        container.RegisterType<IDepartmentRepository, DepartmentRepository>(); 
        container.RegisterType<IReportRepository, ReportRepository>(); 
        container.RegisterType<IActionPointRepository, ActionPointRepository>(); 
        container.RegisterType<IUserMtoRepository, UserMtoRepository>(); 
        container.RegisterType<IRoleMtoRepository, RoleMtoRepository>(); 
        container.RegisterType<IMtoUserResponseRepository, MtoUserResponseRepository>(); 

        config.DependencyResolver = new UnityDependencyResolver(container); 
        config.Formatters.JsonFormatter.MediaTypeMappings.Add(new UriPathExtensionMapping("json", "application/json")); 

        config.Formatters.XmlFormatter.MediaTypeMappings.Add(new UriPathExtensionMapping("xml", "application/xml")); 


        // Web API routes 
        config.MapHttpAttributeRoutes(); 

        config.Routes.MapHttpRoute(
         name: "DefaultApi", 
         routeTemplate: "api/{controller}/{id}", 
         defaults: new { id = RouteParameter.Optional } 
        ); 
        config.Routes.MapHttpRoute(
         name: "Api UriPathExtension", 
         routeTemplate: "api/{controller}.{ext}/{id}", 
         defaults: new { id = RouteParameter.Optional } 
        ); 
        config.Routes.MapHttpRoute(
         name: "MtoApi", 
         routeTemplate: "api/{controller}/{id}", 
         defaults: new { controller = "mto", id = RouteParameter.Optional } 
         ); 
        return container; 
       } 
      } 
     } 

确实涉及到的服务确实有一个参数的构造函数中,控制器也有一个,服务保持空白。

随机[未完成]服务:

using BusinessLayer.Authentication.Interfaces; 
using Newtonsoft.Json.Linq; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace BusinessLayer.Authentication.Services 
{ 
    public class AuthenticationService : IAuthenticationService 
    { 

     public AuthenticationService() 
     { } 

     public bool CheckRedirects(string applicationName, string jsonString) 
     { 
      JObject jsonObj = JObject.Parse(jsonString); 
      ////Exists? --> Search in JSON. 
      foreach (KeyValuePair<string, JToken> sub_obj in (JObject)jsonObj["Redirects"]) 
      { 

      } 

      return true; 
     } 
    } 
} 

AuthenticationController.cs:

using BusinessLayer.Authentication.Interfaces; 
using Microsoft.AspNet.Identity; 
using Microsoft.Owin.Security; 
using Newtonsoft.Json.Linq; 
using System; 
using System.Collections.Generic; 
using System.Collections.Specialized; 
using System.Diagnostics; 
using System.IO; 
using System.Linq; 
using System.Net.Http; 
using System.Security.Claims; 
using System.Threading.Tasks; 
using System.Web; 
using System.Web.Http; 
using System.Web.Http.Cors; 
using System.Web.Mvc; 

namespace Servicebus.Controllers 
{ 
    [System.Web.Mvc.AllowAnonymous] 
    [EnableCors(origins: "*", headers: "*", methods: "*")] 
    public class AuthenticationController : Controller 
    { 

     /// <summary> 
     /// Service from the business layer to get the right information 
     /// </summary> 
     public IAuthenticationService aService; 
     /// <summary> 
     /// Constructor of the hourregistation controller gets the service from the unity container. 
     /// </summary> 

     public AuthenticationController(IAuthenticationService aService) 
     { 
      this.aService = aService; 
     } 

     public ActionResult Login() 
     { 
      NameValueCollection queryString = Request.QueryString; 
      aService.CheckRedirects(queryString["applicationType"], System.IO.File.ReadAllText(Server.MapPath(Url.Content("~/Content/loginRedirects.json")))); 


      String state = Guid.NewGuid().ToString(); 
      String url = this.Url.Action("Callback", "Authentication", null, this.Request.Url.Scheme).ToString(); 
      return Redirect(removed); 
     } 

     public ActionResult Callback() 
     { 
      NameValueCollection queryString = Request.QueryString; 
      if (!queryString["code"].Equals(null)) 
      { 
       IdentityStore(queryString["code"], queryString["state"]); 
      } 

      return null; 
     } 

     private void IdentityStore(string authToken, string queryString, bool isPersistent = false) 
     { 
      var claims = new List<Claim>(); 
      claims.Add(new Claim(ClaimTypes.NameIdentifier, authToken)); 
      claims.Add(new Claim("state", queryString)); 

      var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie); 

      AuthenticationManager.SignIn(new AuthenticationProperties() 
      { 
       AllowRefresh = true, 
       IsPersistent = isPersistent, 
       ExpiresUtc = DateTime.UtcNow.AddDays(7) 
      }, identity); 
     } 

     private IAuthenticationManager AuthenticationManager 
     { 
      get 
      { 
       return HttpContext.GetOwinContext().Authentication; 
      } 
     } 

     public void IdentitySignout() 
     { 

      AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie, DefaultAuthenticationTypes.ExternalCookie); 
     } 
    } 
} 

任何帮助理解。

问候!

+0

我现在完全删除在Global.asax你有OWIN启动。但基本上,您需要确保所有依赖项都在OWIN启动类中注册,因为在使用OWIN服务器启动时不会使用全局... –

+0

显示“AuthenticationController”的构造函数抛出异常的地方。 – Nkosi

+0

我试图完全删除它,但问题依然存在。所以我决定再次添加它。无论global.asax是否存在,错误似乎都是相同的。 – InSum

回答

-1

事实证明,常规控制器中的依赖注入无法使用Unity。对控制器进行更改已解决该问题。

控制器现在看起来是这样的:

 using Microsoft.AspNet.Identity; 
     using Microsoft.Owin.Security; 
     using Newtonsoft.Json.Linq; 
     using System; 
     using System.Collections.Generic; 
     using System.Collections.Specialized; 
     using System.Diagnostics; 
     using System.IO; 
     using System.Linq; 
     using System.Net.Http; 
     using System.Security.Claims; 
     using System.Threading.Tasks; 
     using System.Web; 
     using System.Web.Http; 
     using System.Web.Http.Cors; 
     using System.Web.Mvc; 

     namespace Servicebus.Controllers 
     { 
      [System.Web.Mvc.AllowAnonymous] 
      [EnableCors(origins: "*", headers: "*", methods: "*")] 
      public class AuthenticationController : Controller 
      { 

       /// <summary> 
       /// Service from the business layer to get the right information 
       /// </summary> 
       private IAuthenticationService _aService 
       { 
        get 
        { 
         return GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IAuthenticationService)) as AuthenticationService; 
        } 
       } 
       /// <summary> 
       /// Constructor of the hourregistation controller gets the service from the unity container. 
       /// </summary> 
       public AuthenticationController() 
       { 

       } 
//other functions 
    } 
    } 
+2

不,这是不正确的。你可以使用Unity进行常规的依赖注入。我有一个这样做的项目... –

+0

分享是关怀! – InSum

2

基本上,您需要确保所有依赖项都在OWIN启动类中注册,因为全局将不会用于WebApi管道。

您也可以使用共享容器以及依赖容器,以便您不初始化两个单独的实例。

快速修复:

namespace Servicebus.App_Start 
{ 
    public partial class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      WebApiConfig.Register(new HttpConfiguration()); 
      ConfigureAuth(app); 
     } 
    } 
} 

统一配备了根据自身文档的活化剂,它Provides the bootstrapping for integrating Unity with WebApi when it is hosted in ASP.NET

这是的NuGet:

<package id="Unity.AspNet.WebApi" version="3.5.1405-prerelease" targetFramework="net45" /> 

我劝您实现

重要的软件包

<package id="Microsoft.Owin.Host.SystemWeb" version="3.0.1" targetFramework="net45" /> 

你有没有得到这个?

最后的思考

我总觉得这是一个好主意,做一个小项目,只用基础设施位 - 看看你是否可以得到一个基本的网站和运行。如果你能做到这一点,那么你应该能够调试自己是什么问题。

如果你不能在你的机器上运行一个简单的网站 - 尝试另一台机器 - 如果一切都失败了,那么你有严重的问题。我已经完成了许多这些类型的项目,因此它应该很简单。

+0

我们也尝试过,我编辑了启动程序向您展示我们尝试过的内容。 – InSum

+0

你知道在Unity和ASP.NET的nuget上有一个包。我会用这个作为模板来开始 –

+0

这涉及到一个现有的项目,所以事情有点复杂。我们确实参考了参考项目。必须有我们缺少的东西。 – InSum

相关问题