i was reading a write up on easily dependency injection in ASP.Net MVC 6 from this url http://weblogs.asp.net/scottgu/introducing-asp-net-5
they show how very easily we can inject dependency into project
1st one
namespace WebApplication1
{
public class TimeService
{
public TimeService()
{
Ticks = DateTime.Now.Ticks.ToString();
}
public String Ticks { get; set; }
}
}
register the time service as a transient service in the ConfigureServices method of the Startup class:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddTransient<TimeService>();
}
public class HomeController : Controller
{
public TimeService TimeService { get; set; }
public HomeController(TimeService timeService)
{
TimeService = timeService;
}
public IActionResult About()
{
ViewBag.Message = TimeService.Ticks + " From Controller";
System.Threading.Thread.Sleep(1);
return View();
}
}
2nd one
public class HomeController : Controller
{
[Activate]
public TimeService TimeService { get; set; }
}
now see the second code. are they trying to say that if we use [Activate] attribute then we do not have to instantiate TimeService by controller constructor injection?
just tell me if we use [Activate] attribute then what will be the advantage ?
if we use [Activate] attribute then what line of code we can eliminate from 1st same code. thanks
The differences between the two code blocks are indeed that the first one leverages Constructor Injection to resolve the dependency on TimeService, while the second example marks a property as one that needs resolving using Property Injection.
What this means is simply that the following constructor becomes redundant:
public HomeController(TimeService timeService)
{
TimeService = timeService;
}
As to why one would opt for Constructor versus Property Injection, I find that trying to have a list of your dependencies clearly listed out in your constructor highlights when a class becomes too dependent, which raises concerns as to what a class is trying to accomplish and, subsequently, makes it a candidate for refactoring.
Property Injection via [Activate] will not be supported from beta5 onwards.
Related
I am designing a NuGet package that will be consumed by my application. Due to the project's already implemented architecture, I need to provide a way to instantiate objects using dependency injection both for MVC and Web API outside my controller scope.
Currently I have a class that works in MVC projects, by instantiating objects using the DependencyResolver
public abstract class MyBaseClass<T> where T : class
{
public static T Instance
{
get
{
return DependencyResolver.Current.GetService<T>();
}
}
}
However, when consuming this same class from a WebAPI project, the DependencyResolver is not present, so Im not able to retrieve any object.
I have tried to access the dependency resolver via the HttpContext but have been unsuccessfull. Do you have any way I can access it through a NuGet package?
Thanks!
If it's possible, I'd suggest avoid the service locator pattern and inject the dependency through the constructor instead:
public abstract class MyBaseClass<T> where T : class
{
public MyBaseClass(T instance)
{
Instance = instance;
}
public T Instance { get; }
}
This will allow you to use your package through any "main" entry point (e.g. MVC or WebAPI) that you choose. At that point, it would be the responsibility of the consumer to provide the necessary dependency resolution strategy.
Here's an example of how a consumer (in this case a WebAPI service) of the package would implement the above code:
public class MyWebApiClass : MyBaseClass<MyDependency>
{
public MyWebApiClass(MyDependency resolvedDependency) : base(resolvedDependency) { }
}
public class MyDependency
{
public string Foo { get; set; }
public MyDependency()
{
Foo = "Bar";
}
}
Then the consuming service would also register those dependencies:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddTransient<MyDependency>();
services.AddTransient<MyWebApiClass>();
}
... and inject as needed, allowing the framework to resolve the dependencies (IoC at work):
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly MyWebApiClass _myWebApiClass;
public ValuesController(MyWebApiClass myWebApiClass)
{
_myWebApiClass = myWebApiClass;
}
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { _myWebApiClass.Instance.Foo };
}
}
Making a call to the GET endpoint above, we can see our instance being resolved in MyBaseClass:
My Startup is like this :
public void ConfigureServices(IServiceCollection services)
{
// code here
Bootstraper.Setup(services);
}
And my Bootstraper class is like this :
public static partial class Bootstraper
{
// code here
public static IServiceCollection CurrentServiceCollection { get;set;}
public static IServiceProvider CurrentServiceProvider
{
get { return CurrentServiceCollection.BuildServiceProvider(); }
}
public static void Setup(IServiceCollection serviceCollection)
{
// code here
SetupLog();
InitializeCulture();
InitializeDbContexts();
RegisterDataModelRepositories();
}
and this is content of my RegisterDataModelRepositories():
CurrentServiceCollection.AddTransient<IDefAccidentGroupRepository>(p => new DefAccidentGroupRepository(ApplicationMainContextId));
CurrentServiceCollection.AddTransient<IDefGenderRepository>(p => new DefGenderRepository(ApplicationMainContextId));
in short : I just want to be able to use Service Locator in my methods without resolving dependency in class constructor ... is there any way around it ....
Dependency injection can also be done on a by action basis.
Referece Dependency injection into controllers: Action Injection with FromServices
Sometimes you don't need a service for more than one action within your controller. In this case, it may make sense to inject the service as a parameter to the action method. This is done by marking the parameter with the attribute [FromServices]
public IActionResult SomeAction([FromServices] IReportService reports) {
//...use the report service for this action only
return View();
}
Just make sure that the required services are registered with the service collection.
services.AddTransient<IDefAccidentGroupRepository>(p => new DefAccidentGroupRepository(ApplicationMainContextId));
services.AddTransient<IDefGenderRepository>(p => new DefGenderRepository(ApplicationMainContextId));
services.AddTransient<IReportService, ReportService>().
well , thanks for your help ...
There is a easier and better way for it , I just need to add another Service that use these repository and then resolve that service in my controller and let Asp.net Core 2.0 DI to solve the problem for me ...
public interface IActionService
{
IRepositoryA repA {get;set;}
IRepositoryB repB { get;set;}
DoTaskX();
DoTaskY();
}
then in my ActionService :
public class ActionService : IActionService
{
public IRepositoryA repA {get;set;}
public IRepositoryB repB { get;set;}
public ActionService (IRepositoryA rep_a , IRepositoryB rep_b ) {
repA = rep_a;
repB = rep_b;
}
DoTaskX(){
// do task using repository A and B
}
}
then I register IActionService in Startup.cs and resolve itin my ActionController and life become easier and code become cleaner ...
the solution was easy but I had to change my mindset to solve the problem ...
Working on web api using EF codefirst approach.
I want to use Dependency injection using Unity framework.
i downloaded--Unity.webapi, it addeds few unity files(unityconfig, unityresolver). my entities i registered as like attachment.
but my codefirst entities not implements any interfaces, all are plain code first classes. now i want to write code in my controllers. how to write ?
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<ApplicationDbContext,PolicyInfo>));
container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<ApplicationDbContext, LossInformation>));
container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<ApplicationDbContext, Manufacturer>));
container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<ApplicationDbContext, ModelVariant>));
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
class
public class **PolicyInfo**
{
[Key]
public int PolicyId { get; set; }
[Required]
public string Manufacturer { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime PolicyIssuedDate { get; set; }
}
controller:
[RoutePrefix("api/PolicyInfo")]
public class PolicyInfoController : ApiController
{
GenericRepository<ApplicationDbContext, PolicyInfo> policycontext;
public PolicyInfoController()
{
this.policycontext = new GenericRepository<ApplicationDbContext, PolicyInfo>();
}
}
I hope this is not write way to create context object. because i written PolicyInfo object at constructor level. please suggest any one.
One of the key concepts behind Inversion of Control (IoC) and Dependency Injection (DI) is precisely not to have to manually instantiate the required dependencies inside the consumer class but those dependencies to get injected into the class.
So if you are using Unity or any other framework, the goal is to suppress the line where you are creating the object context by a parameter in this case in the constructor of your API Controller.
So you if your IoC container is properly configured you should be able to get a reference to the GenericRepository using e.g, constructor injection:
Try this:
[RoutePrefix("api/PolicyInfo")]
public class PolicyInfoController : ApiController
{
IGenericRepository<ApplicationDbContext, PolicyInfo> policycontext;
public PolicyInfoController(IGenericRepository<ApplicationContext,PolicyInfo> policyContext)
{
//use the context here... e.g.: Save the reference to the instance field.
this.policyContext = policyContext;
}
}
However, I would suggest a bit more of abstraction in your code in order to make it clearer and more efficient.
Take a look a this article, although a little old, still applies perfectly to your problem. Hope this helps.
I'm trying my hand at dependency injection for my RPG written in c# and some javascript.
I'm trying to inject a service into my controller but keep getting this error:
Error activating IdownloadService No matching bindings are available, and the type is not self-bindable.
In debug mode, it fails on this line with the above error in my CharacterController class:
public IdownloadService downloadService{ get; }
Here is the relevant code:
characterDownloadService.cs
namespace OrionRPG.Character.Downloads
{
public interface IdownloadService
{
Uri CharacterDownloadUri(int charId);
}
public class characterDownloadService : IdownloadService
{
public characterDownloadService()
{}
public const String CharacterServerUrl = "http://myUrl/Characters/";
public Uri CharacterDownloadUri(int charId)
{
var characterName = Character.Name(charId);
return new Uri(CharacterServerUrl + characterName);
}
}
}
CharacterController.cs
namespace OrionRPG.Api.Downloads
{
public class CharacterController
{
public IdownloadService downloadService{ get; }
//inject the service
public CharacterController(IdownloadService downloadService)
{
DownloadService = downloadService;
}
[Route("api/characters/download/{charId}")]
public IHttpActionResult GetCharacterDownload(int charId)
{
return Redirect(DownloadService.CharacterDownloadUri(charId));
}
}
}
Generally speaking, services need to be registered to a container before injection. Different dependency injection framework might have slightly different syntax, the principles are the same.
For example, if you are using Microsoft.Extensions.DependencyInjection, you will need to Register the service: In Startup.cs (ASP.NET Core), you will see a method named ConfigureServices, and you will need to register your service like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(); // Some code by template
...
// This line registers the IdownloadService; when injection happens, the service provider knows to create an implementation of characterDownloadService for requested IdownloadService.
services.AddTransient<IdownloadService, characterDownloadService>();
}
For more details, check this out.
1) As I understand you are trying to use ASP.NET WebApi and it is strange that CharacterController doesn't inherit ApiController
2) You need to use Dependency Injection container which will contains all mapping between interfaces and it's implementation. I would recommend to use Autofac as it is perfectly integrated with ASP.NET MVC and WebAPI. Here is a link with docs
In an MVC project I'm creating I have the following RequirePermissionAttribute that gets put on any action that needs specific permissions (it's been simplified for this example):
public class RequirePermissionAttribute : ActionFilterAttribute, IAuthorizationFilter
{
public Operation Permissions { get; set; }
public RequirePermissionAttribute() { }
public RequirePermissionAttribute(Operation permissions)
{
this.Permissions = permissions;
}
public bool AuthorizeCore(HttpContextBase httpContext)
{
IAuthorizationService authServ = new ASPNETAuthorizationService();
return authServ.Authorize(httpContext);
}
public void OnAuthorization(AuthorizationContext filterContext)
{
Enforce.ArgNotNull(filterContext);
if (this.AuthorizeCore(filterContext.HttpContext))
{
// code snipped.
}
else
{
// code snipped.
}
}
}
So the problem obviously with this is that my authorize attribute has a dependency on the ASPNETAuthorizationService that I created. I can't go the constructor way since attributes are compile-time checked.
One thing to mention, I'm using my own little IoC that I made and it doesn't have support for property injection (yet). Of course, if I did go the property injection route, I'd have to add support for it (which I'd have to do some research on).
What's the best way to inject something into an attribute class?
What's the best way to inject something into an attribute class?
Strictly speaking, we cannot use dependency injection to inject a dependency into an attribute. Attributes are for metadata not behavior. [AttributeSpecification()] encourages this by forbidding reference types as arguments.
What you're probably looking for is to use an attribute and a filter together, and then to inject dependencies into the filter. The attribute adds metadata, which determines whether to apply the filter, and the filter receives the injected dependencies.
How to use dependency injection with an attribute?
There are very few reasons to do this.
That said, if you're intent on injecting into an attribute, you can use the ASP.NET Core MVC IApplicationModelProvider. The framework passes dependencies into the provider's constructor, and the provider can pass dependencies to the attribute's properties or methods.
In your Startup, register your provider.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.TryAddEnumerable(ServiceDescriptor.Transient
<IApplicationModelProvider, MyApplicationModelProvider>());
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
}
}
Use constructor injection in the provider, and pass those dependencies to the attribute.
using System.Linq;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.Routing;
public class MyApplicationModelProvider : IApplicationModelProvider
{
private IUrlHelperFactory _urlHelperFactory;
// constructor injection
public MyApplicationModelProvider(IUrlHelperFactory urlHelperFactory)
{
_urlHelperFactory = urlHelperFactory;
}
public int Order { get { return -1000 + 10; } }
public void OnProvidersExecuted(ApplicationModelProviderContext context)
{
foreach (var controllerModel in context.Result.Controllers)
{
// pass the depencency to controller attibutes
controllerModel.Attributes
.OfType<MyAttribute>().ToList()
.ForEach(a => a.UrlHelperFactory = _urlHelperFactory);
// pass the dependency to action attributes
controllerModel.Actions.SelectMany(a => a.Attributes)
.OfType<MyAttribute>().ToList()
.ForEach(a => a.UrlHelperFactory = _urlHelperFactory);
}
}
public void OnProvidersExecuting(ApplicationModelProviderContext context)
{
// intentionally empty
}
}
Create an attribute with public setters that can receive dependencies.
using System;
using Microsoft.AspNetCore.Mvc.Routing;
public sealed class MyAttribute : Attribute
{
private string _someParameter;
public IUrlHelperFactory UrlHelperFactory { get; set; }
public MyAttribute(string someParameter)
{
_someParameter = someParameter;
}
}
Apply the attribute to a controller or an action.
using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
[MyAttribute("SomeArgument")]
public class ValuesController : Controller
{
[HttpGet]
[MyAttribute("AnotherArgument")]
public string Get()
{
return "Foobar";
}
}
The above demonstrates one way, for the rare use case, that you can inject dependencies into an attribute. If you figure out a valid reason to do this, please post it in the comments.
I originally thought this was not possible, but I stand corrected. Here's an example with Ninject:
http://codeclimber.net.nz/archive/2009/02/10/how-to-use-ninject-to-inject-dependencies-into-asp.net-mvc.aspx
Update 2016-10-13
This is a pretty old question by now, and frameworks have changed quite a bit. Ninject now allows you to add bindings to specific filters based on the presence of specific attributes, with code like this:
// LogFilter is applied to controllers that have the LogAttribute
this.BindFilter<LogFilter>(FilterScope.Controller, 0)
.WhenControllerHas<LogAttribute>()
.WithConstructorArgument("logLevel", Level.Info);
// LogFilter is applied to actions that have the LogAttribute
this.BindFilter<LogFilter>(FilterScope.Action, 0)
.WhenActionHas<LogAttribute>()
.WithConstructorArgument("logLevel", Level.Info);
// LogFilter is applied to all actions of the HomeController
this.BindFilter<LogFilter>(FilterScope.Action, 0)
.WhenControllerTypeIs<HomeController>()
.WithConstructorArgument("logLevel", Level.Info);
// LogFilter is applied to all Index actions
this.BindFilter(FilterScope.Action, 0)
.When((controllerContext, actionDescriptor) =>
actionDescriptor.ActionName == "Index")
.WithConstructorArgument("logLevel", Level.Info);
This is in keeping with the principle, argued by Mark Seeman and by the author of Simple Injector, which is that you should keep the logic of your action filter separate from the custom attribute class.
MVC 5 and 6 also make it far easier to inject values into attributes than it used to be. Still, separating your action filter from your attribute is really the best approach to take.