FluentValidation on ApplicationService Endpoint - aspnetboilerplate

I'm trying to add FluentValidation to my ABP ApplicationService as described in this article.
I added the NuGet package, and also specified the dependency on my main application module:
[DependsOn(
typeof(MyCoreModule),
typeof(AbpQuartzModule),
typeof(AbpFluentValidationModule))]
public class MyApplicationModule : AbpModule
{
// ...
}
I then created a validator:
public class MyDtoValidator : AbstractValidator<MyDto>
{
public MyDtoValidator()
{
RuleFor(x => x).Custom(MyCustomRule);
}
// ...
}
Then in my app service I simply have the following endpoint:
public class MyAppService : ApplicationService
{
// Constructor
public void MyEndpoint(MyDto input)
{
// ...
}
}
The MyDtoValidator constructor is never called. I presume one has to call the validator manually for application services.

aspnetboilerplate resolves the validators using IOC check source code
In the source code for the related unit tests FluentValidationTestController they defined the validator class inside the controller.
I'm assuming that you created 2 seperate classes for the validator and controller, thus the validator factory isn't finding the MyDtoValidator class.
TLDR: try adding the interface ITransientDependency to the MyDtoValidator class

Related

Class fixture type 'SetupFixture' had one or more unresolved constructor arguments [duplicate]

I am using XUnit and need to perform some action before running a test suit. so, I try to use IClassFixture feature of XUnit. but I cannot find a way to inject dependencies into the Fixture class. my code structure is such as below:
public class MyFixture
{
IDependency _dep;
public MyFixture(IDependency dep)
{
_dep = dep;
}
void DoSomeJob()
{
//// some code there
dep.DoSome();
}
}
And this is my test class code:
public class MyTest : IClassFixture<MyFixture>
{
[Fact]
public void test_my_code()
{
////simply just test the code
}
}
but when I run the test I am getting the exception
Xunit.Sdk.TestClassException Class fixture type 'MyFixture' had one or more unresolved constructor
Your Fixture class depends on IDependency dep, which has not been configured. You could use the Fixture class to setup a service provider; However it is not the best solution, as you have to end up using service locator patter such as
serviceProvider.GetRequiredService<T>()
Suggest to use xunit.di, it is an extension built into xunit framework to support constructor dependency injection, which allows us to achieve Inversion of Control (IoC) between test classes and their dependencies.
Install-Package Xunit.Di
To use xunit.di:
Install the xunit.di nuget package
Create a Setup.cs class to configure dependencies, (optional) and inherits the Xunit.Di.Setup.cs
Configure dependencies in the Setup.cs class.
Find full instructions and demos from xunit.di GET-STARTED
Your test project has the following:
Setup class that has a public IServiceProvider, which configures all the dependencies
Test class with constructor injecting the dependencies
Your Setup.cs class looks like below:
private IServiceProvider _services;
private bool _built = false;
private readonly IHostBuilder _defaultBuilder;
public Setup()
{
_defaultBuilder = Host.CreateDefaultBuilder();
}
public IServiceProvider Services => _services ?? Build();
private IServiceProvider Build()
{
if (_built)
throw new InvalidOperationException("Build can only be called once.");
_built = true;
_defaultBuilder.ConfigureServices((context, services) =>
{
services.AddSingleton<TextReaderService>();
services.AddSingleton<IDependency, DependencyImpl>();
// where DependencyImpl implements IDependency
// ... add other services needed
});
_services = _defaultBuilder.Build().Services;
return _services;
}
Then your test class looks like below:
public class MyTest
{
private readonly IDependency _dependency;
public MyTest(IDependency dependency)
{
_dependency = dependency;
}
[Fact]
public void test_my_code()
{
var result = _dependency.DoStuff();
Assert.NotNull(result);
////simply just test the code
}
}

How to Configure the injection of my IErrorInfoBuilder in AbpBoilerPlate

