How to write NUnit test for dependency injection service .net core - nunit

I have a service class with some injected services. It's dealing with my Azure storage requests. I need to write NUnit tests for that class.
I'm new to NUnit and I'm struggling with making the object of that my AzureService.cs
Below AzureService.cs. I have used some injected services
using System;
using System.Linq;
using System.Threading.Tasks;
using JohnMorris.Plugin.Image.Upload.Azure.Interfaces;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Nop.Core.Caching;
using Nop.Core.Configuration;
using Nop.Core.Domain.Media;
using Nop.Services.Logging;
namespace JohnMorris.Plugin.Image.Upload.Azure.Services
{
public class AzureService : IAzureService
{
#region Constants
private const string THUMB_EXISTS_KEY = "Nop.azure.thumb.exists-{0}";
private const string THUMBS_PATTERN_KEY = "Nop.azure.thumb";
#endregion
#region Fields
private readonly ILogger _logger;
private static CloudBlobContainer _container;
private readonly IStaticCacheManager _cacheManager;
private readonly MediaSettings _mediaSettings;
private readonly NopConfig _config;
#endregion
#region
public AzureService(IStaticCacheManager cacheManager, MediaSettings mediaSettings, NopConfig config, ILogger logger)
{
this._cacheManager = cacheManager;
this._mediaSettings = mediaSettings;
this._config = config;
this._logger = logger;
}
#endregion
#region Utilities
public string GetAzureStorageUrl()
{
return $"{_config.AzureBlobStorageEndPoint}{_config.AzureBlobStorageContainerName}";
}
public virtual async Task DeleteFileAsync(string prefix)
{
try
{
BlobContinuationToken continuationToken = null;
do
{
var resultSegment = await _container.ListBlobsSegmentedAsync(prefix, true, BlobListingDetails.All, null, continuationToken, null, null);
await Task.WhenAll(resultSegment.Results.Select(blobItem => ((CloudBlockBlob)blobItem).DeleteAsync()));
//get the continuation token.
continuationToken = resultSegment.ContinuationToken;
}
while (continuationToken != null);
_cacheManager.RemoveByPrefix(THUMBS_PATTERN_KEY);
}
catch (Exception e)
{
_logger.Error($"Azure file delete error", e);
}
}
public virtual async Task<bool> CheckFileExistsAsync(string filePath)
{
try
{
var key = string.Format(THUMB_EXISTS_KEY, filePath);
return await _cacheManager.Get(key, async () =>
{
//GetBlockBlobReference doesn't need to be async since it doesn't contact the server yet
var blockBlob = _container.GetBlockBlobReference(filePath);
return await blockBlob.ExistsAsync();
});
}
catch { return false; }
}
public virtual async Task SaveFileAsync(string filePath, string mimeType, byte[] binary)
{
try
{
var blockBlob = _container.GetBlockBlobReference(filePath);
if (!string.IsNullOrEmpty(mimeType))
blockBlob.Properties.ContentType = mimeType;
if (!string.IsNullOrEmpty(_mediaSettings.AzureCacheControlHeader))
blockBlob.Properties.CacheControl = _mediaSettings.AzureCacheControlHeader;
await blockBlob.UploadFromByteArrayAsync(binary, 0, binary.Length);
_cacheManager.RemoveByPrefix(THUMBS_PATTERN_KEY);
}
catch (Exception e)
{
_logger.Error($"Azure file upload error", e);
}
}
public virtual byte[] LoadFileFromAzure(string filePath)
{
try
{
var blob = _container.GetBlockBlobReference(filePath);
if (blob.ExistsAsync().GetAwaiter().GetResult())
{
blob.FetchAttributesAsync().GetAwaiter().GetResult();
var bytes = new byte[blob.Properties.Length];
blob.DownloadToByteArrayAsync(bytes, 0).GetAwaiter().GetResult();
return bytes;
}
}
catch (Exception)
{
}
return new byte[0];
}
#endregion
}
}
This is my test class below, I need to create new AzureService(); from my service class. But in my AzureService constructor, I'm injecting some service
using JohnMorris.Plugin.Image.Upload.Azure.Services;
using Nop.Core.Caching;
using Nop.Core.Domain.Media;
using Nop.Services.Tests;
using NUnit.Framework;
namespace JohnMorris.Plugin.Image.Upload.Azure.Test
{
public class AzureServiceTest
{
private AzureService _azureService;
[SetUp]
public void Setup()
{
_azureService = new AzureService( cacheManager, mediaSettings, config, logger);
}
[Test]
public void App_settings_has_azure_connection_details()
{
var url= _azureService.GetAzureStorageUrl();
Assert.IsNotNull(url);
Assert.IsNotEmpty(url);
}
[Test]
public void Check_File_Exists_Async_test(){
//To Do
}
[Test]
public void Save_File_Async_Test()(){
//To Do
}
[Test]
public void Load_File_From_Azure_Test(){
//To Do
}
}
}

