Parameterless constructor error with autofac in web api 2 - asp.net-mvc

I am using Autofac as IOC and here is my structure:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AdTudent.Repo
{
public interface IRepository
{
IAdvertisementRepository Advertisements { get; set; }
IProfileRepository Profiles { get; set; }
}
}
My repositories class is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AdTudent.Repo
{
public class Repositories : IRepository
{
public Repositories(IAdvertisementRepository advertisementRepository,
IProfileRepository profileRepository)
{
Advertisements = advertisementRepository;
Profiles = profileRepository;
}
public IAdvertisementRepository Advertisements { get; set; }
public IProfileRepository Profiles { get; set; }
}
}
And my startup class is:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
builder.RegisterType<Repositories>().As<IRepository>();
builder.Register<IGraphClient>(context =>
{
var graphClient = new GraphClient(new Uri("http://localhost:7474/db/data"));
graphClient.Connect();
return graphClient;
}).SingleInstance();
// STANDARD WEB API SETUP:
// Get your HttpConfiguration. In OWIN, you'll create one
// rather than using GlobalConfiguration.
var config = new HttpConfiguration();
// Register your Web API controllers.
//builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Run other optional steps, like registering filters,
// per-controller-type services, etc., then set the dependency resolver
// to be Autofac.
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
// OWIN WEB API SETUP:
// Register the Autofac middleware FIRST, then the Autofac Web API middleware,
// and finally the standard Web API middleware.
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseWebApi(config);
ConfigureAuth(app);
}
}
and here is my account controller:
public class AccountController : ApiController
{
private IRepository _repository;
private const string LocalLoginProvider = "Local";
private ApplicationUserManager _userManager;
private IGraphClient _graphClient;
public ISecureDataFormat<AuthenticationTicket> AccessTokenFormat { get; private set; }
public AccountController(IRepository repository, IGraphClient graphClient,
ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
{
AccessTokenFormat = accessTokenFormat;
_repository = repository;
_graphClient = graphClient;
}
}
but I always this problem
"Message": "An error has occurred.",
"ExceptionMessage": "An error occurred when trying to create a controller of type 'AccountController'. Make sure that the controller has a parameterless public constructor.",
"ExceptionType": "System.InvalidOperationException",
"StackTrace": " at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)\r\n at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
I searched on the internet but I couldn't find anything that can help can anyone guide me?

Per the WebApi OWIN documentation:
A common error in OWIN integration is use of the GlobalConfiguration.Configuration. In OWIN you create the configuration from scratch. You should not reference GlobalConfiguration.Configuration anywhere when using the OWIN integration.
It looks like you have a couple of issues:
The HttpConfiguration needs to be newed up when using OWIN.
You are missing the UseAutofacWebApi virtual method call.
You also need the Autofac WebApi OWIN package as per the docs.
public class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
// STANDARD WEB API SETUP:
// Get your HttpConfiguration. In OWIN, you'll create one
// rather than using GlobalConfiguration.
var config = new HttpConfiguration();
// Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Run other optional steps, like registering filters,
// per-controller-type services, etc., then set the dependency resolver
// to be Autofac.
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
// OWIN WEB API SETUP:
// Register the Autofac middleware FIRST, then the Autofac Web API middleware,
// and finally the standard Web API middleware.
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}

Check your Global.asax.cs. You should remove this line if you have it:
GlobalConfiguration.Configure(WebApiConfig.Register);
You can move this to Startup.cs Configuration like this:
WebApiConfig.Register(config);

You haven't told Autofac how to create an ISecureDataFormat<AuthenticationTicket> instance.
Add this in your startup class before your call builder.Build().
builder.RegisterType<ISecureDataFormat<AuthenticationTicket>>().As<TicketDataFormat>();

Related

Unable to resolve service for type [MoneyTracker.Models.solutionDb]' while attempting to activate 'MoneyTracker.Data.ApplicationDbContext'.)

I am getting the error when trying to run my application. Using .NET Core on Rider for Mac.
Program.cs
using System.Configuration;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using MoneyTracker.Data;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true);
builder.Services.AddControllersWithViews();
//Allows us to connect to our database using the connection string in Program.cs
//Uses the ApplicationDbContext file under Data to invoke the table creation
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("SolutionConnection")
));
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
My ApplicationDbContext.cs
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.CodeAnalysis;
using Microsoft.EntityFrameworkCore;
using MoneyTracker.Models;
namespace MoneyTracker.Data;
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, DbSet<solutionDb> solutionDb)
: base(options)
{
}
public DbSet<solutionDb> SolutionDb { get; set; } //creates a solution table with the name solutionDb
}
my solutionDb.cs Model file
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
namespace MoneyTracker.Models;
public class solutionDb
{
[Key]
public int Id { get; set; }
[Required]
public string SolutionName {get; set;} = null!;
public int Cost {get; set;}
}
I tried going back through and retracing steps, but I can't figure out what I am doing wrong here. I attempted restructure the Program.cs file and refresh the DB connection running through Azure SQL Edge. I am newer to C# and the MVC style, so apologies if this is a simple fix.
Don't write DbSet<solutionDb> solutionDb in constructor of ApplicationDbContext. Asp.Net Core using Constructor injection, When you write DbSet<solutionDb> solutionDb in ApplicationDbContext's constructor, The project will think that you inject DbSet<solutionDb> solutionDb into ApplicationDbContext, But you don't register it in DI container, So project will report this error, Change your code like:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<solutionDb> SolutionDb { get; set; } //creates a solution table with the name solutionDb
}
You can refer to this Docs to learn more details.