Starting from the MVC module-zero-template I defined my IErrorInfoBuilder in this way:
public class MyErrorInfoBuilder : IErrorInfoBuilder, ISingletonDependency {
// ...
}
and I injected it in the PreInitialize method of the BookingWebApiModule, the only point the code where the Register method does not throw an error:
namespace GPSoftware.Booking.Api {
[DependsOn(typeof(AbpWebApiModule), typeof(BookingApplicationModule))]
public class BookingWebApiModule : AbpModule {
public override void PreInitialize() {
IocManager.Register<IErrorInfoBuilder, MyErrorInfoBuilder>();
}
// ...
}
My problem is my custom error builder is not always invoked by the framework in my application. There are some situations (like when a validation error occurs in the input DTO of a AppService method) that continues to invoke the default Abp implementation of the IErrorInfoBuilder interface.
I am sure It is a matter of initialization/configuration. But I don't know how and where, in the code, to fix the issue.

Castle Windsor DI installer: dependency factory method has nested dependency on ApiController property

I am trying to implement DI with Castle Windsor. Currently I have a controller with overloaded constructors like this (this is an antipattern as described here: https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=97):
public class MyController : ApiController
{
protected IStorageService StorageService;
protected MyController()
{
StorageService = StorageServiceFactory.CreateStorageService(User.Identity as ClaimsIdentity);
}
protected MyController(IStorageService storageService)
{
StorageService = storageService;
}
}
I am trying to get rid of the first constructor and have Castle Windsor handle the resolution of the storage service dependency.
I created a Castle Windsor installer class like this:
public class StorageServiceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IStorageService>()
.UsingFactoryMethod(
() => StorageServiceFactory.CreateStorageService(User.Identity as ClaimsIdentity)));
}
}
The problem is that User (which has type IPrincipal) is a property on ApiController, so it's not accessible from the installer. How can I make this work?
Update:
#PatrickQuirk seems to be implying that there is a better way to do this using Castle Windsor without needing a factory at all.
My StorageServiceFactory looks like this:
public static class StorageServiceFactory
{
public static IStorageService CreateStorageService(ClaimsIdentity identity)
{
if (identity == null)
{
return null;
}
Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier);
if (providerKeyClaim == null || string.IsNullOrEmpty(providerKeyClaim.Value))
{
return null;
}
StorageProviderType storageProviderType;
string storageProviderString = identity.FindFirstValue("storage_provider");
if (string.IsNullOrWhiteSpace(storageProviderString) || !Enum.TryParse(storageProviderString, out storageProviderType))
{
return null;
}
string accessToken = identity.FindFirstValue("access_token");
if (string.IsNullOrWhiteSpace(accessToken))
{
return null;
}
switch (storageProviderType)
{
// Return IStorageService implementation based on the type...
}
}
}
Is there a way to incorporate selecting the correct IStorageService into Windsor's dependency resolution and avoid the factory altogether? Or do I still need it?
I like #PatrickQuirk's solution, except that it seems odd to have to create a wrapper and corresponding wrapper interface for the factory just for the sake of dependency injection. Ideally I'd have the api controller's constructor take in an IStorageService as a parameter, which seems more intuitive/consistent with the field that actually needs to be set.
I don't think the multiple constructors is as much of a sin as the hidden dependency on StorageServiceFactory is, but I agree with your approach for the most part.
Instead of a factory method, pass a factory object into the class and have it create the storage service:
public class MyController : ApiController
{
protected IStorageService StorageService;
protected MyController(IStorageServiceFactory storageServiceFactory)
{
StorageService = storageServiceFactory.CreateStorageService(User.Identity as ClaimsIdentity);
}
}
And then define your factory interface and implementation:
public interface IStorageServiceFactory
{
IStorageService Create(ClaimsIdentity claimsIdentity);
}
public class StorageServiceFactoryImpl : IStorageServiceFactory
{
public IStorageService Create(ClaimsIdentity claimsIdentity)
{
return StorageServiceFactory.CreateStorageService(claimsIdentity);
}
}
This way, you have a single constructor and the dependency on the storage service factory is explicit.
Regarding your update:
...it seems odd to have to create a wrapper and corresponding wrapper interface for the factory just for the sake of dependency injection.
Well, that's kind of the point of dependency injection.
The wrapper I propose is solving two problems: it removes the need to call a static method from inside your class (hiding a dependency), and allows for delayed resolution (because your dependency relies on member data to be created).
If you have a way to change the dependencies of creating an IStorageService to not rely on a member of the class you're giving it to, then you could pass one in directly (provided you can tell Windsor how to create one).

Autofac, WebAPI, and Media Formatters

I need some assistance. I am trying to use Autofac to get me a few dependencies that are need for a custom media formatter. I followed the Wiki but it is a little confusing. I am trying to use property injection for the media formatter since it needs to be registered with the global configuration.
Code:
public class UserMediaFormatter : JsonMediaTypeFormatter
{
public UsersRepository repository { get; set; }
}
public class WebApiApplication : System.Web.HttpApplication
{
GlobalConfiguration.Configuration.Formatters.Insert(2, new UserMediaFormatter());
builder.RegisterType(typeof(UserMediaFormatter)).PropertiesAutowired()
.As<MediaTypeFormatter>()
.InstancePerApiControllerType(typeof (UsersController));
}
[AutofacControllerConfiguration]
public class UsersController : ApiController
{
}
If you want to let Autofac to add your custom formatter to the marked controllers then you don't need to add it to the GlobalConfiguration.Configuration.Formatters because it makes your formatter globally available and it prevents Autofac to inject properties on it.
So remove the GlobalConfiguration.Configuration.Formatters.Insert call
and use the following exact syntax to register your formatter:
builder.Register<MediaTypeFormatter>(c => new UserMediaFormatter())
.PropertiesAutowired()
.InstancePerApiControllerType(typeof(UsersController));

How to apply a global filter in playframework

When using #before, it is only used in one class. How do I apply a global filter in playframework? So that one filter is used for all controller classes.
A simple solution is to extend a base controller for all of your controllers and have the #Before in the base controller.
The other option (and the better solution, as it is more flexible) is to use the #With annotation. The example on the play documentation is
Example:
public class Secure extends Controller {
#Before
static void checkAuthenticated() {
if(!session.containsKey("user")) {
unAuthorized();
}
}
}
And on another Controller:
#With(Secure.class)
public class Admin extends Application {
...
}
This means the Admin controller will process all the interceptors (#Before, #After, #Finally) contained within the Secure controller.
I did this very thing by handling incoming requests globally in the GlobalSettings class:
This describes the class:
http://www.playframework.org/documentation/2.0/JavaGlobal
This describes the method you'd want to override.
http://www.playframework.org/documentation/2.0/JavaInterceptors
Here's an example of how I used it in my own project (of course, this is a simplified version of what you're looking for):
#Override
public play.mvc.Action onRequest(play.mvc.Http.Request request, java.lang.reflect.Method method) {
if (request.path().startsWith("/secret/locked")) {
return new Action.Simple() {
#Override
public Result call(play.mvc.Http.Context ctx) throws Throwable {
return redirect(routes.Application.forbidden());
}
};
}
return super.onRequest(request, method);
}
You can simply use PlayPlugin for this issue. See here for more details.
It's not a good solution to extend a base controller for all of your controllers and have the #Before in the base controller.
You can extends the filter or essensialfilter .e.g.
class filter1 extends Filter {}
and apply filter1 to Global

Resources