Issue on using AutoMapper in asp.net core - asp.net

I am following a tutorial on asp.net core and angular. When I add the Automapper inside my Startup class it crashes the dotnet cli and couldn't render the page. This is how I use the Automapper in the Startup:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SpaServices.AngularCli;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using aspcoreangular.persistence;
using AutoMapper;
namespace aspcoreangular
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAutoMapper();
services.AddDbContext<VegaDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Default")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
}
}
This is how I use it in the controller. But it doesn't get to this point
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using aspcoreangular.models;
using aspcoreangular.persistence;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace aspcoreangular.Controllers
{
public class MakesController : Controller
{
private readonly VegaDbContext context;
private readonly IMapper mapper;
protected MakesController(VegaDbContext context, IMapper mapper)
{
this.mapper = mapper;
this.context = context;
}
[HttpGet("/api/makes")]
public async Task<IEnumerable<Resources.MakeResource>> GetMakes()
{
var makes = await context.Makes.Include(m => m.Models).ToListAsync();
return mapper.Map<List<Make>, List<Resources.MakeResource>>(makes);
}
}
}
This is the image of the crash:
Can you please help me with this? Thank you.
This my MakeResouce class
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using aspcoreangular.models;
namespace aspcoreangular.Controllers.Resources
{
public class MakeResource
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<ModelResource> Models { get; set; }
public MakeResource()
{
Models = new Collection<ModelResource>();
}
}
}
and in my mappingprofile
using aspcoreangular.Controllers.Resources;
using aspcoreangular.models;
using AutoMapper;
namespace aspcoreangular.ClientApp.Mapping
{
public class MappingProfile : Profile
{
protected MappingProfile()
{
CreateMap<Make, MakeResource>();
CreateMap<Model, ModelResource>();
}
}
}

When AutoMapper maps source object to destination object before mapping itself it has to create an instance of the destination object and then Mapper can map properties using reflection.
And the error says: No parameterless constructor is defined for this object.
That means: AutoMapper kindly asks System.Activator class to create instance of the destination object for him. But System.Activator fails because it can't find public parameterless contructor in destination class (obviously, System.Activator can use constructor with parameters, but AutoMapper hadn't provided any parameters for constructor). And that is why the third line of the Error message comes from Activator.CreateInstance method.
So, to sum up, you should examine Resources.MakeResource class (as destination) for parameterless constructor.
PS. But I can't tell you on Why this exception crashes the whole Application

Related

Why is the presence of middleware preventing execution of an endpoint?