Invoking WCF service via ChannelFactory in MVC controller using Unity.Mvc5

I've following projects:
Poco (listing all the potential objects/dtos)
BusinessServices (contains all the logic and communicates with database)
WcfServices (calls into Business Services and return Pocos)
MVC5 (calls into WcfServices)
Now, I'm trying to invoke the WcfServices without using the Proxy, but using the ChannelFactory and initializing it via Unity, I'm getting the error: "No parameterless constructor defined for this object". Please help.
UnityConfig.cs
public static void RegisterComponents()
{
var container = new UnityContainer();
// Register WCF
container.RegisterType<IPersonService>(
new ContainerControlledLifetimeManager(),
new InjectionFactory((c) => new ChannelFactory<IPersonService>("WSHttpBinding_IPersonService").CreateChannel()));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
PersonController.cs
public class PersonController : Controller
{
private readonly IPersonService _personService;
public PersonController(IPersonService personService)
{
_personService = personService;
}
...
...
...
}

No ApplicationRoleManager class in my MVC 5 template

When I try to add app.CreatePerOwinContext(ApplicationRoleManager.Create) to configauth I am told applicationRoleManager does not exist. Does anybody know why?
using Microsoft.Owin.Security.OAuth;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.DataProtection;
using Microsoft.Owin.Security.Google;
using Owin;
using System;
using LaCeibaNetv4.Models;
namespace LaCeibaNetv4
{
public partial class Startup
{
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
I was having the same issue and came across this code which I used to add the class to my project:
public class ApplicationRoleManager : RoleManager<IdentityRole>
{
public ApplicationRoleManager(IRoleStore<IdentityRole,string> roleStore)
: base(roleStore) { }
public static ApplicationRoleManager Create(
IdentityFactoryOptions<ApplicationRoleManager> options,
IOwinContext context)
{
var manager = new ApplicationRoleManager(
new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()));
return manager;
}
}
Also, remember to have it configured at startup by adding this piece of code in Startup.Auth.cs:
app.CreatePerOwinContext<ApplicationRoleManager>(Application‌​RoleManager.Create);
The full article is available here: http://www.codeproject.com/Articles/762428/ASP-NET-MVC-and-Identity-Understanding-the-Basics

Import aspect is not working using MEF

using mefcontrib.mvc3 on my mvc web application. used following class for initialize mef before application start event. That class is auto generated(downloaded) from nuget. some tiny changes applied for catalog(for plugins folder) and controller factory segments.
[assembly: WebActivator.PreApplicationStartMethod(typeof(OMR.CMS.App_Start.MefContribMVC3), "Start")]
namespace OMR.CMS.App_Start
{
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Web.Mvc;
using MefContrib.Hosting.Conventions;
using MefContrib.Web.Mvc;
public static class MefContribMVC3
{
public static void Start()
{
// Register the CompositionContainerLifetimeHttpModule HttpModule.
// This makes sure everything is cleaned up correctly after each request.
CompositionContainerLifetimeHttpModule.Register();
// Create MEF catalog based on the contents of ~/bin.
//
// Note that any class in the referenced assemblies implementing in "IController"
// is automatically exported to MEF. There is no need for explicit [Export] attributes
// on ASP.NET MVC controllers. When implementing multiple constructors ensure that
// there is one constructor marked with the [ImportingConstructor] attribute.
var catalog = new AggregateCatalog(
//new DirectoryCatalog("bin"),
new DirectoryCatalog("Plugins"),
new ConventionCatalog(new MvcApplicationRegistry())); // Note: add your own (convention)catalogs here if needed.
// Tell MVC3 to use MEF as its dependency resolver.
var dependencyResolver = new CompositionDependencyResolver(catalog);
DependencyResolver.SetResolver(dependencyResolver);
// Tell MVC3 to resolve dependencies in controllers
ControllerBuilder.Current.SetControllerFactory(new MyMEFControllerFactory(dependencyResolver));
// Tell MVC3 to resolve dependencies in filters
FilterProviders.Providers.Remove(FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider));
FilterProviders.Providers.Add(new CompositionFilterAttributeFilterProvider(dependencyResolver));
// Tell MVC3 to resolve dependencies in model validators
ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());
ModelValidatorProviders.Providers.Add(
new CompositionDataAnnotationsModelValidatorProvider(dependencyResolver));
// Tell MVC3 to resolve model binders through MEF. Note that a model binder should be decorated
// with [ModelBinderExport].
ModelBinderProviders.BinderProviders.Add(
new CompositionModelBinderProvider(dependencyResolver));
}
}
}
and using followin code on my application class:
using OMR.Core.Web.Filters;
using OMR.Core.Web.Routing;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace OMR.CMS
{
public class MvcApplication : System.Web.HttpApplication
{
[ImportMany(typeof(IFilterRegistration))]
public IEnumerable<Lazy<IFilterRegistration>> Filters { get; set; }
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
BundleConfig.RegisterBundles(BundleTable.Bundles);
RegisterFilters();
RegisterRoutes();
}
private void RegisterFilters()
{
var filters = GlobalFilters.Filters;
var filterRegistrations = DependencyResolver.Current.GetServices<IFilterRegistration>();
foreach (var registar in filterRegistrations)
registar.Register(filters);
}
public void RegisterRoutes()
{
var routes = RouteTable.Routes;
var routeRegistrations = DependencyResolver.Current.GetServices<IRouteRegistration>();
// Ignores
foreach (var registrar in routeRegistrations)
registrar.Ignore(routes);
// Routes
foreach (var registrar in routeRegistrations)
registrar.Route(routes);
}
}
}
The problem is following property is currently null on application start method.
ImportMany(typeof(IFilterRegistration))]
public IEnumerable<Lazy<IFilterRegistration>> Filters { get; set; }
But following lines is working:
var filterRegistrations = DependencyResolver.Current.GetServices<IFilterRegistration>();
Why my import declaration isn't work?