Question is, what exactly do you want to test? If you want to test if NopConfig is properly reading values from AppSettings, then you do not have to test AzureService at all.
If you want to test that GetAzureStorageUrl method is working correctly, then you should mock your NopConfig dependency and focus on testing only AzureService methods like this:
using Moq;
using Nop.Core.Configuration;
using NUnit.Framework;
namespace NopTest
{
public class AzureService
{
private readonly NopConfig _config;
public AzureService(NopConfig config)
{
_config = config;
}
public string GetAzureStorageUrl()
{
return $"{_config.AzureBlobStorageEndPoint}{_config.AzureBlobStorageContainerName}";
}
}
[TestFixture]
public class NopTest
{
[Test]
public void GetStorageUrlTest()
{
Mock<NopConfig> nopConfigMock = new Mock<NopConfig>();
nopConfigMock.Setup(x => x.AzureBlobStorageEndPoint).Returns("https://www.example.com/");
nopConfigMock.Setup(x => x.AzureBlobStorageContainerName).Returns("containername");
AzureService azureService = new AzureService(nopConfigMock.Object);
string azureStorageUrl = azureService.GetAzureStorageUrl();
Assert.AreEqual("https://www.example.com/containername", azureStorageUrl);
}
}
}

Related

Entity Framework core + OData 8.0.1 CRUD Operations ASP.Net core 5

public class Books
{
public int Id{get;set;}
public string Name{get;set;}
}
public class BookController : ODataController
{
private readonly IBookRepository _bookRepository;
private readonly IMapper _mapper;
public BookController(IBookRepository bookRepository, IMapper mapper)
{
_bookRepository = bookRepository;
_mapper = mapper;
}
[EnableQuery]
[HttpGet]
public ActionResult Get()
{
try
{
IQueryable<BookDto> res = _bookRepository.Books().ProjectTo<BookDto>(_mapper.ConfigurationProvider);
if (res.Count() == 0)
return NotFound();
return Ok(res);
}
catch(Exception)
{
return StatusCode(StatusCodes.Status500InternalServerError, "Unable to get Book");
}
}
[HttpGet("{Id}")]
public async Task<ActionResult<Book>> GetBookById(string Id)
{
var book = await _bookRepository.GetBookById(Id);
if (book == null)
return NotFound();
return book;
}
[HttpPost]
public async Task<ActionResult<Book>> Post([fr]CreateBookDto createBookDto)
{
try
{
if (createBookDto == null)
return BadRequest();
Book book = _mapper.Map<Book>(createBookDto);
var result = await _bookRepository.Book(book);
return CreatedAtAction(nameof(GetBookById), new { id = book.UserId }, result);
}
catch (Exception)
{
return StatusCode(StatusCodes.Status500InternalServerError,"Failed to save Book information");
}
}
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
var connectionStr = Configuration.GetConnectionString("ConnectionString");
services.AddControllers();
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
services.AddControllers().AddOData(opt => opt.AddRouteComponents("api",GetEdModel()).Select().Filter().Count().Expand());
services.AddDbContext<AppDbContext>(options => options.UseMySql(connectionStr,ServerVersion.AutoDetect(connectionStr)));
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Book_api", Version = "v1" });
});
services.AddScoped<IBookRepository, BookRepository>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Book_api v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
private IEdmModel GetEdModel()
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<User>("User");
builder.EntitySet<BookDto>("Book");
return builder.GetEdmModel();
}
}
Hi Guys. I'm trying to implement OData on my ASP.Net Core 5 API. I can retrieve books using the Get. But I am struggling to do a POST. When I try to use the POST on Postman, the CreateBookDto properties all return null. I tried to add [FromBody] that does not work also. The only time this seems to work is when I decorate the controller with [ApiController] but that in turn affects my GET. I'm not sure what to do anymore.

