webapiconfig varias solicitud solicitado recurso que ningún net método encontraron encontrado con coincidían coinciden coincida asp admite acciones c# asp.net-web-api controller ioc-container constructor-injection

c# - varias - ¿Cómo se llama el constructor del controlador de API web?



se encontraron varias acciones que coincidían con la solicitud web api (3)

De acuerdo con este artículo , un controlador debe tener un constructor que obtenga la interfaz que se implementará pasada, a la:

public class DuckbillsController : ApiController { IDuckbillRepository _platypiRepository; public DuckbillsController(IDuckbillRepository platypiRepository) { if (platypiRepository == null) { throw new ArgumentNullException("platypiRepository is null"); } _platypiRepository = platypiRepository; } }

Pero, ¿cómo se llama este constructor? Un reconocimiento a través de un cliente que llama a un método API web incluido en esta clase, pero ¿cómo se pasa el tipo de interfaz? ¿O eso no tiene que suceder (el constructor no es invocado explícitamente por nadie / desde ningún lugar)?

ACTUALIZAR

Los ejemplos canónicos muestran "readonly privado" antepuesto a la declaración de interfaz, pero no es necesario compilarlo. ¿Hay algún motivo de compilación, es decir, convincente, para que preceda "lectura privada"?


La fábrica del controlador los crea para ti ... Debes echarle un vistazo a Inyección de dependencia.

Pruebe Autofac, tiene una buena integración para MVC.


Tienes que usar una inyección de dependencia (structmap, ninject) lo que sea. Si no desea utilizar DI, debe proporcionar un constructor de sobrecarga como se muestra a continuación.

public DuckbillsController():this( new DuckbillRepository()) { }


Ya que no hay documentación sobre esto en ningún lugar (los documentos oficiales solo hablan de hacerlo con Unity). Así es como lo haces.

La propiedad HttpConfiguration.DependencyResolver es una instancia de IDependecyResolver que básicamente es un localizador de servicios (usted solicita una instancia de tipo y sabe cómo crearla). Lo que me gustaría es proporcionar mi propia instanciación de controlador.

Úselo así:

config.DependencyResolver = new OverriddenWebApiDependencyResolver(config.DependencyResolver) .Add(typeof(ScoreboardController), () => new ScoreboardController(Messages) );

Implementado así:

/// <summary> /// The standard web api dependency resolver cannot inject dependencies into a controller /// use this as a simple makeshift IoC /// </summary> public class OverriddenWebApiDependencyResolver : WebApiOverrideDependency<IDependencyResolver >, IDependencyResolver { public OverriddenWebApiDependencyResolver Add(Type serviceType, Func<object> initializer) { provided.Add(serviceType, initializer); return this; } public IDependencyScope BeginScope() => new Scope(inner.BeginScope(), provided); public OverriddenWebApiDependencyResolver(IDependencyResolver inner) : base(inner, new Dictionary<Type, Func<object>>()) { } public class Scope : WebApiOverrideDependency<IDependencyScope>, IDependencyScope { public Scope(IDependencyScope inner, IDictionary<Type, Func<object>> provided) : base(inner, provided) { } } } public abstract class WebApiOverrideDependency<T> : IDependencyScope where T : IDependencyScope { public void Dispose() => inner.Dispose(); public Object GetService(Type serviceType) { Func<Object> res; return provided.TryGetValue(serviceType, out res) ? res() : inner.GetService(serviceType); } public IEnumerable<Object> GetServices(Type serviceType) { Func<Object> res; return inner.GetServices(serviceType).Concat(provided.TryGetValue(serviceType, out res) ? new[] { res()} : Enumerable.Empty<object>()); } protected readonly T inner; protected readonly IDictionary<Type, Func<object>> provided; public WebApiOverrideDependency(T inner, IDictionary<Type, Func<object>> provided) { this.inner = inner; this.provided = provided; } }

El truco es que en realidad tiene que implementar IDependencyScope dos veces : una para IDependencyResolver y otra para el alcance que crea en cada solicitud.