ASP.NET MVC WebApi: No parameterless constructor defined for this object

I have an ASP.NET MVC 4 Application that I want to implement Unit of Work Pattern.
In my Web Project I have:
IocConfig.cs
using System.Web.Http;
using NinjectMVC.Data;
using NinjectMVC.Data.Contracts;
using Ninject;
namespace NinjectMVC
{
public class IocConfig
{
public static void RegisterIoc(HttpConfiguration config)
{
var kernel = new StandardKernel(); // Ninject IoC
// 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<INinjectMVCUow>().To<NinjectMVCUow>();
// Tell WebApi how to use our Ninject IoC
config.DependencyResolver = new NinjectDependencyResolver(kernel);
}
}
}
Global.asax
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace NinjectMVC
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
// Tell WebApi to use our custom Ioc (Ninject)
IocConfig.RegisterIoc(GlobalConfiguration.Configuration);
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
}
}
}
PersonsController.cs
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using NinjectMVC.Data.Contracts;
using NinjectMVC.Model;
namespace NinjectMVC.Controllers
{
public class PersonsController : ApiControllerBase
{
public PersonsController(INinjectMVCUow uow)
{
Uow = uow;
}
#region OData Future: IQueryable<T>
//[Queryable]
// public IQueryable<Person> Get()
#endregion
// GET /api/persons
public IEnumerable<Person> Get()
{
return Uow.Persons.GetAll()
.OrderBy(p => p.FirstName);
}
// GET /api/persons/5
public Person Get(int id)
{
var person = Uow.Persons.GetById(id);
if (person != null) return person;
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
// OData: GET /api/persons/?firstname=\'Hans\''
// With OData query syntax we would not need such methods
// /api/persons/getbyfirstname?value=Joe1
[ActionName("getbyfirstname")]
public Person GetByFirstName(string value)
{
var person = Uow.Persons.GetAll()
.FirstOrDefault(p => p.FirstName.StartsWith(value));
if (person != null) return person;
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
// Update an existing person
// PUT /api/persons/
public HttpResponseMessage Put(Person person)
{
Uow.Persons.Update(person);
Uow.Commit();
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
}
}
When I try to surf: http://www.domain.com/Persons/Get Im getting:
No parameterless constructor defined for this object.
Is there any stuff I have missed? I would appreciate any help.
Here is the zip file of the project for better references:
http://filebin.ca/E6aoOkaUpbQ/NinjectMVC.zip
Wep.API uses a different IDependencyResolver than the MVC framework.
When you use theHttpConfiguration.DependencyResolver it only works for ApiControllers. But your ApiControllerBase derives from Controller...
So your ApiControllerBase should inherit from ApiController.
Change it in your ApiBaseController.cs:
public abstract class ApiControllerBase : ApiController
{
}
If you want to inject dependencies to regular Controller derived classes you need to use ( in your IocConfig):
System.Web.Mvc.DependencyResolver.SetResolver(new NinjectMvcDependencyResolver(container));
Note that in this case you cannot use your NinjectDependencyResolver because it's for ApiControllers.
So you need a different NinjectMvcDependencyResolver which should implement System.Web.Mvc.IDependencyResolver.
public class NinjectMvcDependencyResolver: NinjectDependencyScope,
System.Web.Mvc.IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
}
I know this is an old thread, but this might be useful for someone. :)
In my case, it was missing the DependencyResolver on NinjectWebCommon.cs.
I followed this article and everything worked fine.
RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;

Resources