Ninject-ing Mehdime.Entity.IDbContextScopeFactory failing - asp.net-web-api2

I am trying make use of Mehdi El Gueddari's DBContextScope solution and DI it into my WebAPI2 Controller as follows:
NinjectConfigurator.cs:
container.Bind<IUserProfileInquiryProcessor>().To<UserProfileInquiryProcessor>().InRequestScope();
container.Bind<IDbContextScopeFactory>().To<DbContextScopeFactory>().InSingletonScope();
UserProfileController.cs:
public UserProfileController(
IUserProfileInquiryProcessor userProfileInquiryProcessor,
IDbContextScopeFactory dbContextScopeFactory)
{
_dbContextScopeFactory = dbContextScopeFactory;
_userProfileInquiryProcessor = userProfileInquiryProcessor;
}
However, Ninject appears to be failing to inject IDbContextScopeFactory and returns with the following exception:
An error occurred when trying to create a controller of type 'UserProfileController'. Make sure that the controller has a parameterless public constructor.
I know it is IDbContextScopeFactory that is failing to resolve and the controller is created if I omit that parameter (only) from the constructor.
Can anyone advise what I am doing wrong or what I should try? Thanks.

Related

Unable to resolve service for type 'System.String' while attempting to activate in .net core

I have a factory class and it has a constructor where dependency injection is implemented. When trying to register the factory method in program.cs file I get the below error when running the application. "Unable to resolve service for type 'System.String' while attempting to activate 'Factory".
public class Factory : IFactory
{
private readonly A _a;
private readonly string _test;
public Factory(A a, string sample)
{
_a= a;
_test= string.IsNullOrEmpty(sample) ? string.Empty : Path.GetFullPath(sample);
}
private string Create(long id)
{
var b = _test.make(id);
return b;
}
}
In program.cs file how can we register this string element _test? Can anyone help!
It is because your Factory constructor is not parameter-less, and when the service provider tries to instantiate the Factory, it has no value to pass for the "sample" variable.
There are two possible solutions to this:
1- Changing the design of your factory, and passing the "sample" as a variable to Create method instead of the constructor.
OR
2- Registering the factory like this:
services.AddSingleton(s => new Factory(s.GetService<A>(), "desired string"));
Btw, I don't know what is the use case that you have for implementing this factory class, but it doesn't seem the right way of implementing it. I suggest you take a look at this beforehand:
Factory Design Pattern

Inject httpcontext into custom attribute outside controller in .net core

I need to inject httpcontext into custom attribute that is used outside the controller. I found several solutions how to do it in controller, but my case is little tricky. Now I have following code in my PermissionController
[PermissionFilter(PermissionEnum.Permission, AccessLevelEnum.Create)] <-- it works perfectly
[HttpPost("users/{userId}")]
public async Task<IActionResult>
AssignPermissionToUser([FromBody] List<PermissionToVM> permissions, int userId)
{
await _permissionService.Assign(permissions); <-- .Assign() extension
//code goes here
}
In the method above there is a call of extension method .Assign. This method code is available below.
//[SecondPermissionFilter(PermissionEnum.Permission,
AccessLevelEnum.Create)] <-- here I check permissions but don't
know how to inject the httpcontext
public async Task Assign(List<PermissionToVM> permissions)
{
//code goes here
}
As mentioned in many websites I visited f.e. here https://dotnetcoretutorials.com/2017/01/05/accessing-httpcontext-asp-net-core/ injecting of httpcontext outside the controller can be done using IHttpContextAccessor. The problem is that I don't know how to use it without passing it into constructor. My custom attribute should be called as decorator [SecondPermissionFilter(PermissionEnum.Permission, AccessLevelEnum.Create)] when only permission settings should be passed, so there is no any reference to httpcontextaccessor.
Is this even possible? If not, there is maybe another way to do this?
EDIT: Here is the code of SecondPermissionFilter class:
public sealed class SecondPermissionFilterAttribute : Attribute
{
private readonly PermissionEnum _requestedPermission;
private readonly IEnumerable<AccessLevelEnum> _accessLevelCollection;
private readonly IHttpContextAccessor _contextAccessor; //<-- how to inject?
public PermissionFilterAttribute(PermissionEnum requestedPermission, params AccessLevelEnum[] accessLevelCollection)
{
_requestedPermission = requestedPermission;
_accessLevelCollection = accessLevelCollection;
}
}
What you are after is something called Property Injection. As per the official docs this is not something that is supported out of the box by the .NET Core DI Container.
You can however use a third party library such as Ninject or Autofac - both of which are available via NuGet.
In my opinion the Ninject syntax is nicer, however as noted in this answer, and this answer property injection itself is considered bad practice. So if possible I would try to avoid it.
So you should instead use one of the three methods specified by the filter documentation, this answer breaks things down a bit more.
Edit
This answer deals specificically with Attribute injection, the second answer looks to achieve this without external dependencies.

Facing issue when trying to fake helper function

I am using Nunit and FakeItEasy for my MVC Controller functions.
My Test Code:
[Test]
public async Task Search_Success()
{
if (!isFakeInitialized)
InitializeFake();
url = "/N/UserSvc/v1/Types?skip=0&take=" + Constants.MaxSearchRowNumber;
Types= A.CollectionOfFake<Type>(3);
List<Type> found=new List<Type>(Types);
A.CallTo(() => nFake.GetDataAsync<IEnumerable<Type>>(fakeHttpSession, url)).Returns(Types);
var fakeHelper = A.Fake<helperFunctions>();
A.CallTo(() => FakeHelper.GetAvailableTypes(fakeHttpSession, found, true)).Returns(foundTypes);
//Act
var actionResult = await myController.SearchView();
var viewResult = actionResult as ViewResult;
//Assert
Assert.IsNotNull(viewResult);
Assert.AreEqual("Search", viewResult.ViewName);
}
I am getting error at
A.CallTo(() => nFakeHelper.GetAvailableTypes(fakeHttpSession, found, true)).Returns(foundTypes);
Error: cannot convert lambda expression to type object because it is not a delegate type.
Here is the helper function Code:
public List GetAvailableTypes(Session session,List allTypes,bool includeAllType)
{
List results = new List();
return results;
}
How can i overcome the error.
If nothing else, your A.CallTo should fail because GetAvailableLicenseTypes isn't virtual. I'm a little surprised at the error message, though.
I've tried to reproduce, but had to trim things down quite a bit and fill in missing code, and ended up getting
The current proxy generator can not intercept the specified method for the following reason:
- Non virtual methods can not be intercepted.
Are you able to include more information, starting with the full error, including stack trace?
var nmsFakeHelper = A.Fake<NMCHelperFunctions>();
A.CallTo(() => nmsFakeHelper.GetAvailableLicenseTypes(fakeHttpSession, foundLicense, true)).Returns(foundLicensTypes);
These two lines are your issue.
The first line declares nmsFakeHelper as a fake of concrete type NMCHelperFunctions.
The second line then defines the behaviour of the fake when it's GetAvailableLicenseTypes method is called.
In the background, FakeItEasy decides what type of fake it should use (mock, stub, etc.). If the type you are asking a fake of is concrete you get a stub. However, if you want to be able to define behaviour (define return values or validate that methods were called etc.) you need a mock instead of a stub.
To get FakeItEasy to decide to return a mock instead of a stub, you need to give it an interface type instead. This is because a mock needs to be able to intercept the method calls but in .NET, methods can only be intercepted if they are virtual calls. This happens when the type you are using is an interface, but cannot happen when the type you are using is a concrete type.
So to get around this problem, you should add an interface to the NMCHelperFunctions type that includes (at the very least) the GetAvailableLicenseTypes method (as well as any other methods you may).
This means that your first line will change to the following (assuming you name your interface iNMCHelperFunctions):
var nmsFakeHelper = A.Fake<iNMCHelperFunctions>();
Your second line would remain unchanged, and your test code should now work.
You may have to refactor your application code to use the interface type instead of the concrete type. There is some benefit from doing this because it allows your components to be swappable so it's easier to add or change behaviour in the future by writing a new class that adheres to the same interface and switching to that.

How to troubleshooting Construction Injection using Ninject

I am having problem with construction injection fail.
When I call Restful API, the service return the message "An error occurred when trying to create a controller of type 'TasksController'. Make sure that the controller has a parameterless public constructor."
The cause of this issue is the Web API Controller can't construct the class because of wrong parameter in the constructor.
This is Ninject Configuration
container.Bind<IAddTaskQueryProcessor>().To<AddTaskQueryProcessor>().InRequestScope();
container.Bind<ITaskByIdQueryProcessor>().To<TaskByIdQueryProcessor>().InRequestScope();
container.Bind<IPagedDataRequestFactory>().To<PagedDataRequestFactory>().InSingletonScope();
container.Bind<IAllTasksInquiryProcessor>().To<AllTasksInquiryProcessor>().InRequestScope();
This is a constructor of a class of a Controller. the parameters are injected when calling the constructor.
public TasksController(IAddTaskMaintenanceProcessor addTaskMaintenanceProcessor, ITaskByIdInquiryProcessor taskByIdInquiryProcessor,
IUpdateTaskMaintenanceProcessor updateTaskMaintenanceProcessor,
IPagedDataRequestFactory pagedDataRequestFactory,
IAllTasksInquiryProcessor allTasksInquiryProcessor)
{
_addTaskMaintenanceProcessor = addTaskMaintenanceProcessor;
_taskByIdInquiryProcessor = taskByIdInquiryProcessor;
_updateTaskMaintenanceProcessor = updateTaskMaintenanceProcessor;
_pagedDataRequestFactory = pagedDataRequestFactory;
_allTasksInquiryProcessor = allTasksInquiryProcessor;
}
[Environment]
ASP.NET Web API 2.1
NInject 3.2.2
How to check which parameter in a constructor is wrong?
I solved this problem. the parameters in the constructor are injected correctly. but a parameter IAllTaskQueryProcess in AllTaskInqueryProcess's constructor is not injected. so that ASP.NET engine can't invoke the controller class
public AllTasksInquiryProcessor(IAllTasksQueryProcessor queryProcessor, IAutoMapper autoMapper)
{
_queryProcessor = queryProcessor;
_autoMapper = autoMapper;
}

MuleEventContext with annotation

I want to avoid using the Callable interface in a Mule component, instead of this i want to use annotations based coding.
I am using the following code but getting an error.
How can i use the annotation based approach?
public Object processEvent(#Lookup MuleEventContext eventContext) throws Exception {
System.out.println("eventContext: " + eventContext.getMessage().getPayload());
return "GOT IT";
}
From the documentation:
The Lookup annotation is used to inject objects from the Mule registry
The MuleEventContext is not a registry object but a dynamic one, so this can not work.
What do you need the MuleEventContext for?