Web API with Windows Service and MEF - c#

I have created a web api project and run as a windows service.
I have added MEF to load a dll (LibOne.dll) and use it in the controller (ValueController). But unable to get the values in the imported interface.
I followed this link to implement this and added MefDependencyResolver in my web api project.
How to integrate MEF with ASP.NET MVC 4 and ASP.NET Web API
in the values controller the IMyClass is returning always null. How to resolve this?
Is there anything I am mising?
Here is my Web Api Controller
[Export(typeof(ValuesController))]
public class ValuesController : ApiController
{
[Import(typeof(IMyClass))]
private IMyClass Myclass { get; set; }
public String GetString(Int32 id)
{
return Myclass.GetValues();
}
}
SelfHosted Service to run the web api as windows service
protected override void OnStart(string[] args)
{
var config = new HttpSelfHostConfiguration("http://localhost:8080");
Thread.Sleep(10000);
MefConfig.RegisterMef(config);
config.Routes.MapHttpRoute(
name: "API",
routeTemplate: "{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
HttpSelfHostServer server = new HttpSelfHostServer(config);
server.OpenAsync().Wait();
}
MEF registration
public static void RegisterMef(HttpConfiguration config)
{
var assemblyCatalog = new AggregateCatalog();
assemblyCatalog.Catalogs.Add(new DirectoryCatalog(#""));
var container = new CompositionContainer(assemblyCatalog);
var resolver = new MefDependencyResolver(container);
config.DependencyResolver = resolver;
}
Exporting this class from LibOne.dll
[Export(typeof(IMyClass))]
public class Super :IMyClass
{
public string GetValues()
{
return "My value";
}
}
MEFDependencyResolver:
internal class MefDependencyResolver : IDependencyResolver
{
private readonly CompositionContainer _container;
/// <summary />
/// <param name="container"></param>
public MefDependencyResolver(CompositionContainer container)
{
_container = container;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public IDependencyScope BeginScope()
{
return this;
}
/// <summary>
/// Called to request a service implementation.
///
/// Here we call upon MEF to instantiate implementations of dependencies.
/// </summary>
/// <param name="serviceType">Type of service requested.</param>
/// <returns>Service implementation or null.</returns>
public object GetService(Type serviceType)
{
if (serviceType == null)
throw new ArgumentNullException("serviceType");
var name = AttributedModelServices.GetContractName(serviceType);
var export = _container.GetExportedValueOrDefault<object>(name);
return export;
}
/// <summary>
/// Called to request service implementations.
///
/// Here we call upon MEF to instantiate implementations of dependencies.
/// </summary>
/// <param name="serviceType">Type of service requested.</param>
/// <returns>Service implementations.</returns>
public IEnumerable<object> GetServices(Type serviceType)
{
if (serviceType == null)
throw new ArgumentNullException("serviceType");
var exports = _container.GetExportedValues<object>(AttributedModelServices.GetContractName(serviceType));
return exports;
}
/// <summary>
///
/// </summary>
public void Dispose()
{
}
}

Related

api request with postman

I have a mvc application. And I am using a API for retrieving. teachers.
This is the class:
[Authorize(Roles = IdentityRoles.Teacher)]
[RoutePrefix("api//current")]
public sealed class CurrentTeacherController : ApiControllerBase
{
private readonly ICurrentTeacherProcess _currentTeacherProcess;
/// <summary>
/// Constructor.
/// </summary>
public CurrentTeacherController(ICurrentTeacherProcess process)
{
_currentTeacherProcess = process;
}
/// <summary>
/// Gets the teacher data of the current user
/// </summary>
/// <returns>The TeacherDto of the current teacher</returns>
[Route("")]
[HttpGet]
public TeacherDto GetTeacher()
{
return _currentTeacherProcess.GetTeacher();
}
}
And I am using Postman for retriving a teacher. For example teacher with id: 1001.
And In Postman I put this:
http://localhost:6598/api/register/
But I get a : 404 not found exception.
This is the startup.cs file:
public sealed class Startup
{
/// <summary>
/// Configures the application for use with OWIN. This method is called implicitly by Microsoft.Owin.Host.SystemWeb.
/// </summary>
/// <param name="app"><see cref="IAppBuilder" />implementation.</param>
public void Configuration(IAppBuilder app)
{
var config = GlobalConfiguration.Configuration;
WebApiConfig.Register(config);
var container = AutofacConfig.Register(config);
app.UseAutofacLifetimeScopeInjector(container);
app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
{
AuthenticationType = "Hallo",
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = ApiGatewaySecurityTokenHandler.CreateTokenValidationParameters(
"hoi", "hoi", IdentityRoles.Duo, IdentityRoles.Competent, IdentityRoles.Berichtenbox),
TokenHandler = container.Resolve<JwtSecurityTokenHandler>()
});
app.UseStageMarker(PipelineStage.PostAuthenticate);
app.UseMiddlewareFromContainer<ApiGatewayMiddleware>();
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
update with startup.cs file
You get a 404 because a handler doesn't exist in your API for that request. You need to add the id to your API route like so
[Route("{id}")]
[HttpGet]
public TeacherDto GetTeacher(int id/* or other type if you aren't using int as your primary key*/ )
{
return _currentTeacherProcess.GetTeacher(id);
}
And your request should be:
http://localhost:6598/api/register/teachers/current/1001

Adding Unity to MVC WebApi app

Hello all I've Added Unity to an MVC app. it seems that DI is working with the MVC Portion of the app but i cannot figure out why it wont work with the API part of the application.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name:"DefaultApi",
routeTemplate:"api/{controller}/{id}",
defaults: new {id = RouteParameter.Optional}
);
config.Formatters.Add(new JsonMediaTypeFormatter());
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore;
config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.None;
}
}
public static class UnityMvcActivator
{
/// <summary>
/// Integrates Unity when the application starts.
/// </summary>
public static void Start(HttpConfiguration configuration)
{
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(UnityConfig.Container));
DependencyResolver.SetResolver(new UnityDependencyResolver(UnityConfig.Container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
// Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
/// <summary>
/// Disposes the Unity container when the application is shut down.
/// </summary>
public static void Shutdown()
{
UnityConfig.Container.Dispose();
}
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Address", action = "Index", id = UrlParameter.Optional }
);
}
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
BundleConfig.RegisterBundles(BundleTable.Bundles);
RouteConfig.RegisterRoutes(RouteTable.Routes);
UnityMvcActivator.Start(GlobalConfiguration.Configuration);
}
I am just trying to get a repository to work in the web api but i keep getting
An error occurred when trying to create a controller of type 'AddressSearchController'. Make sure that the controller has a parameterless public constructor.",
this error. I have seen a few posts about this. I have tried them and still cannot get this to work. Does anyone have any suggestions?
public class AddressSearchController:_SimpleController<Address>
{
public AddressSearchController(IRepository<Address> addressRepository) : base(addressRepository)
{
}
[HttpPost]
[Route("api/AddressSearch/Search")]
public IHttpActionResult Search([FromBody] AddressSearchDto addressSearchDto)
{
var addresses = new List<Address>()
{
CreateAddress(1,"Main St", 123),
CreateAddress(2,"Main St", 124),
CreateAddress(3,"Main St", 125),
};
return Ok(addresses);
}
static Address CreateAddress(int id,string street, int houseNumber)
{
return new Address()
{
Id = id,
StreetName = street,
HouseNumber = houseNumber
};
}
}
public static void RegisterTypes(IUnityContainer container)
{
RegisterInstances(container);
}
private static void RegisterInstances(IUnityContainer container)
{
container.RegisterType<IAddressContext, AddressContext>();
container.RegisterType(typeof(IRepository<>), typeof(Repository<>));
}
using System;
using Address_Tracker.Data.Context;
using Address_Tracker.Data.Context.Interfaces;
using Address_Tracker.Data.Repositories;
using Unity;
namespace Address_Tracker
{
/// <summary>
/// Specifies the Unity configuration for the main container.
/// </summary>
public static class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container =
new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Configured Unity Container.
/// </summary>
public static IUnityContainer Container => container.Value;
#endregion
/// <summary>
/// Registers the type mappings with the Unity container.
/// </summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>
/// There is no need to register concrete types such as controllers or
/// API controllers (unless you want to change the defaults), as Unity
/// allows resolving a concrete type even if it was not previously
/// registered.
/// </remarks>
public static void RegisterTypes(IUnityContainer container)
{
RegisterInstances(container);
}
private static void RegisterInstances(IUnityContainer container)
{
container.RegisterType<IAddressContext, AddressContext>();
container.RegisterType(typeof(IRepository<>), typeof(Repository<>));
}
}
}
Your AddressSearchController should have a default constructor, or if you have no default / parameterless constructor, then please pass interfaces instead of concrete classes in AddressSearchController.
I believe you may have such a scenario:
public class AddressSearchController : ApiController
{
public AddressSearchController(SomeClassParameter obj)
{
//some code
}
}
What you want actually is ether this:
public class AddressSearchController : ApiController
{
public AddressSearchController() // add default ctor
{
}
public AddressSearchController(SomeClassParameter obj)
{
//some code
}
}
or this:
Register the interface ISomeClassParameter for type SomeClassParameter in Unity
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
UnityConfig.RegisterComponents(); // <----- Add this line
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Register component:
container.RegisterType<ISomeClassParameter , SomeClassParameter >();
and do constructor injection :
public class AddressSearchController : ApiController
{
public AddressSearchController(ISomeClassParameter obj)
{
//some code
}
}
Also, make sure you have the WebApi version of Unity
I tried it out, it worked for me:

SignalR resolving a hub context from a change event handler

I have an issue where I can't seem to send new data to the connected Signal R clients from a ChangedEventHandler. The docs says that I can get the hub context by using:-
var context = GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
context.Clients.All.addToList(insertedCustomer);
However nothing gets sent to the clients (checked on fiddler) or any errors reported. My onchange event is wired up at the moment from Application_Start as I am creating a proof of concept. I should point out the hub does work on start up and retrieves the data from the initial GetAll call
protected void Application_Start()
{
...
_sqlTableDependency.OnChanged += _sqlTableDependency_OnChanged;
_sqlTableDependency.Start();
...
}
private void _sqlTableDependency_OnChanged(object sender, RecordChangedEventArgs<BiddingText> e)
{
switch (e.ChangeType)
{
case ChangeType.Insert:
foreach (var insertedCustomer in e.ChangedEntities)
{
var context = GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
context.Clients.All.addToList(insertedCustomer);
biddingTextList.Add(insertedCustomer);
}
break;
}
}
When I put a breakpoint on the hub context I get my ChatHub back.
My Javascript code:
$.connection.hub.url = "http://localhost:37185/signalr";
// Reference the auto-generated proxy for the hub.
var chat = $.connection.chatHub;
chat.client.initialText = function(data) {
var index;
//console.log(data.length);
for (index = 0; index < data.List.length; ++index) {
$('#list').append("<li>" + data.List[index].text + "</li>");
}
};
chat.client.addToList = function(data) {
console.log(data);
$('#list').append("<li>" + data.text + "</li>");
};
// Start the connection.
$.connection.hub.start({ jsonp: true }).done(function () {
chat.server.getAll(1831);
});
My Hub code:
public class ChatHub : Microsoft.AspNet.SignalR.Hub
{
private readonly IMediator mediator;
public ChatHub(IMediator mediator)
{
this.mediator = mediator;
}
public void GetAll(int saleId)
{
var model = mediator.Request(new BiddingTextQuery { SaleId = saleId});
Clients.Caller.initialText(model);
}
}
Not sure if this is relevant but the Clients.Connection.Identity is different everytime I use GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
Can anyone help?
I had some similar issues a while back setting up a Nancy API to publish some events to SignalR clients.
The core issue I had was that I had failed to ensure Nancy and SignalR was using the same DI container at the SignalR global level.
SignalR, as Nancy, has a default DependencyResolver that is used to resolve any dependencies in your hubs. When I failed to implement the same source of dependencies for Nancy and SignalR I basically ended up with two separate applications.
Small disclaimer: You have not posted your config code, so my solution here is based on some assumptions (as well as the following twitter answer from David Fowler when you reached out on twitter:
#rippo you have a custom dependency resolver and global has has another. You need to use one container
(https://twitter.com/davidfowl/status/635000470340153344)
Now some code:
First you need to implement a custom SignalR depependency resolver, and ensure it uses the same source of dependencies as the rest of your application.
This is the implementation I used for an Autofac container:
using Autofac;
using Autofac.Builder;
using Autofac.Core;
using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
namespace LabCommunicator.Server.Configuration
{
internal class AutofacSignalrDependencyResolver : DefaultDependencyResolver, IRegistrationSource
{
private ILifetimeScope LifetimeScope { get; set; }
public AutofacSignalrDependencyResolver(ILifetimeScope lifetimeScope)
{
LifetimeScope = lifetimeScope;
var currentRegistrationSource = LifetimeScope.ComponentRegistry.Sources.FirstOrDefault(s => s.GetType() == GetType());
if (currentRegistrationSource != null)
{
((AutofacSignalrDependencyResolver)currentRegistrationSource).LifetimeScope = lifetimeScope;
}
else
{
LifetimeScope.ComponentRegistry.AddRegistrationSource(this);
}
}
public override object GetService(Type serviceType)
{
object result;
if (LifetimeScope == null)
{
return base.GetService(serviceType);
}
if (LifetimeScope.TryResolve(serviceType, out result))
{
return result;
}
return null;
}
public override IEnumerable<object> GetServices(Type serviceType)
{
object result;
if (LifetimeScope == null)
{
return base.GetServices(serviceType);
}
if (LifetimeScope.TryResolve(typeof(IEnumerable<>).MakeGenericType(serviceType), out result))
{
return (IEnumerable<object>)result;
}
return Enumerable.Empty<object>();
}
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
var typedService = service as TypedService;
if (typedService != null)
{
var instances = base.GetServices(typedService.ServiceType);
if (instances != null)
{
return instances
.Select(i => RegistrationBuilder.ForDelegate(i.GetType(), (c, p) => i).As(typedService.ServiceType)
.InstancePerLifetimeScope()
.PreserveExistingDefaults()
.CreateRegistration());
}
}
return Enumerable.Empty<IComponentRegistration>();
}
bool IRegistrationSource.IsAdapterForIndividualComponents
{
get { return false; }
}
}
}
Next, in your SignalR config, you need to assign the custom dependency resolver:
Note: My app was using owin, so you may not need the HubConfiguration bit, but you need the GlobalHost bit (which is the one I messed up when my stuff was not working).
var resolver = new AutofacSignalrDependencyResolver(container);
'Owin config options.
var config = new HubConfiguration()
{
Resolver = resolver,
EnableDetailedErrors = true,
EnableCrossDomain = true
};
GlobalHost.DependencyResolver = resolver;
'More owin stuff
app.MapHubs(config);
Hope this will help resolve your issue.
You need to keep track of the clients that connect to the hub, and then send them the new messages, something like this
This is a base class I wrote for my Hubs
/// <summary>
/// base class for Hubs in the system.
/// </summary>
public class HubBase : Hub {
/// <summary>
/// The hub users
/// </summary>
protected static ConcurrentDictionary<Guid, HubUser> Users = new ConcurrentDictionary<Guid, HubUser>();
/// <summary>
/// Called when the connection connects to this hub instance.
/// </summary>
/// <returns>
/// A <see cref="T:System.Threading.Tasks.Task" />
/// </returns>
public override System.Threading.Tasks.Task OnConnected() {
Guid userName = RetrieveUserId();
string connectionId = Context.ConnectionId;
HubUser user = Users.GetOrAdd(userName, _ => new HubUser {
UserId = userName,
ConnectionIds = new HashSet<string>()
});
lock (user.ConnectionIds) {
user.ConnectionIds.Add(connectionId);
}
return base.OnConnected();
}
/// <summary>
/// Called when a connection disconnects from this hub gracefully or due to a timeout.
/// </summary>
/// <param name="stopCalled">true, if stop was called on the client closing the connection gracefully;
/// false, if the connection has been lost for longer than the
/// <see cref="P:Microsoft.AspNet.SignalR.Configuration.IConfigurationManager.DisconnectTimeout" />.
/// Timeouts can be caused by clients reconnecting to another SignalR server in scaleout.</param>
/// <returns>
/// A <see cref="T:System.Threading.Tasks.Task" />
/// </returns>
public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled) {
try {
Guid userName = RetrieveUserId();
string connectionId = Context.ConnectionId;
HubUser user;
Users.TryGetValue(userName, out user);
if (user != null) {
lock (user.ConnectionIds) {
user.ConnectionIds.RemoveWhere(cid => cid.Equals(connectionId));
if (!user.ConnectionIds.Any()) {
HubUser removedUser;
Users.TryRemove(userName, out removedUser);
}
}
}
} catch {
//Bug in SignalR causing Context.User.Identity.Name to sometime be null
//when user disconnects, thus remove the connection manually.
lock (Users) {
HubUser entry = Users.Values.FirstOrDefault(v => v.ConnectionIds.Contains(Context.ConnectionId));
if (entry != null) entry.ConnectionIds.Remove(Context.ConnectionId);
}
}
return base.OnDisconnected(stopCalled);
}
private Guid RetrieveUserId() {
Cookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket decryptedCookie = FormsAuthentication.Decrypt(authCookie.Value);
var user = JsonConvert.DeserializeObject<User>(decryptedCookie.UserData);
return user.Id;
}
}
Then the Hub code is
/// <summary>
/// A hub for sending alerts to users.
/// </summary>
public class AlertHub : HubBase, IAlertHub {
/// <summary>
/// Sends the alert.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="userId">The user identifier.</param>
public void SendAlert(string message, Guid userId) {
HubUser user;
Users.TryGetValue(userId, out user);
if (user != null) {
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<AlertHub>();
context.Clients.Clients(user.ConnectionIds.ToList()).sendAlert(message);
}
}
/// <summary>
/// Send alert to user.
/// </summary>
/// <param name="returnId">The return identifier.</param>
/// <param name="userId">The user identifier.</param>
public void ReturnProcessedAlert(Guid returnId, Guid userId) {
HubUser user;
Users.TryGetValue(userId, out user);
if (user != null) {
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<AlertHub>();
context.Clients.Clients(user.ConnectionIds.ToList()).returnProcessedAlert(returnId);
}
}
}

Owin Web Api statup.cs with ninject

I have a problem to use web api Owin with ninject. When I try to use my web api , it was this error, and I can not fix this problem , I've tried many ways , none of which revolved my problem.
This error occurs when I boot my application
Error activating ModelValidatorProvider using binding from ModelValidatorProvider to
NinjectDefaultModelValidatorProvider
A cyclical dependency was detected between the constructors of two services.
Activation path:
3) Injection of dependency ModelValidatorProvider into parameter defaultModelValidatorProviders of constructor of type DefaultModelValidatorProviders
2) Injection of dependency DefaultModelValidatorProviders into parameter defaultModelValidatorProviders of constructor of type NinjectDefaultModelValidatorProvider
1) Request for ModelValidatorProvider
Suggestions:
1) Ensure that you have not declared a dependency for ModelValidatorProvider on any implementations of the service.
2) Consider combining the services into a single one to remove the cycle.
3) Use property injection instead of constructor injection, and implement IInitializable
if you need initialization logic to be run after property values have been injected
My statup.cs
var config = new HttpConfiguration();
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/api/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(365),
Provider = new SimpleAuthorizationServerProvider(),
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
config.DependencyResolver = new NinjectResolver(NinjectWebCommon.CreateKernel());
app.UseWebApi(config);
My class DependencyResolver.cs
public class NinjectDependencyScope : IDependencyScope, System.Web.Mvc.IDependencyResolver
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
this.resolver = resolver;
}
public void Dispose()
{
resolver = null;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.GetAll(serviceType);
}
}
public class NinjectResolver : NinjectDependencyScope, System.Web.Mvc.IDependencyResolver, IDependencyResolver
{
private IKernel kernel;
public NinjectResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel);
}
}
and my class NinjectWebCommon.cs
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
public static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
//Injeções de Depêndencias
//Inject AppService
kernel.Bind(typeof (IAppServiceBase<>)).To(typeof (AppServiceBase<>));
kernel.Bind<ICanalDistribuicaoAppService>().To<CanalDistribuicaoAppService>();
kernel.Bind<ICaracteristicasAppService>().To<CaracteristicasAppService>();
kernel.Bind<ICaracteristicasValorAppService>().To<CaracteristicasValorAppService>();
kernel.Bind<ICentroAppService>().To<CentroAppService>();
kernel.Bind<IClassificacaoContabilAppService>().To<ClassificacaoContabilAppService>();
kernel.Bind<IClienteAppService>().To<ClienteAppService>();
kernel.Bind<IClienteModalidadeCentroAppService>().To<ClienteModalidadeCentroAppService>();
kernel.Bind<IClienteTipoCarregamentoCentroAppService>().To<ClienteTipoCarregamentoCentroAppService>();
kernel.Bind<IClienteEmailAppService>().To<ClienteEmailAppService>();
kernel.Bind<IClienteGrupoAppService>().To<ClienteGrupoAppService>();
kernel.Bind<IClienteStatusAppService>().To<ClienteStatusAppService>();
kernel.Bind<ICondicaoPagamentoAppService>().To<CondicaoPagamentoAppService>();
kernel.Bind<IDimensoesAppService>().To<DimensoesAppService>();
kernel.Bind<IEmbalagemAppService>().To<EmbalagemAppService>();
kernel.Bind<IEscritorioVendasAppService>().To<EscritorioVendasAppService>();
kernel.Bind<IEstoqueAppService>().To<EstoqueAppService>();
kernel.Bind<IGrupoProdutoRestritoAppService>().To<GrupoProdutoRestritoAppService>();
kernel.Bind<ILiberacaoCIFAppService>().To<LiberacaoCIFAppService>();
kernel.Bind<ILocalRetiradaAppService>().To<LocalRetiradaAppService>();
kernel.Bind<IMateriaisAppService>().To<MateriaisAppService>();
kernel.Bind<IModalidadeAppService>().To<ModalidadeAppService>();
kernel.Bind<IOrganizacaoVendasAppService>().To<OrganizacaoVendasAppService>();
kernel.Bind<IPedidoFavoritoAppService>().To<PedidoFavoritoAppService>();
kernel.Bind<IProdutoAppService>().To<ProdutoAppService>();
kernel.Bind<IRamoEmpresaAppService>().To<RamoEmpresaAppService>();
kernel.Bind<ISegmentoMercadoAppService>().To<SegmentoMercadoAppService>();
kernel.Bind<ISetorAtividadeAppService>().To<SetorAtividadeAppService>();
kernel.Bind<IStatusReservaAppService>().To<StatusReservaAppService>();
kernel.Bind<ISubstituicaoFiscalAppService>().To<SubstituicaoFiscalAppService>();
kernel.Bind<ITipoCarregamentoAppService>().To<TipoCarregamentoAppService>();
kernel.Bind<ITipoEmailAppService>().To<TipoEmailAppService>();
kernel.Bind<IUtilizacaoAppService>().To<UtilizacaoAppService>();
kernel.Bind<IUsuarioAppService>().To<UsuarioAppService>();
//Inject Services
kernel.Bind(typeof (IServiceBase<>)).To(typeof (ServiceBase<>));
kernel.Bind<ICanalDistribuicaoService>().To<CanalDistribuicaoService>();
kernel.Bind<ICaracteristicasService>().To<CaracteristicasService>();
kernel.Bind<ICaracteristicasValorService>().To<CaracteristicasValorService>();
kernel.Bind<ICentroService>().To<CentroService>();
kernel.Bind<IClassificacaoContabilService>().To<ClassificacaoContabilService>();
kernel.Bind<IClienteService>().To<ClienteService>();
kernel.Bind<IClienteModalidadeCentroService>().To<ClienteModalidadeCentroService>();
kernel.Bind<IClienteTipoCarregamentoCentroService>().To<ClienteTipoCarregamentoCentroService>();
kernel.Bind<IClienteEmailService>().To<ClienteEmailService>();
kernel.Bind<IClienteGrupoService>().To<ClienteGrupoService>();
kernel.Bind<IClienteStatusService>().To<ClienteStatusService>();
kernel.Bind<ICondicaoPagamentoService>().To<CondicaoPagamentoService>();
kernel.Bind<IDimensoesService>().To<DimensoesService>();
kernel.Bind<IEmbalagemService>().To<EmbalagemService>();
kernel.Bind<IEscritorioVendasService>().To<EscritorioVendasService>();
kernel.Bind<IEstoqueService>().To<EstoqueService>();
kernel.Bind<IGrupoProdutoRestritoService>().To<GrupoProdutoRestritoService>();
kernel.Bind<ILiberacaoCIFService>().To<LiberacaoCIFService>();
kernel.Bind<ILocalRetiradaService>().To<LocalRetiradaService>();
kernel.Bind<IMateriaisService>().To<MateriaisService>();
kernel.Bind<IModalidadeService>().To<ModalidadeService>();
kernel.Bind<IOrganizacaoVendasService>().To<OrganizacaoVendasService>();
kernel.Bind<IPedidoFavoritoService>().To<PedidoFavoritoService>();
kernel.Bind<IProdutoService>().To<ProdutoService>();
kernel.Bind<IRamoEmpresaService>().To<RamoEmpresaService>();
kernel.Bind<ISegmentoMercadoService>().To<SegmentoMercadoService>();
kernel.Bind<ISetorAtividadeService>().To<SetorAtividadeService>();
kernel.Bind<IStatusReservaService>().To<StatusReservaService>();
kernel.Bind<ISubstituicaoFiscalService>().To<SubstituicaoFiscalService>();
kernel.Bind<ITipoCarregamentoService>().To<TipoCarregamentoService>();
kernel.Bind<ITipoEmailService>().To<TipoEmailService>();
kernel.Bind<IUtilizacaoService>().To<UtilizacaoService>();
kernel.Bind<IUsuarioService>().To<UsuarioService>();
//Inject Repositories
kernel.Bind(typeof (IRepositoryBase<>)).To(typeof (RepositoryBase<>));
kernel.Bind<ICanalDistribuicaoRepository>().To<CanalDistribuicaoRepository>();
kernel.Bind<ICaracteristicasRepository>().To<CaracteristicasRepository>();
kernel.Bind<ICaracteristicasValorRepository>().To<CaracteristicasValorRepository>();
kernel.Bind<ICentroRepository>().To<CentroRepository>();
kernel.Bind<IClassificacaoContabilRepository>().To<ClassificacaoContabilRepository>();
kernel.Bind<IClienteRepository>().To<ClienteRepository>();
kernel.Bind<IClienteModalidadeCentroRepository>().To<ClienteModalidadeCentroRepository>();
kernel.Bind<IClienteTipoCarregamentoCentroRepository>().To<ClienteTipoCarregamentoCentroRepository>();
kernel.Bind<IClienteEmailRepository>().To<ClienteEmailRepository>();
kernel.Bind<IClienteGrupoRepository>().To<ClienteGrupoRepository>();
kernel.Bind<IClienteStatusRepository>().To<ClienteStatusRepository>();
kernel.Bind<ICondicaoPagamentoRepository>().To<CondicaoPagamentoRepository>();
kernel.Bind<IDimensoesRepository>().To<DimensoesRepository>();
kernel.Bind<IEmbalagemRepository>().To<EmbalagemRepository>();
kernel.Bind<IEscritorioVendasRepository>().To<EscritorioVendasRepository>();
kernel.Bind<IEstoqueRepository>().To<EstoqueRepository>();
kernel.Bind<IGrupoProdutoRestritoRepository>().To<GrupoProdutoRestritoRepository>();
kernel.Bind<ILiberacaoCIFRepository>().To<LiberacaoCIFRepository>();
kernel.Bind<ILocalRetiradaRepository>().To<LocalRetiradaRepository>();
kernel.Bind<IMateriaisRepository>().To<MateriaisRepository>();
kernel.Bind<IModalidadeRepository>().To<ModalidadeRepository>();
kernel.Bind<IOrganizacaoVendasRepository>().To<OrganizacaoVendasRepository>();
kernel.Bind<IPedidoFavoritoRepository>().To<PedidoFavoritoRepository>();
kernel.Bind<IProdutoRepository>().To<ProdutoRepository>();
kernel.Bind<IRamoEmpresaRepository>().To<RamoEmpresaRepository>();
kernel.Bind<ISegmentoMercadoRepository>().To<SegmentoMercadoRepository>();
kernel.Bind<ISetorAtividadeRepository>().To<SetorAtividadeRepository>();
kernel.Bind<IStatusReservaRepository>().To<StatusReservaRepository>();
kernel.Bind<ISubstituicaoFiscalRepository>().To<SubstituicaoFiscalRepository>();
kernel.Bind<ITipoCarregamentoRepository>().To<TipoCarregamentoRepository>();
kernel.Bind<ITipoEmailRepository>().To<TipoEmailRepository>();
kernel.Bind<IUtilizacaoRepository>().To<UtilizacaoRepository>();
kernel.Bind<IUsuarioRepository>().To<UsuarioRepository>();
}
}
Help me plis.
I know its very old Q but still comes up in google in top 3 search for this error. So as a solution just remove ninject.web.webapi and its dependencies like ninject.web.webapi.webhost.

