I have a custom authorize attribute like this :
public class AuthorizeApplicationAttribute : AuthorizeAttribute {
private MainServiceSoapClient client;
public AuthorizeApplicationAttribute() {
this.client = new MainServiceSoapClient();
}
public AuthorizeApplicationAttribute(MainServiceSoapClient client) {
this.client = client;
}
protected override bool IsAuthorized(HttpActionContext actionContext) {
if (!base.IsAuthorized(actionContext)) return false;
var currentUser = System.Web.Security.Membership.GetUser();
if (currentUser == null) return false;
var userId = (int)currentUser.ProviderUserKey;
return client.HasPermission(userId);
}
}
which I register in WebApiConfig as :
public class WebApiConfig {
public static void Register(HttpConfiguration config) {
// Web API configuration and services
config.Filters.Add(new AuthorizeApplicationAttribute());
// more configuration ...
}
}
but AuthorizeAttribute doesn't have a dispose, I can call the constructor with the soap client instance, but then I'm not sure where to dispose it.
FYI: I'm not using a IoC container. Trying to learn how to make it manually.
This example uses a SoapClient but I have the same question about a DbContext while I can live without disposing DbContext and don't think not disposing a WCF Client will be that good.
Use a using statement inside your IsAuthorized method to initialize and Dispose when needed instead of initializing in constructor.
If you ever need dependency injection then you can use Property Injection.
This question has two answers with Ninject and StructureMap How to use dependency injection with an attribute?
Solution to this question might give you exactly what you want:
What is the best workaround for the WCF client `using` block issue?
Related
I am creating a class which reads the header using IHttpContextAccessor and reads the values from header.
Like ".net framework" we can access context in static manner HttpContext.Current... so shall I inject my class as Singlton or Scoped as the context or context.header value is going to change in each request.
Below is what I am trying
public class RequestHeaderHelper
{
private readonly IHttpContextAccessor httpContext;
public RequestHeaderHelper(IHttpContextAccessor httpContext)
{
this.httpContext = httpContext;
}
public string BrowserIP
{
get
{
if (httpContext.HttpContext.Request.Headers.ContainsKey("X-Client-IP"))
return httpContext.HttpContext.Request.Headers.ContainsKey("X-Client-IP").ToString();
else
return string.Empty;
}
private set { }
}
....
}
Edit 1
Further I am going to use this class inside my other classes like logger. I have created action filter and exception logger where I am going to use this.
I am also using wcf client class to call the service. I am using logging there as well using beforesend and aftersend. I am adding endpoint behavior.
I want to use wcf client as singlton but use the above class in logger.
I am trying to set up some authorisation for a Web API I have. My project uses Entity framework context, and dependency injection.
I have a Web API function like this:
[Authorize2]
[HttpPost]
[Route("whatever")]
public async Task<IHttpActionResult> APIfunction()
{
//Do something...
return Ok();
}
and I have extended the AuthorizeAttribute class to this:
public class Authorize2 : AuthorizeAttribute
{
/// <summary>
///
/// </summary>
/// <param name="actionContext"></param>
public override void OnAuthorization(HttpActionContext actionContext)
{
}
}
This means that the OnAuthorization function will fire before this API function is hit - which is as I want and working fine.
I have a function that is used to determine if the user has permission to access this function. The function is defined in an interface, implemented in a class and the class is instantiated using dependency injection eg:
public interface IPermissions
{
bool hasPermission();
}
public class Permissions : IPermissions
{
public Permissions(numerous DI interfaces passed into the constructor)
{
//Assign values....
}
public bool hasPermission()
{
{
}
and my dependency config has this:
container.Register<Permissions, IPermissions>();
My issue is that I want to call the hasPermission function in my OnAuthorization function eg like this:
public override void OnAuthorization(HttpActionContext actionContext)
{
var perm = _permissions.hasPermission();
}
But I do not know how I can do this, or if it is even possible?
I cannot manually create the classes as there are to many classes and constructors to add it and it is not practical.
I have tried making Authorize2 implement an interface and then create an instance in my dependency constructor, but that would mean passing in a parameter her [Authorize2], which is not possible.
The only other way I can see is to create this function manually within my Authorize class, but I really do not want to do this unless I have to.
Adding this to the to the token is not an option and the data is dynamic and has to be evaluated on a case by case basis
Since the attributes do not allow dependency injection, use service location via the DependencyResolver which you can get via the ActionContext
public override void OnAuthorization(HttpActionContext actionContext) {
var resolver = actionContext.RequestContext.Configuration.DependencyResolver;
var _permissions = (IPermissions)resolver.GetService(typeof(IPermissions));
var perm = _permissions.hasPermission();
//...
}
You need to resolve dependency using parameterized constructor.
Modify your Authorize2 class,
public class Authorize2 : AuthorizeAttribute
{
private readonly IPermissions _permissions;
public Authorize2(IPermissions permissions)
{
this._permissions=permissions;
}
public override void OnAuthorization(HttpActionContext actionContext)
{
var perm = _permissions.hasPermission();
}
}
I’m using Service Stack, and I can´t (or I don´t know how make a Service class with constructor).
Here is what I did:
public class AppHost : AppSelfHostBase
{
public AppHost()
: base("ClientService", typeof(ClientService).Assembly)
{
}
public override void Configure(Container container)
{
}
}
public class Context : ApplicationContext
{
//This class is invoked from program.cs (winform application)
//Here i have the logic of what form should i start.
var listeningOn = string.Format("http://*:{0}/", port);
var appHost = new AppHost();
appHost.Init();
appHost.Start(listeningOn);
ClientService cl = new ClientService((ILayout)f, i);
}
public class ClientService : Service
{
private readonly ILayout _activeForm;
private static Init _initConf;
public ClientService(ILayout f, Init i)
{
_activeForm = f;
_activeForm.GetClientData(i);
_initConf = i;
}
public HttpResult Post(Person request)
{
//Here i use _activeForm and _initConf
}
}
So, as I said, in the class ClientService, I wanna make a constructor, but when I make a request to the post message, it shows me the following error:
Error trying to resolve Service
'DexBrokerClient.Services.ClientService' or one of its auto wired
dependencies
ServiceStack Services are autowired and created using both Constructor and Property Injection. Any Constructor parameters are mandatory and must be registered in ServiceStack's IOC in AppHost.Configure(), e.g:
public override void Configure(Container container)
{
container.Register<ILayout>(c => ...);
container.Register<Init>(c => ...);
}
Whereas any public properties on Services are optional and will be populated from the IOC if they exist or are otherwise null.
Resolving Services
Services should be resolved using base.ResolveService<T> API's when inside Service class or HostContext.ResolveService<T>() singleton outside of Services. This resolves the Service class from ServiceStack's IOC and is populated with the IRequest context (if any).
#Mati, #TheMiddleMan The #mythz's answer expects you to have some general knowledge about dependency injection and containers that is IOC (inversion of control). In your question you ask about constructor injection. ServiceStack's IOC can handle it using auto-wiring if you have pre-configured (registered) the parameter object, for example:
container.Register(c => new Layout());
For more samples see https://docs.servicestack.net/ioc.
More about IOC and DI (dependency injection) can be read from https://dzone.com/articles/ioc-vs-di.
I've found a few questions on this, but they tend to point to the exact documentation I'm following... but it's still not working.
I'm building a fairly simple ASP.NET MVC 4 site, and the plan is to use ActionFilterAttribute-based logging. I have a DataAccessProvider class which opens transactions with the database and provides unit-of-work instances, and I'm trying to inject it into the filter attribute.
The documentation says that it's enough to just call RegisterFilterProvider(), and ensure that the relevant types are registered. It specifically says that there is no need to register the attribute, but I've tried both with and without. My code currently looks something like this:
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.Register(x => new EntityAccessProvider())
.As<IDataAccessProvider>()
.InstancePerHttpRequest();
builder.RegisterType<DebugLogAttribute>().PropertiesAutowired();
// ^ I've tried it with and without this line
builder.RegisterFilterProvider();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
The example in the docs then just places a property on the filter, so I've done the same:
public class DebugLogAttribute : ActionFilterAttribute
{
private IDataAccessProvider DataAccess { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext) { ... }
public override void OnActionExecuted(ActionExecutedContext filterContext) { ... }
}
The docs say that's all is required - not even a constructor to inject into; it's done by property injection. When I run this code, however, The DataAccess property is always null; Autofac seems to ignore it. I know the registration works properly because it's correctly injecting EntityAccessProvider into my controllers, but it's not working for attributes. What am I missing?
Your property of type IDataAccessProvider has to be public for injection to work. You can still mark DebugLogAttribute, IDataAccessProvider and it's implementation as internal if you prefer.
[DebugLogAttribute]
public class HOmeController : Controller
{
public ActionResult Index()
{
return View();
}
}
internal class DebugLogAttribute : ActionFilterAttribute
{
public IDataAccessProvider DataAccess { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Debugger.Break();
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
Debugger.Break();
}
}
internal interface IDataAccessProvider {}
internal class DataAccessProvider:IDataAccessProvider {}
I've been having the same issue in asp dotnet core but the current solution (making it public) doesn't seem to work. What I find odd is that the comment below is regarding a web-api but I'm using a normal ASP.NET Core MVC (MVC6). So if anyone has the same problem, try out the solution below.
https://docs.autofac.org/en/latest/integration/webapi.html#standard-web-api-filter-attributes-are-singletons
Unlike the filter provider in MVC, the one in Web API does not allow you to specify that the filter instances should not be cached. This means that all filter attributes in Web API are effectively singleton instances that exist for the entire lifetime of the application.
public override async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
MyService = context.HttpContext.
RequestServices.GetService(typeof(IMyService)) as IMyService;
}
I have a global filter attribute that needs access to an item that is registerd per HTTP request:
// other ContainerBuilder stuff
builder.RegisterType<HttpDependency>().As<IHttpDependency>().InstancePerHttpRequest();
And elsewhere:
internal sealed class MyActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// EVIL YUCKY SERVICE LOCATOR!
var resolved = AutofacDependencyResolver.Current.RequestLifetimeScope.Resolve<IHttpDependency>();
if (resolved.NeedsRedirect)
{
// does a redirect
}
base.OnActionExecuting(filterContext);
}
}
And registering it as a global filter:
// in FilterConfig.cs
filters.Add(new MyActionFilter());
Since this is a global filter, I can't use constructor injection, i.e. the HTTP context on app startup shouldn't get reused for every request. How can I wire this up properly without resorting to reaching out and grabbing it via a service locator?
One method is to remove your logic from the Attribute and implement it in a class that implements IActionFilter. The class is then registered with the container so that dependency injection will work correctly. Orchard CMS using this approach.
public class MyCustomActionFilterAttribute : Attribute
{
}
public class MyCustomActionFilter : FilterProvider, IActionFilter
{
protected MyService Service { get; private set; }
// MyService can be injected by the container...
public MyCustomActionFilter(MyService service)
{
this.Service = service;
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
// Check to see if the action has a matching attribute
var attributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof(MyCustomActionFilterAttribute), true);
// Perform some logic here....
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
}
}
It is possible to create an IActionInvoker that applies the filter to the action, this class is automatically instantiated my MVC using the DependencyResolver.
public class FilterResolvingActionInvoker : ControllerActionInvoker
{
protected IEnumerable<IFilterProvider> Providers { get; private set; }
// Filters registered with the container are injected by the container
public FilterResolvingActionInvoker(IEnumerable<IFilterProvider> providers)
{
this.Providers = providers;
}
// Add the filter to the current FilterInfo
protected override FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
var filters = base.GetFilters(controllerContext, actionDescriptor);
foreach (var provider in this.Providers)
{
provider.AddFilters(filters);
}
return filters;
}
}
Define a common interface that allows us to register our filters.
public interface IFilterProvider
{
void AddFilters(FilterInfo filterInfo);
}
public abstract class FilterProvider : IFilterProvider
{
public void AddFilters(FilterInfo filterInfo)
{
if (this is IActionFilter)
{
filterInfo.ActionFilters.Add(this as IActionFilter);
}
}
}
And register them with the container builder. It is also possible to create an extension method for Autofac to automatically register all IFilterProviders in your assembly.
builder.RegisterType<FilterResolvingActionInvoker>().As<IActionInvoker>().InstancePerDependency();
builder.RegisterType<MyCustomActionFilter>().As<IFilterProvider>().InstancePerDependency();
As always, one of the options to avoid the locator is to have a local factory which is set up in the Compositon Root. The factory is set up so that it uses your ioc container.
http://netpl.blogspot.com/2012/12/di-factories-and-composition-root.html
Although you could argue that "technically" this "looks like" locator (you create a factory instance and ask it for the service), it doesn't introduce any dependencies to any other infrastructure including the actual IoC container you ultimately use to implement the factory - the implementation of the actual factory is a part of the Composition Root (somewhere near the global application class).
Such approach leads to a lot of isolated small factories responsible for parts of your infrastructure but still each factory has a pluggable provider you can implement near the Composition Root thus avoiding any external dependencies.