I've been following Steven Sanderson's book called Pro ASP.NET MVC Framework, and I'm running into an exception:
Could not load type 'DomainModel.Abstract.IProductsRepository' from assembly 'DomainModel'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.TypeLoadException: Could not load type 'DomainModel.Abstract.IProductsRepository' from assembly 'DomainModel'
.
Line 19: public WindsorControllerFactory()
Line 20: {
Line 21: container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
Line 22:
Line 23: var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes() where typeof(IController).IsAssignableFrom(t) select t;
Here's my WindsorControllerFactory code:
public class WindsorControllerFactory : DefaultControllerFactory
{
WindsorContainer container;
public WindsorControllerFactory()
{
container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes() where typeof(IController).IsAssignableFrom(t) select t;
foreach (Type t in controllerTypes)
container.AddComponentLifeStyle(t.FullName, t, LifestyleType.Transient);
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return (IController)container.Resolve(controllerType);
}
}
My Global.asax.cs code:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory());
}
And the web.config values:
<configSections>
< section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
</configSections>
<castle>
<components>
<component id="ProdsRepository" service="DomainModel.Abstract.IProductsRepository, DomainModel"
type="DomainModel.Concrete.SqlProductsRepository, DomainModel">
<parameters>
< connectionString>data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|SportsStore.mdf;User Instance=true< /connectionString>
</parameters>
</component>
</components>
</castle>
My question is why could not load type 'DomainModel.Abstract.IProductsRepository' from assembly 'DomainModel'. ?
A possible explanation for this error is that the IProductsRepository interface is not public and/or is not placed inside the DomainModel.Abstract namespace in the DomainModel assembly. Make sure that the definition looks like this and that it is part of the DomainModel project:
namespace DomainModel.Abstract
{
public interface IProductsRepository
{
...
}
}
The same stands true for the DomainModel.Concrete.SqlProductsRepository, DomainModel class that you've defined.
Related
What would be the recommended way to use Ninject to inject the same HttpClient object to all Controller instances in an application?
Currently, I am injecting an EntityFramework Database context following Adam Freeman's MVC book as follows. However, this creates a new dbContext for each controller instance, which is probably not ideal for HttpClient, since HttpClient is meant to be reused across all controllers in an MVC application.
Constructor:
public class AccountController : Controller
{
MyDBContext dbContext = new MyDBContext();
public AccountController(MyDBContext context)
{
dbContext = context;
}
...
}
And the Ninject Factory is as follows:
/// Class based on Adam Freeman's MVC book to use dependency injection to create controllers
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel ninjectKernel;
public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
AddBindings();
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null
? null
: (IController)ninjectKernel.Get(controllerType);
}
private void AddBindings()
{
ninjectKernel.Bind<MyDBContext>().ToSelf().InTransientScope();
}
}
You just have to change your configuration to:
ninjectKernel.Bind<MyDBContext>().ToSelf().InRequestScope();
For more information about request scoping, please read this.
Thanks Steven. Currently, I find that the following works. I created a static HttpClient property in the NinjectController and bound it as constant in singleton scope. Daniel's book was helpful in better understanding Ninject.
/// Class based on Adam Freeman's MVC book to use dependency injection to create controllers
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel ninjectKernel;
private static HttpClient WebAPIClient; // added
public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
WebAPIClient = new HttpClient(); // added
WebAPIClient.BaseAddress = new Uri("http://localhost:1153"); // added
AddBindings();
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null
? null
: (IController)ninjectKernel.Get(controllerType);
}
private void AddBindings()
{
ninjectKernel.Bind<MyDBContext>().ToSelf().InTransientScope();
ninjectKernel.Bind<HttpClient>().ToConstant(WebAPIClient).InSingletonScope(); // added
}
}
Heres my error:
Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'ConnectCx.Web.PluginUI.MVC5.Services.DefaultService' can be invoked with the available services and parameters:
Cannot resolve parameter 'ConnectCx.Web.PluginUI.MVC5.Repository.IRepository1[ConnectCx.Web.PluginUI.MVC5.Models.ViewModels.DependancyTestViewModel] dependancyRepository' of constructor 'Void .ctor(ConnectCx.Web.PluginUI.MVC5.Repository.IRepository1[ConnectCx.Web.PluginUI.MVC5.Models.ViewModels.DependancyTestViewModel])'.
Here's my Global
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
var builder = new ContainerBuilder();
// Register our MVC controllers.
builder.RegisterControllers(typeof(MvcApplication).Assembly);
//Register our Services
//builder.RegisterType(typeof(DefaultService)).AsImplementedInterfaces();
//builder.RegisterType<IRepository>();
//builder.RegisterType(typeof(IRepository)).AsImplementedInterfaces();
builder.RegisterType<DefaultService>().As<IDefaultService>().SingleInstance().PreserveExistingDefaults();
// OPTIONAL: Register model binders that require DI.
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
builder.RegisterModelBinderProvider();
// OPTIONAL: Register web abstractions like HttpContextBase.
builder.RegisterModule<AutofacWebTypesModule>();
// OPTIONAL: Enable property injection in view pages.
builder.RegisterSource(new ViewRegistrationSource());
// OPTIONAL: Enable property injection into action filters.
builder.RegisterFilterProvider();
// Set the dependency resolver to be Autofac.
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
heres my Irepository
namespace ConnectCx.Web.PluginUI.MVC5.Repository
{
public interface IRepository<T> where T : class
{
T Get(object id);
void Attach(T entity);
IQueryable<T> GetAll();
void Insert(T entity);
void Delete(T entity);
void Update(T entity);
void SubmitChanges(); //need?
T Find(Expression<Func<T, bool>> predicate);
IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate);
T GetById(int id);
}
}
heres my Default Service
public class DefaultService : IDefaultService
{
private readonly IRepository<DependancyTestViewModel> _dependancyRepository;
public DefaultService(IRepository<DependancyTestViewModel> dependancyRepository)
{
this._dependancyRepository = dependancyRepository;
}
public virtual string DependancyStringTest()
{
var test = _dependancyRepository.GetAll();//expect to blowup for test
return "hello world, wasup?";
}
}
heres my default service interface
namespace ConnectCx.Web.PluginUI.MVC5.Services.ServiceInterface
{
public interface IDefaultService
{
string DependancyStringTest();
}
}
is this an issue with my implimentation of Irepository? if not what is the issue here?
This error message tells you that Autofac is not able to build a DefaultService instance because the only available constructor require a IRepository<DependancyTestViewModel> and none is registered.
In order to fix this error you have to register a IRepository<DependancyTestViewModel>.
For example :
builder.RegisterType<DependancyTestViewModelRepository>()
.As<IRepository<DependancyTestViewModel>>();
or if you have a generic repository
builder.RegisterGeneric(typeof(GenericRepository<>))
.As(typeof(IRepository<>));
I want to use Ninject in my project,this is my code :
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel ninjectKernel;
public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
AddBindings();
}
protected override IController GetControllerInstance(RequestContextrequestContext, Type controllerType)
{
return (controllerType == null) ? null :(IController)ninjectKernel.Get(controllerType);
}
private void AddBindings()
{
ninjectKernel.Bind<IHomeService>().To<HomeService>();
ninjectKernel.Bind<IHomeBussiness>().To<HomeBussiness>();
}
}
and my global.asax is :
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
and my home controller is:
private readonly IHomeService _iHomeService;
public HomeController(IHomeService iHomeService)
{
_iHomeService = iHomeService;
}
and now :
When I run My project I see that say Does not exist StandardProvider.cs
and my error is:
Error activating ObjectContext using implicit self-binding of ObjectContext
Several constructors have the same priority. Please specify the constructor using ToConstructor syntax or add an Inject attribute.
how can I Resolve this Issue?
Please I need help with this scenario:
I want to use the default ASP Membership/Authentication in my MVC app, connected to a VPN.
In web.config I setup the connection "MyCustomConnection":
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
...
<add name="MyCustomConnection" connectionString="Data Source=172.x.x.y\somewhere;Initial Catalog=The.Main.DB;User ID=sa;Password=sapass;Trusted_Connection=True;Integrated Security=SSPI" providerName="System.Data.SqlClient" />
</connectionStrings>
Then in InitializeSimpleMembershipAttribute I have:
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<UsersContext>(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection("MyCustomConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}
}
When the debugger hit(After a click in the Login Hyperlink of the Basic Template) WebSecurity.InitializeDatabaseConnection("MyCustomConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true), threw an exception:
Cannot open database "The.Main.DB" requested by the login. The login failed.
Login failed for user 'VPN\MYUSER'.
Additionally in User Context:
public class UsersContext : DbContext
{
public UsersContext()
: base("MyCustomConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
}
My question is:
Why WebSecurity.InitializeDatabaseConnection("MyCustomConnection",... is trying to connect with the user of vpn and no with 'sa'(and his password 'sapass') as my connection string.
Thanks.
The issue is with the connection string, specifically the use of Trusted_Connection=True;Integrated Security=SSPI for more information, check here: Difference between Integrated Security = True and Integrated Security = SSPI
I'm trying to learn a bit about MVC and have come across a problem when using Ninject. I want to bind repositories but keep getting the 'Object reference not set to an instance of an object' error.
I have created my NinjectControllerFactory:
public class NinjectControllerFactory : DefaultControllerFactory
{
// A Ninject "kernel" is the thing that can supply object instances
private IKernel kernel = new StandardKernel(new SportsShopServices());
// ASP .NET MVC calls this to get the controller for each request
protected override IController GetControllerInstance(RequestContext context, Type controllerType)
{
if (controllerType == null)
return null;
return (IController) kernel.Get(controllerType);
}
// Configure how abstract sevice types are mapped to concrete implementations
private class SportsShopServices : NinjectModule
{
public override void Load()
{
Bind<IProductRepository>().To<SqlProductsRepository>()
.WithConstructorArgument("connectionString",
ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString);
}
}
}
and my controller :
public class ProductsController : Controller
{
private IProductRepository productsRepository;
// Constructor used with Ninject
public ProductsController(IProductRepository _productsRepository)
{
this.productsRepository = _productsRepository;
}
public ViewResult List()
{
return View(productsRepository.Products.ToList());
}
}
I have modified the Web.config file to provide the db connection string and the Global.asax file Application_Start() method to include:
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
I am working on an example from the PRO ASP .NET MVC 2 book but just can't get this work, been trying all day.
If you just want out-out-the-box ninject functionality, you are doing too much by creating your own controller factory.
all you need is the following in global.asax
public class MvcApplication : NinjectHttpApplication
{
protected override IKernel CreateKernel()
{
var modules = new INinjectModule[]
{
new ServiceModule()
};
return new StandardKernel(modules);
}
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
RegisterAllControllersIn(Assembly.GetExecutingAssembly());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
internal class ServiceModule : NinjectModule
{
public override void Load()
{
// controllers
this.Bind<Controllers.AccountController>().ToSelf();
this.Bind<Controllers.HomeController>().ToSelf();
// Repository
Bind<Controllers.IFormsAuthentication>().To<Controllers.FormsAuthenticationService>();
Bind<Controllers.IMembershipService>().To<Controllers.AccountMembershipService>();
}
}
}