【问题标题】:Web API, Unity and Parameterless ConstructorWeb API、Unity 和无参数构造函数
【发布时间】:2017-08-15 12:59:34
【问题描述】:

我有一个 Web API 解决方案,我想将一个类注入到我的 Controller 构造函数中。

我正在使用统一:

WebApiConfig.cs

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var container = new UnityContainer();
        container.RegisterType<IDatabaseAdapter, DatabaseAdapter>(new HierarchicalLifetimeManager());
        config.DependencyResolver = new UnityResolver(container);

        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
        var constraintResolver = new DefaultInlineConstraintResolver
                                 {
                                     ConstraintMap =
                                     {
                                         ["apiVersion"] = typeof(ApiVersionRouteConstraint)
                                     }
                                 };
        config.MapHttpAttributeRoutes(constraintResolver);
        config.AddApiVersioning();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

UnityResolver

public class UnityResolver : IDependencyResolver
{
    protected IUnityContainer _container;

    public UnityResolver(IUnityContainer container)
    {
        _container = container ?? throw new ArgumentNullException("container");
    }

    public object GetService(Type serviceType)
    {
        try
        {
            return _container.Resolve(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        try
        {
            return _container.ResolveAll(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return new List<object>();
        }
    }

    public IDependencyScope BeginScope()
    {
        var child = _container.CreateChildContainer();
        return new UnityResolver(child);
    }

    public void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        _container.Dispose();
    }
}

我的控制器。

[System.Web.Http.RoutePrefix("api/v{version:apiVersion}/measurements")]
[ApiVersion("1.0")]
public class MeasurementsController : Controller
{
    private readonly IDatabaseAdapter _databaseAdapter;
    [InjectionConstructor]
    public MeasurementsController(IDatabaseAdapter databaseAdapter)
    {
        _databaseAdapter = databaseAdapter;
    }
    [MapToApiVersion("1.0")]
    [System.Web.Http.Route("GetTrafficLights")]
    public JsonResult GetTrafficLights()
    {
        var trafficLights = TrafficLightCache.TrafficLightCache.TrafficLights();
        var result = new JsonResult
        {
            Data = JsonConvert.SerializeObject(trafficLights),
            JsonRequestBehavior = JsonRequestBehavior.AllowGet
        };
        return result;
    }
    [MapToApiVersion("1.0")]
    [System.Web.Http.Route("UpdateMeasurement")]
    public async Task<HttpStatusCodeResult> Update(string measurementToUpdate)
    {
        var measurement = JsonConvert.DeserializeObject<Measurement>(measurementToUpdate, new JsonSerializerSettings
        {
            DateTimeZoneHandling = DateTimeZoneHandling.Utc
        });
        await _databaseAdapter.Update(measurement);
        return new HttpStatusCodeResult(HttpStatusCode.Accepted);
    }
}

数据库适配器

public class DatabaseAdapter : IDatabaseAdapter
{
   public async Task<Dictionary<int, CacheEntry>> MeasurementCache()
   { ... }

   public async Task Update(Measurement measurement)
   { ... }
}

IDatabaseAdapter

public interface IDatabaseAdapter
{
    Task<Dictionary<int, TrafficLightCache.CacheEntry>> MeasurementCache();
    Task Update(Measurement measurement);
}

错误提示找不到无参数构造函数。如果我添加一个空的无参数构造函数,它永远不会触发包含 IDatabaseAdapter 注入的构造函数,因此对 Update 的调用总是导致 _databaseAdapter 为空。

堆栈跟踪是

[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) +247
   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 'APITest2.Controllers.V1.MeasurementsController'. 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

【问题讨论】:

  • The error says no parameterless constructor found. 请附上异常的堆栈跟踪/屏幕截图。
  • no parameterless constructor found属于哪一类?
  • @ChetanRanpariya - MeasurementsController
  • @ChetanRanpariya - 如果我添加无参数构造函数,我不会收到错误,但 DatabaseAdapter 没有注入并且始终为空。
  • 我认为控制器需要一个无参构造函数,尝试从填充实例的无参构造函数中自己调用构造函数。

标签: c# asp.net-mvc asp.net-web-api dependency-injection


【解决方案1】:

您需要使用 ApiController。不是控制器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    相关资源
    最近更新 更多