Closed sarabu07 closed 3 years ago
Does this help? If not, please provide me with more information on what it is you are trying to achieve, what you tried, and what you're stuck with.
@dotnetjunkie We are using Asp.Net core and .Net core 3.1. The above example seems to be for .Net framework. Is it still valid for .Net core 3.1?
Is it still valid for .Net core 3.1?
Don't know. Did you check?
@dotnetjunkie I get
'FluentValidationModelValidatorProvider' is inaccessible due to its protection level error.
Also, I get
System.InvalidOperationException: Unable to resolve service for type 'Serilog.ILogger' while attempting to activate
and didn't get any error for IValidatorFactory
interface. We use below code to use Fluent Validation.
services.AddMvc(options =>
{
options.Filters.Add(typeof(ValidateModelAttribute));
options.EnableEndpointRouting = false;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
.AddXmlSerializerFormatters()
.AddFluentValidation(options =>
{
options.RegisterValidatorsFromAssemblyContaining<Startup>();
// Avoid MVC modelstate validation
options.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
});
Unable to resolve service for type 'Serilog.ILogger' while attempting to activate'
How is that related to the integration Fluent Validation? Does Fluent Validation depend on and use Serilog? Or do you usr Serilog in your application?
@dotnetjunkie we use Serilog in our ValidateModelAttribute
class to log the errors. Please refer to my first post for code.
public ValidateModelAttribute(IValidatorFactory factory, ILogger logger)
{
_factory = factory;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
@dotnetjunkie We are using global action filter with the name 'ValidateModelAttribute' and if i remove Ilogger from construction the code is working.
public ValidateModelAttribute(IValidatorFactory factory)
{
_factory = factory;
//_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
In simple injector we could not pass any additional parameter to global filter constructor ? or Im missing something
You are adding your filter attribute to MVC's Filters
collection, but the list of filters is tighly coupled to the built-in DI container. To circumvent this, you'll need to wrap the type in a proxy class, similar to the proxy described in this Stack Overflow answer: https://stackoverflow.com/a/43569535
@dotnetjunkie Thanks, When i implemented in my code i get
Argument 1: cannot convert from 'T.SimpleInjectiorAsyncActionFilterProxy
' to 'System.Type'
services.AddMvc(mvc =>
{
mvc.Filters.Add(new SimpleInjectiorAsyncActionFilterProxy<ValidateModelAttribute>(container);
mvc.EnableEndpointRouting = false;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
.AddFluentValidation(options =>
{
options.RegisterValidatorsFromAssemblyContaining<Startup>();
// Avoid MVC modelstate validation
options.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
});
Try this:
mvc.Filters.Add(typeof(SimpleInjectiorAsyncActionFilterProxy<ValidateModelAttribute>));
@dotnetjunkie Thanks. Now the DI is injecting for Logger but getting
The type 'D.SimpleInjectiorAsyncActionFilterProxy`1[[D.CustomValidator, D, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' must derive from 'Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata'. (Parameter 'filterType')
Please see below my proxy class.
public sealed class SimpleInjectiorAsyncActionFilterProxy<TAsyncActionFilter>
where TAsyncActionFilter : ActionFilterAttribute, IFilterMetadata
{
private readonly Container container;
public SimpleInjectiorAsyncActionFilterProxy(Container container)
{
this.container = container;
}
public void OnActionExecuting(ActionExecutingContext c)
{
container.GetInstance<TAsyncActionFilter>().OnActionExecuting(c);
}
}
Change the definitioncof your proxy to:
public sealed class SimpleInjectiorAsyncActionFilterProxy<TAsyncActionFilter
: IFilterMetadata
where TAsyncActionFilter : ActionFilterAttribute, IFilterMetadata
@dotnetjunkie Thanks now no errors, I see DI injected but OnActionExecuting is not getting fired
public sealed class SimpleInjectiorAsyncActionFilterProxy<TAsyncActionFilter>
: IFilterMetadata where TAsyncActionFilter : ActionFilterAttribute, IFilterMetadata
{
private readonly Container container;
public SimpleInjectiorAsyncActionFilterProxy(Container container)
{
this.container = container;
}
public void OnActionExecuting(ActionExecutingContext context)
{
container.GetInstance<TAsyncActionFilter>().OnActionExecuting(context);
}
}
DI code
container.Register<ValidateModelAttribute >();
I'm sorry, but I'm on holiday roght now, so am unable to help you any further at the moment. Hopefully you'll be able to figure out how to get this working. Ley me know if you figured it out.
Cheers
@dotnetjunkie Sorry to bother in your vacation. Happy vacation!.
@dotnetjunkie The below code for simple injector action proxy worked. Thanks for your help.
public sealed class SimpleInjectiorAsyncActionFilterProxy<T>
: IFilterFactory where T : ActionFilterAttribute, IFilterMetadata
{
private readonly Container container;
public SimpleInjectiorAsyncActionFilterProxy(Container container)
{
this.container = container;
}
bool IFilterFactory.IsReusable { get; }
public void OnActionExecuting(ActionExecutingContext context)
{
container.GetInstance<T>().OnActionExecuting(context);
}
IFilterMetadata IFilterFactory.CreateInstance(IServiceProvider serviceProvider)
{
return container.GetInstance<T>();
}
}
We are using fluent validation library and use ActionFilterAttribute for custom handling the validation events. Please see our code below. Let me know how to integrate Simple Injector with this example.