Extend windsor dependency injection to cover web api part of website?

I have an ASP.NET MVC application, which uses Windsor for dependency injection.
Now, I have started to build an API inside the application under /controllers/api .
In my first API controller, I need access to some services from my domain project, which is added by Windsor. This works perfectly for normal controllers. However, whwen I for instance access /api/officeproduct/gettest , I get the following error:
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<script id="tinyhippos-injected"/>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Type 'LetterAmazer.Websites.Client.Controllers.Api.OfficeProductController' does not have a default constructor
</ExceptionMessage>
<ExceptionType>System.ArgumentException</ExceptionType>
<StackTrace>
at System.Linq.Expressions.Expression.New(Type type) at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
</StackTrace>
</Error>
I really don't know how to fix it, despite using a lot of time so way. Any ideas how to get it to work?
My API controller:
public class OfficeProductController : ApiController
{
private IOfficeProductService officeProductService;
public OfficeProductController(IOfficeProductService officeProductService)
{
this.officeProductService = officeProductService;
}
[System.Web.Http.HttpPost]
public ActionResult Create(OfficeProductViewModel model)
{
var officeProduct = new OfficeProduct()
{
CountryId = 1,
ProductScope = ProductScope.Single,
LetterDetails = new LetterDetails()
{
LetterColor = LetterColor.BlackWhite,
LetterPaperWeight = LetterPaperWeight.Eight,
LetterProcessing = LetterProcessing.Dull,
LetterSize = LetterSize.A4,
LetterType = LetterType.Pres
},
OfficeId = 1
};
officeProductService.Create(officeProduct);
return new JsonResult();
}
[System.Web.Http.HttpPost]
public ActionResult Test(string id)
{
return new ContentResult() { Content = id };
}
[System.Web.Http.HttpGet]
public ActionResult Gettest()
{
return new ContentResult() {Content ="hej"};
}
}
Web API registration:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Global.asax:
public class MvcApplication : System.Web.HttpApplication, IContainerAccessor
{
protected void Application_Start()
{
log4net.Config.XmlConfigurator.Configure();
InitializeContainer();
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
private void InitializeContainer()
{
var oldProvider = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider);
FilterProviders.Providers.Remove(oldProvider);
Container.Register(Component.For<IWindsorContainer>().Instance(this.Container));
Container.Install(new BootstrapInstaller());
registerCustom();
Container.Install(new WebWindsorInstaller());
var provider = new WindsorFilterAttributeFilterProvider(this.Container);
FilterProviders.Providers.Add(provider);
DependencyResolver.SetResolver(new WindsorDependencyResolver(ServiceFactory.Container));
}
private void registerCustom()
{
// All services in service DLL
var assembly = Assembly.LoadFrom(Server.MapPath("~/bin/LetterAmazer.Business.Services.dll"));
;
Container.Register(
Classes.FromAssembly(assembly)
.InNamespace("LetterAmazer.Business.Services.Services")
.WithServiceAllInterfaces());
Container.Register(
Classes.FromAssembly(assembly)
.InNamespace("LetterAmazer.Business.Services.Services.FulfillmentJobs")
.WithServiceAllInterfaces());
Container.Register(
Classes.FromAssembly(assembly)
.InNamespace("LetterAmazer.Business.Services.Services.PaymentMethods.Implementations")
.WithServiceAllInterfaces());
// All factories in service DLL
Container.Register(
Classes.FromAssembly(assembly)
.InNamespace("LetterAmazer.Business.Services.Factory")
.WithServiceAllInterfaces());
Container.Register(Component.For<LetterAmazerEntities>());
}
public IWindsorContainer Container
{
get { return ServiceFactory.Container; }
}
}
Windsor - dependency resolver:
/// <summary>
/// Reference: http://stackoverflow.com/questions/4140860/castle-windsor-dependency-resolver-for-mvc-3
/// </summary>
public class WindsorDependencyResolver : IDependencyResolver
{
private readonly IWindsorContainer container = null;
/// <summary>
///
/// </summary>
/// <param name="container"></param>
public WindsorDependencyResolver(IWindsorContainer container)
{
this.container = container;
}
/// <summary>
///
/// </summary>
/// <param name="serviceType"></param>
/// <returns></returns>
public object GetService(Type serviceType)
{
return container.Kernel.HasComponent(serviceType) ? container.Resolve(serviceType) : null;
}
/// <summary>
///
/// </summary>
/// <param name="serviceType"></param>
/// <returns></returns>
public IEnumerable<object> GetServices(Type serviceType)
{
return container.Kernel.HasComponent(serviceType) ? container.ResolveAll(serviceType).Cast<object>() : new object[] {};
}
}
Windsor - controller factory
/// <summary>
/// Controller Factory class for instantiating controllers using the Windsor IoC container.
/// </summary>
public class WindsorControllerFactory : DefaultControllerFactory
{
private static readonly ILog logger = LogManager.GetLogger(typeof(WindsorControllerFactory));
private readonly IWindsorContainer container = null;
/// <summary>
///
/// </summary>
/// <param name="container"></param>
public WindsorControllerFactory(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404,
string.Format("The controller for path '{0}' could not be found or it does not implement IController.",
requestContext.HttpContext.Request.Path));
}
IController controller = (IController)container.Resolve(controllerType);
return controller;
}
/// <summary>
///
/// </summary>
/// <param name="controller"></param>
public override void ReleaseController(IController controller)
{
var disposable = controller as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
container.Release(controller);
}
You need to create a class that implements IHttpControllerActivator then register it when you initialize the container.
WindsorHttpControllerActivator
public class WindsorHttpControllerActivator : IHttpControllerActivator
{
private readonly IWindsorContainer _container;
public WindsorHttpControllerActivator(IWindsorContainer container)
{
_container = container;
}
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
var controller = (IHttpController)_container.Resolve(controllerType);
request.RegisterForDispose(new Release(() => _container.Release(controller)));
return controller;
}
private class Release : IDisposable
{
private readonly Action _release;
public Release(Action release)
{
_release = release;
}
public void Dispose()
{
_release();
}
}
}
Register HttpControllerActivator
private void InitializeContainer()
{
var oldProvider = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider);
FilterProviders.Providers.Remove(oldProvider);
Container.Register(Component.For<IWindsorContainer>().Instance(this.Container));
Container.Install(new BootstrapInstaller());
registerCustom();
Container.Install(new WebWindsorInstaller());
var provider = new WindsorFilterAttributeFilterProvider(this.Container);
FilterProviders.Providers.Add(provider);
DependencyResolver.SetResolver(new WindsorDependencyResolver(ServiceFactory.Container));
// register WebApi controllers
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new WindsorHttpControllerActivator(ServiceFactory.Container));
}

Categories

Resources