Xamarin forms - Cannot get object from REST API to xaml page

I am developing an Xamarin.Forms app in VS 2019. My REST API is hosted on GoDaddy.
When I call the api I get back my json converted object fine in my viewmodel. But the object is null
from my xaml page. See this code:
public class NewOrderViewModel : BaseViewModel
{
public NewOrderDetails NewOrderDetails { get; set; }
public ICommand OkCommand { get; private set;}
public ICommand CancelCommand { get; private set; }
readonly IPageService _pageService;
public NewOrderViewModel(IPageService pageService, int custId)
{
_pageService = pageService;
OkCommand = new Command(NewOrder);
CancelCommand = new Command(CancelOrder);
NewOrderDetails = new NewOrderDetails();
LoadNewOrderDetails(custId);
}
private async void LoadNewOrderDetails(int custId)
{
using (var client = new HttpClient(new System.Net.Http.HttpClientHandler()))
{
var response = await client.GetStringAsync("http://api.lates.com.au/api/Customers/" + custId.ToString());
var customer = JsonConvert.DeserializeObject<Customer>(response);
await _pageService.DisplayAlert("Value", customer.CustomerName, "OK"); //This confirms the correct customer is returned.
NewOrderDetails.CustomerName = customer.CustomerName;
foreach (var cd in customer.CustomerDepartments)
{
NewOrderDetails.CustomerDepartments.Add(cd);
}
NewOrderDetails.OrderDate = DateTime.Today;
NewOrderDetails.DeliveryDate = DateTime.Today;
NewOrderDetails.CustomerId = custId;
}
}
private void NewOrder()
{
_pageService.PopAsync();
_pageService.PushModalAsync(new CustomerOrder());
}
private void CancelOrder()
{
_pageService.PopAsync();
}
}
public partial class NewOrder : ContentPage
{
public NewOrder()
{
InitializeComponent();
imgAddIcon.Source = FileImageSource.FromFile("AddDocument64By64.png");
}
protected override void OnAppearing()
{
BindingContext = new NewOrderViewModel(new PageService(), 1);
//If i put a break point here the NewOrderDetails property of NewOrderViewModel is null - WHY???
}
}
It seems to be something to do with asynchronous timing. Let me know if you need more info.
Malcolm
If i put a break point here the NewOrderDetails property of
NewOrderViewModel is null - WHY???
At that time your break point hit, the data in NewOrderDetails has not be set because the httpRequest is still requesting and you have to await the request finish to get the data from Api.
To solve your problem, you have to implement INotifyPropertyChanged in both NewOrderDetails and NewOrderViewModel to notify the View update value after you get the data from Api. I will give you some code snippets:
In NewOrderDetails :
public class NewOrderDetails : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public NewOrderDetails()
{
}
public string CustomerName
{
set
{
if (customerName != value)
{
customerName = value;
OnPropertyChanged("CustomerName");
}
}
get
{
return customerName;
}
}
string customerName { get; set; }
}
In NewOrderViewModel :
public class NewOrderViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public NewOrderDetails NewOrderDetaila
{
set
{
if (newOrderDetails != value)
{
newOrderDetails = value;
OnPropertyChanged("NewOrderDetaila");
}
}
get
{
return newOrderDetails;
}
}
NewOrderDetails newOrderDetails { get; set; }
public NewOrderViewModel( int custId)
{
NewOrderDetaila = new NewOrderDetails();
LoadNewOrderDetails(custId);
}
private async void LoadNewOrderDetails(int custId)
{
//...
NewOrderDetaila.CustomerName = "133";
//...
}
}
And in Xaml binding:
<Label Text="{Binding NewOrderDetaila.CustomerName}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
Try and let me know if it works for you.
One problem in your code is here:
using (var client = new HttpClient(new System.Net.Http.HttpClientHandler()))
{
var response = await client.GetStringAsync("http://api.lates.com.au/api/Customers/" + custId.ToString());
var customer = JsonConvert.DeserializeObject<Customer>(response);
await _pageService.DisplayAlert("Value", customer.CustomerName, "OK"); //This confirms the correct customer is returned.
NewOrderDetails.CustomerName = customer.CustomerName;
foreach (var cd in customer.CustomerDepartments)
{
NewOrderDetails.CustomerDepartments.Add(cd);
}
NewOrderDetails.OrderDate = DateTime.Today;
NewOrderDetails.DeliveryDate = DateTime.Today;
NewOrderDetails.CustomerId = custId;
}
HttpClient should be defined as static class, and reused during your application lifetime. Disposing and recreating HttpClient leads to socket errors. Your code is causing multiple requests. I suggest also move this method to Task, that returns the object.
Example method:
internal class SendData
{
private static HttpClient client = new HttpClient();
internal static async Task<string> MakeServerRequest(string url, string content)
{
try
{
var request = new StringContent(content, Encoding.UTF8, "application/json");
var result = await client.PostAsync(url, request);
var response = await result.Content.ReadAsStringAsync();
return response;
}
catch (Exception ex)
{
YOUR ADDITIONAL LOGIC HERE
return null;
}
}
}
This will return JSON string that you can serialize to object, and do whatever your app requires.

Calling Stored Procedure in Entity Framework using Aspnet boilerplate

I am using aspnetboilerplate template
i have a student service class. i am getting a student profile List from stored procedure. how can i call a stored procedure in aspnetboilerplate template
public class StudentRepository : TabonoRepositoryBase<User, long>
{
private readonly IActiveTransactionProvider _transactionProvider;
public StudentRepository(IDbContextProvider<TabonoDbContext> dbContextProvider, IActiveTransactionProvider transactionProvider)
: base(dbContextProvider)
{
_transactionProvider = transactionProvider;
}
//TODO: Make async!
public async Task<int> GetProfileCompletePercentage(int studentid)
{
EnsureConnectionOpen();
using (var command = CreateCommand("Sp_GetStudentprofilepercentage", CommandType.StoredProcedure, new SqlParameter("StudentId", studentid)))
{
using (var dataReader = await command.ExecuteReaderAsync())
{
while (dataReader.Read())
{
return Convert.ToInt16(dataReader["TotalPer"].ToString());
}
return 0;
}
}
}
private DbCommand CreateCommand(string commandText, CommandType commandType, params SqlParameter[] parameters)
{
var command = Context.Database.GetDbConnection().CreateCommand();
command.CommandText = commandText;
command.CommandType = commandType;
command.Transaction = GetActiveTransaction();
foreach (var parameter in parameters)
{
command.Parameters.Add(parameter);
}
return command;
}
private void EnsureConnectionOpen()
{
var connection = Context.Database.GetDbConnection();
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
}
private DbTransaction GetActiveTransaction()
{
return (DbTransaction)_transactionProvider.GetActiveTransaction(new ActiveTransactionProviderArgs
{
{"ContextType", typeof(TabonoDbContext) },
{"MultiTenancySide", MultiTenancySide }
});
}
}
And this is the service class
public class StudentService : AsyncCrudAppService<StudentCore, StudentDto, int, PagedResultRequestDto, StudentCreateDto, StudentUpdateDto>, IStudentService
{
public readonly IRepository<StudentCore> _studentRepository;
private readonly UserManager _userManager;
private readonly IStudentService _studentservice;
public StudentService(IRepository<StudentCore> repository, UserManager um, IStudentService studentservice) : base(repository)
{
_studentRepository = repository;
_userManager = um;
_studentservice = studentservice;
}
public Task GetProfileCompletePercentage(int studentid)
{
return _studentservice.GetProfileCompletePercentage(studentid);
}
}
Create an interface:
public interface IStudentRepository : IRepository<StudentCore>
{
Task<int> GetProfileCompletePercentage(int studentid);
}
Implement the interface:
public class StudentRepository : TabonoRepositoryBase<StudentCore>, IStudentRepository
{
// ...
}
Inject the interface and call the method:
public class StudentService : ...
{
private readonly IStudentRepository _studentRepository;
public StudentService(IStudentRepository repository) : base(repository)
{
_studentRepository = repository;
}
public Task GetProfileCompletePercentage(int studentid)
{
return _studentRepository.GetProfileCompletePercentage(studentid);
}
}
Note: StudentService must not inject IStudentService in constructor → infinite recursion!
For reference: https://www.codeproject.com/Articles/1199648/Using-Stored-Procedure-User-Defined-Function-and-V

Unable to inject DBContext into my Web API 2 Controller with Unity

I've been at it for days, but I can't get Unity to inject anything with RegisterType<> into my Controller. I'm using Web Api 2, in Visual Studio 2015, with Unity 4. Whenever I try to inject IUnitOfWork or IRFContext, I get "message": "An error occurred when trying to create a controller of type 'ClPlayersController'. Make sure that the controller has a parameterless public constructor.".
I'm using the Unity.AspNet.WebApi to bootstrapp into WebApi. Below is my UnityWebApiActivator
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(mycompany.project.api.UnityWebApiActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(mycompany.project.api.UnityWebApiActivator), "Shutdown")]
namespace mycompany.project.api
{
public static class UnityWebApiActivator
{
public static void Start()
{
var resolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
}
I'm using a Start.cs due to Owin.
[assembly: OwinStartup(typeof(mycompany.project.api.Startup))]
namespace mycompany.project.api
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
ConfigureOAuth(app);
config.DependencyResolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider(),
RefreshTokenProvider = new SimpleRefreshTokenProvider()
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
}
My WebApiConfig.cs is below:
namespace mycompany.project.api
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
log4net.Config.XmlConfigurator.Configure();
config.MapHttpAttributeRoutes();
config.EnableSystemDiagnosticsTracing();
config.Services.Add(typeof(IExceptionLogger),
new SimpleExceptionLogger(new LogManagerAdapter()));
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
}
}
}
My UnityConfig.cs is below
namespace mycompany.project.api
{
public class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
#endregion
public static void RegisterTypes(IUnityContainer container)
{
var config = new MapperConfiguration(cfg =>
{
//AutoMapper bindings
});
container.RegisterInstance<IMapper>(config.CreateMapper());
container.RegisterType<IRFContext, RFContext>(new PerThreadLifetimeManager());
container.RegisterType<IUnitOfWork, UnitOfWork>();
XmlConfigurator.Configure();
var logManager = new LogManagerAdapter();
container.RegisterInstance<ILogManager>(logManager);
}
}
}
All that I have in my Global.asax is below:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Error()
{
var exception = Server.GetLastError();
if (exception != null)
{
var log = new LogManagerAdapter().GetLog(typeof(WebApiApplication));
log.Error("Unhandled exception.", exception);
}
}
}
If my Controller is like this, it works fine:
public class ClPlayersController : ApiController
{
private readonly IMapper mapper;
public ClPlayersController(IMapper _mapper, IUnityContainer container)
{
mapper = _mapper;
}
But placing IUnitOfWork, like below, or the IRFContext, I get the error:
private readonly IMapper mapper;
private readonly IUnitOfWork unitOfWork;
public ClPlayersController(IMapper _mapper, IUnityContainer container, IUnitOfWork _unitOfWork)
{
mapper = _mapper;
unitOfWork = _unitOfWork;
}
I can't find, for the life of me, what I'm doing wrong. If I loop through the container.Registrations on the constructor, I find the mappings, but they refuse to get injected. Any hints?
EDIT
Below is the code for UnitOfWork and RFContext
namespace mycompany.project.data.configuracao
{
public class UnitOfWork : IUnitOfWork
{
private readonly IRFContext _rfContext;
private bool _disposed = false;
public UnitOfWork(IRFContext rfContext)
{
_rfContext = rfContext;
}
public void Commit()
{
if (_disposed)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
_rfContext.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing && _rfContext != null)
{
_rfContext.Dispose();
}
_disposed = true;
}
}
}
and
namespace mycompany.project.data.configuracao
{
public interface IUnitOfWork : IDisposable
{
void Commit();
}
}
and RFContext is a basic POCO generated DBContext
namespace mycompany.project.data.configuracao
{
using System.Linq;
public class RFContext : System.Data.Entity.DbContext, IRFContext
{
public System.Data.Entity.DbSet<ClGrupoEconomico> ClGrupoEconomicoes { get; set; }
//all my DbSets
public System.Data.Entity.DbSet<SpTipoLog> SpTipoLogs { get; set; }
static RFContext()
{
System.Data.Entity.Database.SetInitializer<RFContext>(null);
}
public RFContext()
: base("Name=RFContext")
{
}
public RFContext(string connectionString)
: base(connectionString)
{
}
public RFContext(string connectionString, System.Data.Entity.Infrastructure.DbCompiledModel model)
: base(connectionString, model)
{
}
public RFContext(System.Data.Common.DbConnection existingConnection, bool contextOwnsConnection)
: base(existingConnection, contextOwnsConnection)
{
}
public RFContext(System.Data.Common.DbConnection existingConnection, System.Data.Entity.Infrastructure.DbCompiledModel model, bool contextOwnsConnection)
: base(existingConnection, model, contextOwnsConnection)
{
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new ClGrupoEconomicoConfiguration());
//all my Configuration classes
modelBuilder.Configurations.Add(new SpTipoLogConfiguration());
}
public static System.Data.Entity.DbModelBuilder CreateModel(System.Data.Entity.DbModelBuilder modelBuilder, string schema)
{
modelBuilder.Configurations.Add(new ClGrupoEconomicoConfiguration(schema));
//all my configuration classes
modelBuilder.Configurations.Add(new SpTipoLogConfiguration(schema));
return modelBuilder;
}
}
}
Unfortunately the exception you are seeing can occur for several reasons. One of them is when Unity cannot resolve one or more of your injections.
An error occurred when trying to create a controller of type
'FooController'. Make sure that the controller has a parameterless
public constructor.
So, based on the information in your question your setup is apparently correct, since IMapper can be injected. Therefore I guess that UnitOfWork and RFContext have dependencies that Unity cannot resolve. Maybe a repository?
UPDATE:
The problem here is that your RFContext has several constructors.
https://msdn.microsoft.com/en-us/library/cc440940.aspx#cnstrctinj_multiple
When a target class contains more than one constructor with the same
number of parameters, you must apply the InjectionConstructor
attribute to the constructor that the Unity container will use to
indicate which constructor the container should use. As with automatic
constructor injection, you can specify the constructor parameters as a
concrete type, or you can specify an interface or base class for which
the Unity container contains a registered mapping.
In this case Unity doesn't know how to resolve your RFContext, and will try to use the constructor with the most parameters. You can solve it by using
container.RegisterType<IRFContext, RFContext>(new InjectionConstructor());

