Comment utiliser Unity avec Asp.Net WebApi MVC4 RTM

La version RTM d’asp.net MVC4 est maintenant disponible à l’adresse suivante : http://www.microsoft.com/en-us/download/details.aspx?id=30683

Il y a eu quelques changements entre la version Beta puis RC pour utiliser Unity avec WebApi, voici une solution, dans un premier temps il faudra utiliser la nouvelle version de unity disponible via NuGet :

image

Il faut ensuite instancier le container dans Global.asax de la manière suivante :

	public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);

var container = new Microsoft.Practices.Unity.UnityContainer();
container.RegisterType<Services.ValueService>();

System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new UnityServiceDependencyResolver(container);
}
}

Le dependency resolver de webapi est configurable, c’est ce que l’on peut voir à la dernière ligne , voici la classe utilisée :

	public class UnityServiceDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver
{
Microsoft.Practices.Unity.IUnityContainer m_Container;
System.Web.Http.Dependencies.IDependencyResolver m_DefaultResolver;

public UnityServiceDependencyResolver(Microsoft.Practices.Unity.IUnityContainer container)
{
m_Container = container;
m_DefaultResolver = System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver;
}

public System.Web.Http.Dependencies.IDependencyScope BeginScope()
{
// This example does not support child scopes, so we simply return 'this'.
return this;
}

public object GetService(Type serviceType)
{
if (IsBuiltIn(serviceType))
{
return m_DefaultResolver.GetService(serviceType);
}
return m_Container.Resolve(serviceType);
}

public IEnumerable<object> GetServices(Type serviceType)
{
if (IsBuiltIn(serviceType))
{
return m_DefaultResolver.GetServices(serviceType);
}

return m_Container.ResolveAll(serviceType);
}

private bool IsBuiltIn(Type serviceType)
{
if (serviceType == typeof(System.Web.Http.Tracing.ITraceManager)
|| serviceType == typeof(System.Web.Http.Tracing.ITraceWriter)
|| serviceType == typeof(System.Web.Http.Dispatcher.IHttpControllerSelector)
|| serviceType == typeof(System.Web.Http.Dispatcher.IAssembliesResolver)
|| serviceType == typeof(System.Net.Http.Formatting.IContentNegotiator)
|| serviceType == typeof(System.Web.Http.Dispatcher.IHttpControllerTypeResolver)
|| serviceType == typeof(System.Web.Http.Dispatcher.IHttpControllerActivator)
|| serviceType == typeof(System.Web.Http.Controllers.IHttpActionSelector)
|| serviceType == typeof(System.Web.Http.Controllers.IHttpActionInvoker)
|| serviceType == typeof(System.Web.Http.Controllers.IActionValueBinder)
|| serviceType == typeof(System.Web.Http.Validation.IBodyModelValidator)
|| serviceType == typeof(System.Web.Http.Metadata.ModelMetadataProvider)
|| serviceType == typeof(System.Web.Http.Hosting.IHostBufferPolicySelector)
|| serviceType.FullName.Equals("System.Web.Http.Validation.IModelValidatorCache")
)
{
return true;
}
return false;
}

public void Dispose()
{
m_Container.Dispose();
}
}

L’idée c’est d’utiliser le resolver standard pour les types prédéfinis, a noter certains type comme IModelValidatorCache sont internal, pour tous les autres cas on utilise le resolver Unity passé en paramètre du constructeur, pour utiliser ses propres services et les resoudre par injection de dépendance.


Ci-dessous le controller sample “ValueController” refactoré pour utiliser un service prédéclaré :

	public class ValuesController : ApiController
{
public ValuesController(Services.ValueService valueService)
{
this.ValueService = valueService;
}

protected Services.ValueService ValueService { get; private set; }

// GET api/values
public IEnumerable<string> Get()
{
return ValueService.GetList();
}

// GET api/values/5
public string Get(int id)
{
return ValueService.GetList().ElementAt(id);
}

// POST api/values
public void Post([FromBody]string value)
{
ValueService.Add(value);
}

// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
}

// DELETE api/values/5
public void Delete(int id)
{
}
}

Le resultat est le suivant :


image

Aucun commentaire: