How to Configure the injection of my IErrorInfoBuilder in AbpBoilerPlate - aspnetboilerplate

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.

Related

FluentValidation on ApplicationService Endpoint

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

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).

Unity not registering

I'm using unity in my MVC app
I have the following RegisterTypes method within my Bootstapper.cs file:
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<AccountController>(new InjectionConstructor());
container.RegisterType<IModelContext, ModelContext>();
container.RegisterType<IModelRepository, ModelRepository>();
}
I have the following controller:
public class APIScoresController : ApiController
{
private IModelRepository _repo;
public APIScoresController(IModelRepository repo)
{
_repo = repo;
}
public IEnumerable<Result> Get()
{
return _repo.GetResults();
}
}
I have the following Model Repo:
public class ModelRepository : IModelRepository
{
ModelContext _ctx;
public ModelRepository(ModelContext ctx)
{
_ctx = ctx;
}
public IQueryable<DomainClasses.Result> GetResults()
{
return _ctx.Results;
}
}
When I try to execute the GET on the APIScoresController I get the following exception:
An error occurred when trying to create a controller of type 'APIScoresController'. Make sure that the controller has a parameterless public constructor
I would have expected unity to create the required ModelContext and ModelRepository objects. Any ideas why it's not doing this?
Problem caused by web api registration needing a different version of system.web.http. I was trying to add web api to an existing mvc5 app - bad idea! I entered a form of dll hell that I hadn't experienced since days of VB6 COM. In the end my solution was to create a new solution with a web api project then retro fit the mvc project.

MVC: Invoking overloaded constructors conditionally

I have an MVC application where I am implementing CQRS where I have seperated saving data from reading data into seperate interfaces. I am using constructor injection for injecting the concrete instances of these interfaces into the Controller. For constructor injection I am using Unity container. See below example
//The Employee controller
public class EmployeeController : Controller
{
IEmployeeRepository _Writer;
IEmployeeQuery _Reader;
//constructor injection
public EmployeeController(IEmployeeRepository writer, IEmployeeQuery reader)
{
this._Writer = writer;
this._Reader = reader;
}
//To Do: constructor injection for write operations only
public EmployeeController(IEmployeeRepository writer)
{
this._Writer = writer;
}
//To Do: constructor injection for read operations only
public EmployeeController(IEmployeeQuery reader)
{
this._Reader = reader;
}
}
//Registration of the concrete types in the unity container.
public static class Bootstrapper
{
public static void ConfigureUnityContainer()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IEmployeeRepository, EmployeeRepository>(new HttpContextLifetimeManager<IEmployeeRepository>());
container.RegisterType<IEmployeeQuery, EmployeeQueries>(new HttpContextLifetimeManager<IEmployeeQuery>());
ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container));
}
}
//The derived Controller Factory for injection dependencies in the Controller constructor
public class UnityControllerFactory : DefaultControllerFactory
{
IUnityContainer container;
public UnityControllerFactory(IUnityContainer container)
{
this.container = container;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
try
{
if (controllerType == null)
{
throw new ArgumentNullException("controllerType");
}
if (!typeof(IController).IsAssignableFrom(controllerType))
{
throw new ArgumentException(String.Format("Type requested is not a controller: {0}", controllerType.Name), "controllerType");
}
return container.Resolve(controllerType) as IController;
}
catch (Exception)
{
return null;
}
}
}
I have figured out that for any action I will either be fetching data or writing data but not both. In that case I need to invoke the controller constructors conditionally depending on which of "_Writer" or "_Reader" I need to initialize.
How can this be done ?
Looks like you have one controller where you should use two? If you never need to be able to both read and write I would consider to refactor that component towards single responsibility.
If you don't want to do that I would consider injecting a NullObject instead of not injecting that dependency at all. See this thread.
The TecX project contains an extension that mimics NInject's contextual binding. That would allow you to specify when to inject what dependency. The code can be found inside the TecX.Unity project (folder ContextualBinding). The tests that show how to use it are inside the TecX.Unity.ContextualBinding.Test project).
What about lazy loading components? You resolve both dependencies but only one that is really used is initialized.
Sample here: http://pwlodek.blogspot.com/2010/05/lazy-and-ienumerable-support-comes-to.html

ASP.NET Web API Ninject constructor injected custom filter and attributes

I'm struggling with getting a custom attribute / filter working with ninject, constructor injection on the ASP.NET Web API.
Here's a few snippets to give some context...
//controller
[ApiAuthorise]
public IEnumerable<Thing> Get()
// Attribute definition with no body
public class ApiAuthoriseAttribute : FilterAttribute {}
// Custom Filter definition
public class ApiAuthoriseFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{ throw new NotImplementedException(); }
}
//Ninject module for my API authorisation
public class ApiAuthoriseModule : NinjectModule
{
public override void Load()
{
this.BindFilter<ApiAuthoriseFilter>(FilterScope.Action, 0)
.WhenActionMethodHas<ApiAuthoriseAttribute>()
}}
//The registerServices(IKernel kernel) method in NinjectMVC3.cs
kernel.Load(new ApiAuthoriseModule());
That's literally all the code I have concerning this filter and attribute.
From what I understand I don't have to explicitly add the filter to the global filter collection as ninject takes care of that, is that correct?
If I place a constructor inside my attribute and throw an exception from within there I can see that the attribute is firing.
My suspicion is something I'm doing wrong within the Ninject side of things but after spending an afternoon reading others examples that appear to be identical to mine I'm know asking for help :)
TIA
There are different classes that you need to work with in Web API, not the standard System.Web.Mvc.FilterAttribute and System.Web.Mvc.IAuthorizationFilter that are used in normal controllers:
public class ApiAuthoriseAttribute : System.Web.Http.Filters.FilterAttribute
{
}
public class ApiAuthoriseFilter : System.Web.Http.Filters.IAuthorizationFilter
{
public System.Threading.Tasks.Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(System.Web.Http.Controllers.HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken, Func<System.Threading.Tasks.Task<HttpResponseMessage>> continuation)
{
throw new NotImplementedException();
}
public bool AllowMultiple
{
get { return false; }
}
}
Then you will obviously have to modify Ninject and the filter binding syntax (BindFilter extension method) to be able to register this new classes. Or wait for Ninject.MVC4 which will include this functionality.

Resources