Troubles with dependency injection

I am working on an ASP.NET WebAPI using OWIN. To manage the instances of DBContext (Entity Framework), I try to use Ninject. However, when I call a controller, the programm returns an error:
The controller cannot be created, missing constructor.
Could you tell me what is going wrong here?
My Controller Class:
public class Testcontroller
{
private IApplicationDbContext _context;
public Testcontroller(IApplicationDbContext context)
{
_context = context;
}
}
This is the Ninject-File:
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
kernel.Bind<IApplicationDbContext>().To<ApplicationDbContext>();
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
private static void RegisterServices(IKernel kernel)
{
}
}
Ninject Dependency Scope:
public class NinjectDependencyScope : IDependencyScope
{
IResolutionRoot resolver;
public NinjectDependencyScope(IResolutionRoot resolver)
{
this.resolver = resolver;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.TryGet(serviceType);
}
public System.Collections.Generic.IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.GetAll(serviceType);
}
public void Dispose()
{
IDisposable disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
}
// This class is the resolver, but it is also the global scope
// so we derive from NinjectScope.
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
IKernel kernel;
public NinjectDependencyResolver(IKernel kernel) : base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
The Entity Framework DbContext-Class:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
}
public virtual DbSet<Models.Team> Teams { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
public interface IApplicationDbContext
{
DbSet<Models.Team> Teams { get; set; }
int SaveChanges();
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
}
I tried to follow this tutorial: http://www.peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api
What have I done wrong here?
Thanks in advance!
Unless there was a serious omission in you controller code, your controller is not inheriting from ApiController, as is expected with Web Api
public class TestController : ApiController {
private IApplicationDbContext _context;
public Testcontroller(IApplicationDbContext context) {
_context = context;
}
}
UPDATE
I tried to set up everything from scratch using this: http://www.alexzaitzev.pro/2014/11/webapi2-owin-and-ninject.html
For some reason, it now works out perfectly fine.
Thank you for your support!