I am a beginner at ASP.Net. Here is my startup.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;
using CAPSWebServer.CapsDataModels;
namespace CAPSWebServer
{
public class Startup
{
public IConfiguration Configuration { get; set; }
public Startup(IConfiguration config)
{
Configuration = config;
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CapsDataContext>(opts =>
{
opts.UseNpgsql(Configuration["ConnectionStrings:CAPSConnection"]);
opts.EnableSensitiveDataLogging(true);
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseMiddleware<TestMiddleware>();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
}
}
And here is my TestMiddleware class:
using Microsoft.AspNetCore.Http;
using System.Linq;
using System.Threading.Tasks;
using CAPSWebServer.CapsDataModels;
namespace CAPSWebServer
{
public class TestMiddleware
{
private RequestDelegate nextDelegate;
public TestMiddleware(RequestDelegate next)
{
nextDelegate = next;
}
public async Task Invoke(HttpContext context, CapsDataContext dataContext)
{
if (context.Request.Path == "/test")
{
await context.Response.WriteAsync($"There are {dataContext.Charges.Count()} charges.\n");
await context.Response.WriteAsync($"There are {dataContext.Inventories.Count()} coils.\n");
}
}
}
}
This application is configured to listen on port 500 of my computer. When I run localhost:5000/test, I get the expected report of how many charges and coils I have in my database. But when I run localhost:5000 by itself, I get nothing. I think I should be getting "Hello, world". If I comment out out the call to UseMiddleware(), I get "Hello, world". Why does the middleware block the endpoint?
I am using Visual Studio 2019.
You need to call the
nextDelegate();
So that the next middleware down the line is executed.
The reason it works when the URL contains "/test" is because you are writing directly into the response stream.

How can you add a Microsoft Graph client service as a MediatR service in .NET Core 3.1?

So I have a .NET Core web API with it's own local data context, and I'd like to add the ability to call Microsoft Graph as a downstream API.
However, when I try to add the necessary properties to call the Graph API, I get a build error:
Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: MediatR.IRequestHandler`2[Application.Users.Me+Query,Microsoft.Graph.User] Lifetime: Transient ImplementationType: Application.Users.Me+Handler': Unable to resolve service for type 'Microsoft.Graph.GraphServiceClient' while attempting to activate 'Application.Users.Me+Handler'.)
Here is my startup class:
using API.Middleware;
using Application.TestEntities;
using FluentValidation.AspNetCore;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Persistence;
using Microsoft.Identity.Web;
namespace API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DataContext>(opt =>
{
opt.UseSqlite(Configuration.GetConnectionString("DefaultConnection"));
});
services.AddCors(opt =>
{
opt.AddPolicy("CorsPolicy", policy =>
{
policy.AllowAnyHeader().AllowAnyMethod().WithOrigins("http://localhost:3000");
});
});
services.AddMicrosoftIdentityWebApiAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
services.AddMediatR(typeof(List.Handler).Assembly);
services.AddControllers(opt =>
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
opt.Filters.Add(new AuthorizeFilter(policy));
})
.AddFluentValidation(cfg => cfg.RegisterValidatorsFromAssemblyContaining<Create>());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseMiddleware<ErrorHandlingMiddleware>();
if (env.IsDevelopment())
{
// app.UseDeveloperExceptionPage();
}
app.UseCors("CorsPolicy");
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
And my application handler for calling downstream:
using System.Threading;
using System.Threading.Tasks;
using MediatR;
using Microsoft.Graph;
using Microsoft.Identity.Web;
namespace Application.Users
{
public class Me
{
public class Query : IRequest<User> { }
public class Handler : IRequestHandler<Query, User>
{
private readonly ITokenAcquisition _tokenAcquisition;
private readonly GraphServiceClient _graphServiceClient;
public Handler(ITokenAcquisition tokenAcquisition, GraphServiceClient graphServiceClient)
{
_tokenAcquisition = tokenAcquisition;
_graphServiceClient = graphServiceClient;
}
public async Task<User> Handle(Query request, CancellationToken cancellationToken)
{
var user = await _graphServiceClient.Me.Request().GetAsync();
return user;
}
}
}
}
Hopefully I'm on the right track here, but please let me know if I'm not.
Right so this was a simple oversight on my part.
As per #franklores, you need to register Microsoft Graph in your startup class services:
services.AddMicrosoftIdentityWebApiAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
Adding the following to appsettings (scopes may differ):
"DownstreamAPI": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "user.read"
},
And be sure to install Microsoft.Identity.Web.MicrosoftGraph to enable the AddMicrosoftGraph() function.

While drop database through ef core anExtention Hoisting Error error occured

I am adding data Identity Entity Framework core in my .Net Core Application. I have installed Microsoft.AspNetCore.Identity.EntityFrameworkCore in my Application and while trying to drop the database I am getting an error
An error occurred while accessing the Microsoft.Extensions.Hosting services. Continuing without the application service provider. Error: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.ISecurityStampValidator Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.SecurityStampValidator1[Domain.AppUser]': Unable to resolve service for type 'Microsoft.AspNetCore.Authentication.ISystemClock' while attempting to activate 'Microsoft.AspNetCore.Identity.SecurityStampValidator1[Domain.AppUser]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.AspNetCore.Identity.ITwoFactorSecurityStampValidator Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.TwoFactorSecurityStampValidator1[Domain.AppUser]': Unable to resolve service for type 'Microsoft.AspNetCore.Authentication.ISystemClock' while attempting to activate 'Microsoft.AspNetCore.Identity.TwoFactorSecurityStampValidator1[Domain.AppUser]'.)
Unable to create an object of type 'DataContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
My DataContext Class is
using System;
using Domain;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace Persistence
{
public class DataContext : IdentityDbContext<AppUser>
{
public DataContext(DbContextOptions options) : base(options)
{
}
public DbSet<Value> Values { get; set; }
public DbSet<Activity> Acitivities {get;set;}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
}
and my Startup.cs Class is
using API.Middleware;
using Application.Activities;
using Domain;
using FluentValidation.AspNetCore;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Persistence;
namespace API
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DataContext>(opt => {
opt.UseSqlite(Configuration.GetConnectionString("DefaultConnection"));
});
services.AddControllers();
services.AddMvc(option => option.EnableEndpointRouting = false)
.AddFluentValidation(cfg => cfg.RegisterValidatorsFromAssemblyContaining<Create>());
var builder = services.AddIdentityCore<AppUser>();
var identityBuilder = new IdentityBuilder(builder.UserType, builder.Services);
identityBuilder.AddEntityFrameworkStores<DataContext>();
identityBuilder.AddSignInManager<SignInManager<AppUser>>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseMiddleware<ErrorHandlingMiddleware>();
if (env.IsDevelopment())
{
// app.UseDeveloperExceptionPage();
}
// app.UseHttpsRedirection();
app.UseCors("CorsPolicy");
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
and my AppUser.cs Class is
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
using System.Text;
namespace Domain
{
public class AppUser : IdentityUser
{
public string DisplayName { get; set; }
}
}
What am I doing wrong here?
I Just Added services.TryAddSingleton<ISystemClock, SystemClock>(); before var builder = services.AddIdentityCore<AppUser>(); it wokred fine

Getting 'ambiguous call' error/warning in ConfigureServices MVC

I am learning ASP.NET and while somewhere I needed this part a few months back ( paused after that) it shows error/warning now. It is a .NET Core app very very basic. I know nothing about the error
See the source code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace WebApplication1
{
public class MyOptions
{
public string color { get; set; }
public string welcomestring { get; set; }
}
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
if (env.IsDevelopment())
{
builder.AddUserSecrets();
}
if (env.IsDevelopment())
{
// This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
builder.AddApplicationInsightsSettings(developerMode: true);
}
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<MyOptions>(Configuration);
var foo = Configuration["welcomestring"];
Console.WriteLine(foo);
// Add framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseApplicationInsightsRequestTelemetry();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseApplicationInsightsExceptionTelemetry();
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
Screenshot of error:
give complete name of object with namespace
example
Microsoft.Extensions.DependencyInjection.OptionConfigurationServiceCollectionExtension
or put your cursor at Configure<MyOptions>
and ALT + SHIFT + F10
and select your model.

Configuring Ninject with Asp.Net MVC & Web Api

i have setup my project with Ninject IoC.
My project has regular Asp.Net MVC controllers and Web Api controllers. Now, Ninject works with Web Api but Ninject doesn't work with regular Asp.MVC controllers.
My regular MVC controller implementation;
public class GalleryController : BaseController
{
public GalleryController(IUow uow)
{
Uow = uow;
}
........
}
Error when using with regular controller
An error occurred when trying to create a controller of type 'Web.Controllers.HomeController'. Make sure that the controller has a parameterless public constructor.]
However, when i try the same code with Web Api, it works
public class GalleryController : BaseApiController
{
public GalleryController(IUow uow)
{
Uow = uow;
}
......
}
my interface which holds difference repositories (the factory pattern)
public interface IUow
{
// Save pending changes to the data store.
void Commit();
//Repositoryries
IRepository<Gallery> Gallery { get; }
IMenuRepository Menus { get; }
}
NinjectDependencyScope class;
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
this.resolver = resolver;
}
public void Dispose()
{
var disposable = resolver as IDisposable;
if (disposable != null)
disposable.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);
}
}
NinjectDependencyResolver class;
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
Ninject configuration for Global.asax;
public class IocConfig
{
public static void RegisterIoc(HttpConfiguration config)
{
var kernel = new StandardKernel(); // Ninject IoC
//kernel.Load(Assembly.GetExecutingAssembly()); //only required for asp.net mvc (not for webapi)
// These registrations are "per instance request".
// See http://blog.bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/
kernel.Bind<RepositoryFactories>().To<RepositoryFactories>()
.InSingletonScope();
kernel.Bind<IRepositoryProvider>().To<RepositoryProvider>();
kernel.Bind<IUow>().To<Uow>();
// Tell WebApi how to use our Ninject IoC
config.DependencyResolver = new NinjectDependencyResolver(kernel);
}
}
Global.asax
protected void Application_Start()
{
// Tell WebApi to use our custom Ioc (Ninject)
IocConfig.RegisterIoc(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfig.CustomizeConfig(GlobalConfiguration.Configuration);
AreaRegistration.RegisterAllAreas();
}
I have written some gists to help configure Ninject with MVC and Web Api. Simply include the file(s):
https://gist.github.com/odytrice/5821087 (for MVC)
https://gist.github.com/odytrice/5842010 (for WebApi)
To add Bindings for concrete Types, Just put them in the Load() method of the MainModule. You can create as many modules as you like to keep bindings organized. but you'll also have to add them to the array that is returned in the Modules property.
Then Add to the Application_Start() method
NinjectContainer.RegisterModules(NinjectModules.Modules) (for MVC)
NinjectHttpContainer.RegisterModules(NinjectHttpModules.Modules) (for WebApi)
Note that you can use the same NinjectModules.Modules for both the MVC and WebApi registration. I just separated it for clearity
UPDATE: Remember to Remove NinjectWebCommon.cs from your project as it loads and bootstraps a new kernel at Runtime which unfortunately is only for MVC.
UPDATE: You can also use
NinjectContainer.RegisterAssembly() (for MVC)
NinjectHttpContainer.RegisterAssembly() (for WebApi)
This will scan your current assembly for all modules. This way you can put your modules anywhere in your project and it will be registered
With MVC 5 and Web API 2.2 I solved this problem by making sure I included the following NuGet packages:
Ninject.MVC5
Ninject.Web.WebApi.WebHost for Web API
This installed other Ninject dependencies and allowed me to RegisterServices through NinjectWebCommon.cs.
After searching a lot, it turns out there we can't use Ninject with web api and regular mvc. I mean, we have to configure the Repositories separately.
I then found a nice article which explains how you can use Ninject with asp.net mvc & web api: http://www.codeproject.com/Articles/412383/Dependency-Injection-in-asp-net-mvc4-and-webapi-us
And now, I don't get the error and it's working :D
Update 1:
Also try Writing a simple implementation of dependency injection in MVC 4 Web API with .NET Framework 4.5
Here is the simple solution that works fine for me:
In Visual studio, create new web application project named DemoApp and make sure you have selected Empty template with MVC and Web API references:
In Package manager console execute one by one:
Install-Package Ninject
Install-Package Ninject.MVC5
Add NinjectDependencyResolver.cs to IoC folder :
using Ninject;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Dependencies;
namespace DemoApp.IoC
{
public class NinjectDependencyResolver : IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return this;
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
public void Dispose() { } //it is not necessary to implement any dispose logic here
}
}
Make the following changes in App_Start/NinjectWebCommon.cs :
Add these lines in CreateKernel method:
NinjectDependencyResolver ninjectResolver = new NinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(ninjectResolver); //MVC
GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; //Web API
Add your bindings in RegisterServices method like:
kernel.Bind< IHelloService>().To< HelloService>();
Now NinjectWebCommon.cs should look like:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(DemoApp.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(DemoApp.App_Start.NinjectWebCommon), "Stop")]
namespace DemoApp.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using DemoApp.IoC;
using System.Web.Mvc;
using System.Web.Http;
using DemoApp.Config;
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>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
NinjectDependencyResolver ninjectResolver = new NinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(ninjectResolver); //MVC
GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; //Web API
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)
{
kernel.Bind<IHelloService>().To<HelloService>();
}
}
}
Just for the completeness of the example, add some Mvc and Api controllers, and code for IHelloService, HelloService :
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DemoApp.Config;
namespace DemoApp.Controllers
{
public class HomeController : Controller
{
private IHelloService helloService;
public HomeController(IHelloService helloService)
{
this.helloService = helloService;
}
// GET: /Home/
public string Index()
{
return "home/index: " + helloService.GetMessage();
}
}
}
UserController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using DemoApp.Config;
namespace DemoApp.Controllers
{
public class UserController : ApiController
{
private IHelloService helloService;
public UserController(IHelloService helloService)
{
this.helloService = helloService;
}
[HttpGet]
public string Data()
{
return "api/user/data: " + helloService.GetMessage();
}
}
}
IHelloService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace DemoApp.Config
{
public interface IHelloService
{
string GetMessage();
}
}
HelloService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace DemoApp.Config
{
public class HelloService : IHelloService
{
public string GetMessage()
{
return "Hi";
}
}
}
The final structure should look like:
Now make some tests in browser. For me it was:
http://localhost:51156/home/index
http://localhost:51156/api/user/data
And that's it.
I think the issue is that you are not registering a ControllerFactory that uses Ninject to build the controllers (and resolve their dependencies), have you tried implementing your own ControllerFactory yet? See also here http://bubblogging.wordpress.com/2012/06/04/mvc-controller-factory-ninject/.
There is a more elegant solution for this by Nenad - it took me 3 extra hours because I first tried to implement the solutions here conflicting with existing infrastructure I had. It is in reply to another stack overflow question. I am duplicating that answer here just in case it helps others to save the time I lost.
There is a way to share same container between MVC and ASP.NET Web API.
You just need to implement both interfaces.
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(this.kernel.BeginBlock());
}
}
Check this article for solution:
Simple Way to share Dependency Resolvers between MVC and Web API

Resources