I have a small problem which, hopefully, you will help me put behind.
I am using a MvcSiteMapProvider, and I want to define visibility for each node using access to a DB via a service interface.
public class AreaSiteMapNodeVisibilityProvider : MvcSiteMapProvider.Extensibility.ISiteMapNodeVisibilityProvider
{
[Inject]
public ISecurityService _SecurityService {get;set;}
public AreaSiteMapNodeVisibilityProvider()
{
}
public bool IsVisible(SiteMapNode node, HttpContext context, IDictionary<string, object> sourceMetadata)
{
MvcSiteMapNode thisNode = node as MvcSiteMapNode;
return _SecurityService.CalculateNodeVisibility(thisNode,context.Cache["someValueIHaveStoredHere"])
}
}
However, my _SecurityService member is always null. Any suggestions? I accept any type of directions, including getting rid of my injection and going another way.
Your ISecurityService is null, because in this case, Ninject is not managing the creation of MvcSiteMapProvider (in MVC app, Ninject resolves dependencies wired from controller root, because it manages the creation of controllers - it overrides the default method for creation controllers).
Options to resolve your issue:
1)
Use Ninject as service locator. Not recommended!, as it is widely considered to be an anti-pattern (but it depends...).
var app = HttpContext.ApplicationInstance as NinjectHttpApplication;
var service = app.Kernel.Get<ISecurityService>();
2) Read R. Gloor's answer on similar question: MVC3, Ninject, MvcSiteMapProvider - How to inject dependency to overridden method and do it his way.
Make sure that
The siteMapNodeVisibilityProvider is NOT configured in the web.config
There is a binding for ISiteMapNodeVisibilityProvider
Related
I am developing a ASP.Net5 MVC6 website Using EF7.
I wanted to access DbContext from one of my classes which is not being called from Controller.
Is it possible to access from there? If yes then please guide me a little so that I can learn how to do it.
So far searched a lot from GitHub and stackoverflow. Very little information on this topic.
If i need to inject to my class then how should I do it?
public class CarAppContext : DbContext
{
public DbSet<Car> Cars { get; set; }
public DbSet<BodyType> BodyTypes { get; set; }
}
public Class NotificationManager
{
CarAppContext ctx;
public NotificationManager(CarAppContext AppCtx)
{
ctx = AppCtx;
}
public void SendNotification(Car HisCar, UserNotification HisNotification)
{
//need to check he has subscribed or not
//ctx is null here
}
}
You could call new CarAppContext().
But if you want to use Dependency Injection instead, you will need to make sure that
You have registered both CarAppContext and NotificationManager with the dependency injection container (generally done in Startup.Configure)
Instantiate NotificationManager from dependency injection
Not surprised you haven't found docs. As ASP.NET 5 is still in beta, our docs haven't been written yet. When its ready, there will be more posted here: http://docs.asp.net/en/latest/fundamentals/dependency-injection.html
Dependency injection is "viral" concept and you have to use it overall in application - pass dependencies via parameters/properties and have single (or few of) registration root. So the answer is - register NotificationManager as dependency.
Even Microsoft's implementation of dependency injection is abstracted enough, so you could easy have kind of classes for each component registers dependencies (like Ninject modules).
Note: Make sure to add this to your file...
using Microsoft.Data.Entity;
Where is the recommended place to perform property injection into action filter attributes in an ASP.NET web api project? In MVC 3 land, we could set our own implementation for ControllerActionInvoker at the point of resolving our controllers from our IoC container, and override its GetFilters() method to inject components resolved from the container.
Is there a similar place to do this in an ASP.NET Web API project? I have a controller factory that resolves controllers from the container, with the CreateController method as so:
public IHttpController CreateController(HttpControllerContext controllerContext, string controllerName)
{
var controller = _kernel.Resolve<IHttpController>(controllerName);
controllerContext.Controller = controller;
controllerContext.ControllerDescriptor = new HttpControllerDescriptor(_configuration, controllerName, controller.GetType());
return controllerContext.Controller;
}
I've had a look at HttpControllerDescriptor to see if there is somewhere to do the injection, but I can't see a suitable place. Any pointers in the right direction?
You need to implement IHttpControllerSelector and register your selector in the (Services property) DefaultServices of the HttpConfiguration.
Or alternatively, to use your own resolver/DI framework, you need to replace the resolver. See here for an example.
You need to Implement your own IFilterProvider. Have a look at the source for ActionDescriptorFilterProvider. This is where you can inject properties.
Here is ActionDescriptorFilterProvider implementation:
public IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
if (configuration == null)
{
throw Error.ArgumentNull("configuration");
}
if (actionDescriptor == null)
{
throw Error.ArgumentNull("actionDescriptor");
}
IEnumerable<FilterInfo> controllerFilters = actionDescriptor.ControllerDescriptor.GetFilters().Select(instance => new FilterInfo(instance, FilterScope.Controller));
IEnumerable<FilterInfo> actionFilters = actionDescriptor.GetFilters().Select(instance => new FilterInfo(instance, FilterScope.Action));
return controllerFilters.Concat(actionFilters);
}
All you have to do is to use instance lambda parameter and inject properties.
Registration As you have figured out, the filter provider needs to be registered against the HttpConfiguration. Or alternatively, to use your own resolver/DI framework, you need to replace the resolver. See here for an example.
I found http://www.devproconnections.com/content1/catpath/database-development/topic/a-perfect-storm-linq-to-sql-dependency-injection-and-asp-net-providers/page/2 and had similar code as from the webpage:
public class CustomProvider : MembershipProvider, IMembershipProvider
{
private IUserRepository _userRepo;
// this .ctor is used via unit tests (as a seam)
public CustomProvider(IUserRepository repo)
{
this._userRepo = repo;
}
// requisite parameter-less constructor:
public CustomProvider()
{
// do NOTHING here
}
public override bool ValidateUser(string username, string password)
{
// HACK:
IUserRepository repo = this._userRepo ?? ObjectFactory.GetInstance<IUserRepository>();
SiteUser user = repo.GetUserByEmailAddress(username.ToLower());
if (user == null)
return false;
if (!user.Active || !user.Verified)
return false;
if (user.PassPhrase.IsNullOrEmpty())
return false;
// do other verification... etc
}
}
Except mine is a custom RoleProvider. Is calling the ObjectFactory.GetInstance an accepted way to inject dependencies into a RoleProvider? I tried to setup a property to inject the dependency, but I could not get that to work. I'm sure my StructureMap registry is wrong. But hard to find out the right way when the documentation is out of date.
So for an ASP.NET MVC3 app, is calling the ObjectFactory ok in a custom RoleProvider? Or should I attempt to inject to a property?
If a property, how? I have For<RoleProvider>().Use(ctx => Roles.Provider); currently. But I'm not sure id the Use should be an Add, nor am I sure on the syntax to inject a dependency into a property.
Still Need help
I'm having an awful time trying to make miniprofiler not throw Null ref exceptions when I merely move the StructureMap ObjectFactory to a property for init. The goal is to allow roles to be cached. I get the same error as these questions mini-profiler nullreferenceexception Help Configure mvc mini profiler with Linq to Sql
I've updated to the latest MVCMiniProfiler and tried it's MVC package. Seems that profiling isn't enabled before the custom RoleProvider is init or the properties are initialized. If I set the field straight from the overridden GetRolesForUser method, everything is fine. If I make that field a backer to a public property, I get NULL exceptions in ProfiledDbCommand. Why?
The Microsoft "provider" pattern does not work well with dependency injection, because of its reliance on statics and singletons. If you have to use a Provider, just do the service location via ObjectFactory.GetInstance and move on.
What's a good way to validate a model when information external to the model is required in order for the validation to take place? For example, consider the following model:
public class Rating {
public string Comment { get; set; }
public int RatingLevel { get; set; }
}
The system administrator can then set the RatingLevels for which a comment is required. These settings are available through a settings service.
So, in order to fully validate the model I need information external to it, in this case the settings service.
I've considered the following so far:
Inject the service into the model. The DefaultModelBinder uses System.Activator to create the object so it doesn't go through the normal dependency resolver and I can't inject the service into the model without creating a new model binder (besides which, that doesn't feel like the correct way to go about it).
Inject the service into an annotation. I'm not yet sure this is possible but will investigate further soon. It still feels clumsy.
Use a custom model binder. Apparently I can implement OnPropertyValidating to do custom property validation. This seems the most preferable so far though I'm not yet sure how to do it.
Which method, above or not, is best suited to this type of validation problem?
Option 1 doesn't fit. The only way it would work would be to pull in the dependency via the service locator anti-pattern.
Option 2 doesn't work. Although I couldn't see how this was possible because of the C# attribute requirements, it is possible. See the following for references:
Resolving IoC Container Services for Validation Attributes in ASP.NET MVC
NInjectDataAnnotationsModelValidatorProvider
Option 3: I didn't know about this earlier, but what appears to be a very powerful way to write validators is to use the ModelValidator class and a corresponding ModelValidatorProvider.
First, you create your custom ModelValidatorProvider:
public class CustomModelValidatorProvider : ModelValidatorProvider
{
public CustomModelValidatorProvider(/* Your dependencies */) {}
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
{
if (metadata.ModelType == typeof(YourModel))
{
yield return new YourModelValidator(...);
}
}
}
ASP.NET MVC's IDependencyResolver will attempt to resolve the above provider, so as long as it's registered with your IoC container you won't need to do anything else. And then the ModelValidator:
public class EntryRatingViewModelValidatorMvcAdapter : ModelValidator
{
public EntryRatingViewModelValidatorMvcAdapter(
ModelMetadata argMetadata,
ControllerContext argContext)
: base(argMetadata, argContext)
{
_validator = validator;
}
public override IEnumerable<ModelValidationResult> Validate(object container)
{
if (/* error condition */)
{
yield return new ModelValidationResult
{
MemberName = "Model.Member",
Message = "Rating is required."
};
}
}
}
As the provider is retrieved through the IDependencyResolver and the provider has full control over the returned ModelValidators I was easily able to inject the dependencies and perform necessary validation.
You could try fluent validation. It supports asp.net mvc and DI so you can inject external services into your validators.
Assuming that you want both client and server-side validation of the model based upon the values returned from the service, I would opt for 2., Inject the service into an annotation.
I give some sample code in my response to this question about adding validators to a model. The only additional step in your case is that you will need to inject your service into your class inheriting from DataAnnotationsModelValidatorProvider.
What about just simply using IValidateableObject and in that method determine if validation is appropriate or not and setting the errors there?
How do I use IValidatableObject?
I have the following code:
public abstract class BaseController : Controller
{
public IUserService UserService { get; set; }
}
All my controllers inherit from this base controller. I started out by configuring it in Ninject using the following code:
kernel.Bind<BaseController>()
.ToSelf()
.WithPropertyValue("UserService", x => x.Kernel.GetService(typeof(IUserService)));
This did not work. I assume it is because of the fact that the BaseController is an abstract class (please confirm my assumption). So I moved on to modify the configuration to:
kernel.Bind<HomeController>()
.ToSelf()
.WithPropertyValue("UserService", x => x.Kernel.GetService(typeof(IUserService)));
This does work. The minor downside is that I now have to configure every controller the same way.
Since I also have DependencyResolver setup in my ASP.NET MVC 3 project I could also remove the above Ninject configuration and modify my base controller to look like:
public IUserService UserService
{
get
{
return DependencyResolver.Current.GetService<IUserService>();
}
}
Is there any benefit to using the fluent configuration as opposed to using the DependencyResolver approach? Is one better than the other? Which approach would be considered a better practice?
It is worth mentioning that I did not want to do constructor injection in my base controller.
A better practice in MVC it is to use constructor injection over property injection. Why did you make your choice like this ?
Using Constructor Injection you states that all dependencies in constructor are necessary for the class to do its job.
Property injection means that the dependencies are optional or that there are the local defaults implementations, so all will work even if you don't provide necessary implementations yourself.
You should really know what you're doing using Property injection or you have no other choice, so the safer approach is to rely on constructor injection.
Now I'll give you my point of view. Other may have other opinions.
DependencyResolver was introduced in MVC 3 for "convenient" service location but for me it's a regular Service locator which for me is also an anti-pattern http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx. I don't use it because I don't like it and there is no benefit in using it.
I prefer to user my controller factory like before and pass the dependencies through constructor.
More the IDependencyResolver has somme issues with some IoC containers (I don't know if it's the case with Ninject). You can read more here : http://mikehadlow.blogspot.com/2011/02/mvc-30-idependencyresolver-interface-is.html
If you need the same dependency in each controller then there seems to be something wrong in your design. Most likely you are handling some kind of cross cutting concern in your base controller. In this case Doing property injection is just treating sympthoms instead of cureing the disease. This should rather be handled by an aspect (e.g. a filter or an interceptor) so that you do not have to pollute your controller with something that does not belong there.
There are many ways to skin the cat they say. You could use conventions-based bindings with .WithPropertyValue() or with .OnActivaction() (as described here).
public class ControllerModule : NinjectModule
{
public override void Load()
{
// Get all controller types derived from the base controller.
IEnumerable<Type> controllerTypes = // ...
foreach (var controllerType in controllerTypes)
{
Bind(controllerType).ToSelf().InRequestScope()
.WithPropertyValue(...);
}
}
}
You could create your own custom implementation of the IInjectionHeuristic interface as described here or your own custom implementation of the IControllerActivator interface.
public class CustomNinjectControllerActivator : IControllerActivator
{
private readonly IKernel kernel;
public CustomNinjectControllerActivator(IKernel kernel)
{
this.kernel = kernel;
}
public IController Create(RequestContext context, Type controllerType)
{
var baseController = kernel.TryGet(controllerType) as BaseController;
if (baseController == null)
{
return null;
}
baseController.UserService = kernel.Get<IUserService>();
return baseController;
}
}
Heck, you could even use the service locator pattern if you are comfortable using it.
public IUserService UserService
{
get { return DependencyResolver.Current.GetService<IUserService>(); }
}
You should choose whichever solution is easiest to implement, test and maintain, and of course provides the desired behavior.