Katana not finding start up method using reflection - reflection

I am working through Scott Allen's MVC 5 Fundamentals course on Pluralsight
The following code should work , but when I browse to localhost:8080 I get a blank page
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Owin.Hosting;
using Owin;
namespace ConsoleApplication1
{
using AppFunc = Func<IDictionary<string, object>, Task>;
class Program
{
static void Main(string[] args)
{
string uri = "http://localhost:8080";
using (WebApp.Start<Startup>(uri)) // Katana Please start, using the configuration from the Startup class and listening on the port given by the uri
{
Console.WriteLine("Started!");
Console.ReadKey();
Console.WriteLine("Stopping!");
}
}
}
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Use<HelloWorldComponent>();
}
}
public class HelloWorldComponent
{
AppFunc _next;
public HelloWorldComponent(AppFunc next)
{
_next = next;
}
// Katana uses reflection to find this Invoke function that matches the AppFunc signature
public Task Invoke(IDictionary<string, object> environment)
{
var response = environment["owin.ResonseBody"] as Stream;
using (var writer = new StreamWriter(response))
{
return writer.WriteAsync("Hello");
}
}
}
}
How do I get it working?

Everything is setup correctly, there is just a small typo in fetching the response object:
var response = environment["owin.ResponseBody"] as Stream;
using (var writer = new StreamWriter(response))
{
return writer.WriteAsync("Hello");
}
Notice the "p" in "ResponseBody"!

Related

Swagger UI and Swagger Doc does not generate query string. .NET 6 Web API with Minimal API, Mediatr, and Swashbuckle

I have build a Web API application using .NET 6, Mediatr, and Swashbuckle ASPNetCore. I am using nTier structure, so there is more than one project for my solutions with my Web API project having reference to a class library project that consist business logic.
The problem is, swagger-ui wont generate query string parameter to be shown on browser while everything else is normal. And another interesting part is, when using Postman, you can pass the query string key and value and it works like a charm.
Here is my request body model from class library project:
using MediatR;
using Microsoft.AspNetCore.Http;
using System.Reflection;
namespace Rest.API.Application
{
public class FindRequest : IRequest<FindResponse>
{
public string firstName { get; init; }
public string lastName { get; set; }
public static ValueTask<FindRequest> BindAsync(HttpContext context, ParameterInfo parameter)
{
FindRequest result = new()
{
firstName = context.Request.Query["firstName"],
lastName = context.Request.Query["lastName"]
};
return ValueTask.FromResult(result);
}
}
}
Here is the Endpoint class from Web API project:
using MediatR;
using Rest.API.Application;
namespace Rest.API.Core
{
public interface IEndpoint
{
void ConfigureApplication(WebApplication app);
}
public class Endpoint : IEndpoint
{
public void ConfigureApplication(WebApplication app)
{
app.MapGet("employee/{id}", async (IMediator mediator, string id) => await mediator.Send(new GetRequest(id)));
app.MapGet("employee", async (IMediator mediator, FindRequest request) => await mediator.Send(request));
}
}
}
My endpoint extension class to wrap all endpoint so I can easily register all endpoint to Program.cs:
using Microsoft.OpenApi.Models;
using System.Reflection;
namespace Rest.API.Core
{
public static class EndpointExtension
{
public static void AddEndpoint(this IServiceCollection service, params Type[] types)
{
var endpoints = new List<IEndpoint>();
foreach (var type in types)
{
endpoints.AddRange(type.Assembly.ExportedTypes
.Where(x => typeof(IEndpoint).IsAssignableFrom(x)
&& !x.IsInterface
&& !x.IsAbstract)
.Select(Activator.CreateInstance)
.Cast<IEndpoint>());
}
service.AddSingleton(endpoints as IReadOnlyCollection<IEndpoint>);
}
public static void UseEndpoint(this WebApplication app)
{
var endpoints = app.Services.GetRequiredService<IReadOnlyCollection<IEndpoint>>();
foreach (var endpoint in endpoints)
{
endpoint.ConfigureApplication(app);
}
}
}
public static class SwaggerExtension
{
public static void ConfigureSwagger(this IServiceCollection services)
{
services.AddEndpointsApiExplorer();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("dev", new OpenApiInfo
{
Title = "Sample Web API Core",
Version = $"DEV-{Environment.Version.Major}.{Environment.Version.Minor}.{DateTime.Now:yyyyMMddHHmmss}",
Description = "Sample Web API"
});
string xmlDocFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
string xmlDocPath = Path.Combine(AppContext.BaseDirectory, xmlDocFile);
c.IncludeXmlComments(xmlDocPath);
});
}
public static void UseSwaggerApp(this WebApplication app)
{
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(x =>
{
x.SwaggerEndpoint("/swagger/dev/swagger.json", "Rest.API.Core");
x.RoutePrefix = "swagger";
x.DocumentTitle = "Sample Web API";
});
}
}
}
public static class CORSExtension
{
public static void ConfigureCORS(this IServiceCollection services)
{
services.AddCors(options =>
{
//NOT FOR PRODUCTION
options.AddPolicy("AllowAnyOrigin", builder =>
{
builder.AllowAnyOrigin();
builder.AllowAnyMethod();
builder.AllowAnyHeader();
});
});
}
}
}
Finally, my Program.cs:
using MediatR;
using Rest.API.Application;
using Rest.API.Core;
using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
#region SERVICES
builder.Services.ConfigureCORS();
builder.Services.AddMediatR(typeof(GetHandler).GetTypeInfo().Assembly);
builder.Services.ConfigureSwagger();
builder.Services.AddEndpoint(typeof(IEndpoint)); //Register all endpoint(controller) that implementing IEndpoint.
#endregion
var app = builder.Build();
#region PIPELINE
app.UseSwaggerApp();
app.UseEndpoint();
app.UseCors("AllowAnyOrigin");
app.UseHttpsRedirection();
#endregion
app.Run();
For the complete sample project you can get from here.
So, any idea how show the query string model on swagger-ui?
Thank You.
There's no way for your model to express how it's being bound from the request. This is a gap being resolved in .NET 7, see https://github.com/dotnet/aspnetcore/issues/40646.
To accomplish this with .NET 6, you can https://www.nuget.org/packages/MinimalApis.Extensions

Why is the presence of middleware preventing execution of an endpoint?

I am a beginner at ASP.Net. Here is my startup.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;
using CAPSWebServer.CapsDataModels;
namespace CAPSWebServer
{
public class Startup
{
public IConfiguration Configuration { get; set; }
public Startup(IConfiguration config)
{
Configuration = config;
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CapsDataContext>(opts =>
{
opts.UseNpgsql(Configuration["ConnectionStrings:CAPSConnection"]);
opts.EnableSensitiveDataLogging(true);
});
}
// 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.UseStaticFiles();
app.UseRouting();
app.UseMiddleware<TestMiddleware>();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
}
}
And here is my TestMiddleware class:
using Microsoft.AspNetCore.Http;
using System.Linq;
using System.Threading.Tasks;
using CAPSWebServer.CapsDataModels;
namespace CAPSWebServer
{
public class TestMiddleware
{
private RequestDelegate nextDelegate;
public TestMiddleware(RequestDelegate next)
{
nextDelegate = next;
}
public async Task Invoke(HttpContext context, CapsDataContext dataContext)
{
if (context.Request.Path == "/test")
{
await context.Response.WriteAsync($"There are {dataContext.Charges.Count()} charges.\n");
await context.Response.WriteAsync($"There are {dataContext.Inventories.Count()} coils.\n");
}
}
}
}
This application is configured to listen on port 500 of my computer. When I run localhost:5000/test, I get the expected report of how many charges and coils I have in my database. But when I run localhost:5000 by itself, I get nothing. I think I should be getting "Hello, world". If I comment out out the call to UseMiddleware(), I get "Hello, world". Why does the middleware block the endpoint?
I am using Visual Studio 2019.
You need to call the
nextDelegate();
So that the next middleware down the line is executed.
The reason it works when the URL contains "/test" is because you are writing directly into the response stream.

EF Core DBContext inside Net Core Worker Windows service

what I am trying to achieve is code a simple .net core background worker (.net core 3.1) where I write data to a SQL Server database (through EF Core 3.1) while this worker is running as a windows service.
When I run the below code from Visual Studio 2019, everything works, but when I publish (Target win-x64) and register the .exe as a service on my win10 machine, I get the following Exception:
Microsoft.Data.SqlClient is not supported on this platform.
Any thoughts on what is causing this and how to fix it?
Program.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Soteria.Common.Database;
namespace Soteria.Service
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
var host = Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
var optionsBuilder = new DbContextOptionsBuilder<SoteriaDbContext>();
optionsBuilder.UseSqlServer("Server=.\\SQLEXPRESS;Database=Soteria;Trusted_Connection=True;");//,
services.AddScoped<SoteriaDbContext>(s => new SoteriaDbContext(optionsBuilder.Options));
services.AddHostedService<Worker>();
});
return host;
}
}
}
Worker.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Soteria.Common.Database;
using Soteria.Common.Messaging;
using Soteria.Common.Models;
namespace Soteria.Service
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IServiceScopeFactory _serviceScopeFactory;
public Worker(ILogger<Worker> logger, IServiceScopeFactory serviceScopeFactory)
{
_logger = logger;
_serviceScopeFactory = serviceScopeFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using var scope = _serviceScopeFactory.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<SoteriaDbContext>();
dbContext.Tests.Add(new Test() {Date = DateTime.Now});
dbContext.SaveChanges();
await Task.Delay(1000, stoppingToken);
}
}
}
}
SoteriaDbContext.cs
using Microsoft.EntityFrameworkCore;
using Soteria.Common.Models;
namespace Soteria.Common.Database
{
public class SoteriaDbContext: DbContext
{
public SoteriaDbContext(DbContextOptions<SoteriaDbContext> options)
: base(options)
{
}
public DbSet<Test> Tests { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Test>().ToTable("Tests");
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.EnableSensitiveDataLogging(true);
}
}
}
Test.cs
using System;
namespace Soteria.Common.Models
{
public class Test
{
public int? Id { get; set; }
public DateTime Date { get; set; }
}
}
Tests.sql
CREATE TABLE [dbo].[Tests]
(
[Id] INT NOT NULL PRIMARY KEY IDENTITY,
[Date] DATETIME NOT NULL
)
I had to install the published sources of the win-x64 folder, and not the "publish" folder to make this actually work. This even though my target runtime was win-x64, which would have led me to expect the published result would be in the "publish" folder.
Release folder structure and confusing publish folder

.NET Core Web API async data return

I'm trying to handle returning data to APi client in GET HTTP response in asynchronous manner but with no luck so far.
My code :
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Server.Database;
using System;
using System.Threading.Tasks;
namespace Server.Controllers
{
//[Produces("application/json")]
[Route("api/[Controller]")]
public class UserController : Controller
{
private readonly DBContext _context;
public UserController(DBContext context)
{
_context = context;
}
[HttpGet("/Users")]
public async Task<IAsyncResult> GetUsers()
{
using (_context)
{
// how to properly return data asynchronously ?
var col = await _context.Users.ToListAsync();
}
}
[HttpGet("/Users/{id}")]
public async Task<IActionResult> GetUserByID(Int32 id)
{
using (_context)
{
//this is wrong, I don't knwo how to do it properly
//var item = await new ObjectResult(_context.Users.FirstOrDefault(user => user.IDUser == id));
}
}
}
}
As you can see I would like to handle GET request asynchronously by returning all users and in another method single user by his ID. I don't know if I need ObjectResultclass as well but I need to respons with JSON object to the client. Someone know how to do this ?
Here, try this:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Server.Database;
using System;
using System.Threading.Tasks;
namespace Server.Controllers
{
//[Produces("application/json")]
[Route("api/[Controller]")]
public class UserController : Controller
{
private readonly DBContext _context;
public UserController(DBContext context)
{
_context = context;
}
[HttpGet("/Users")]
public async Task<IActionResult> GetUsers()
{
return Json(await _context.Users.ToListAsync());
}
[HttpGet("/Users/{id}")]
public async Task<IActionResult> GetUserByID(Int32 id)
{
return Json(await new _context.Users.FirstOrDefault(user => user.IDUser == id));
}
}
}
Note, that in GetUsers you must return IActionResult, not IAsyncResult.

Configuring Ninject with Asp.Net MVC & Web Api

i have setup my project with Ninject IoC.
My project has regular Asp.Net MVC controllers and Web Api controllers. Now, Ninject works with Web Api but Ninject doesn't work with regular Asp.MVC controllers.
My regular MVC controller implementation;
public class GalleryController : BaseController
{
public GalleryController(IUow uow)
{
Uow = uow;
}
........
}
Error when using with regular controller
An error occurred when trying to create a controller of type 'Web.Controllers.HomeController'. Make sure that the controller has a parameterless public constructor.]
However, when i try the same code with Web Api, it works
public class GalleryController : BaseApiController
{
public GalleryController(IUow uow)
{
Uow = uow;
}
......
}
my interface which holds difference repositories (the factory pattern)
public interface IUow
{
// Save pending changes to the data store.
void Commit();
//Repositoryries
IRepository<Gallery> Gallery { get; }
IMenuRepository Menus { get; }
}
NinjectDependencyScope class;
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
this.resolver = resolver;
}
public void Dispose()
{
var disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.GetAll(serviceType);
}
}
NinjectDependencyResolver class;
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
Ninject configuration for Global.asax;
public class IocConfig
{
public static void RegisterIoc(HttpConfiguration config)
{
var kernel = new StandardKernel(); // Ninject IoC
//kernel.Load(Assembly.GetExecutingAssembly()); //only required for asp.net mvc (not for webapi)
// These registrations are "per instance request".
// See http://blog.bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/
kernel.Bind<RepositoryFactories>().To<RepositoryFactories>()
.InSingletonScope();
kernel.Bind<IRepositoryProvider>().To<RepositoryProvider>();
kernel.Bind<IUow>().To<Uow>();
// Tell WebApi how to use our Ninject IoC
config.DependencyResolver = new NinjectDependencyResolver(kernel);
}
}
Global.asax
protected void Application_Start()
{
// Tell WebApi to use our custom Ioc (Ninject)
IocConfig.RegisterIoc(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfig.CustomizeConfig(GlobalConfiguration.Configuration);
AreaRegistration.RegisterAllAreas();
}
I have written some gists to help configure Ninject with MVC and Web Api. Simply include the file(s):
https://gist.github.com/odytrice/5821087 (for MVC)
https://gist.github.com/odytrice/5842010 (for WebApi)
To add Bindings for concrete Types, Just put them in the Load() method of the MainModule. You can create as many modules as you like to keep bindings organized. but you'll also have to add them to the array that is returned in the Modules property.
Then Add to the Application_Start() method
NinjectContainer.RegisterModules(NinjectModules.Modules) (for MVC)
NinjectHttpContainer.RegisterModules(NinjectHttpModules.Modules) (for WebApi)
Note that you can use the same NinjectModules.Modules for both the MVC and WebApi registration. I just separated it for clearity
UPDATE: Remember to Remove NinjectWebCommon.cs from your project as it loads and bootstraps a new kernel at Runtime which unfortunately is only for MVC.
UPDATE: You can also use
NinjectContainer.RegisterAssembly() (for MVC)
NinjectHttpContainer.RegisterAssembly() (for WebApi)
This will scan your current assembly for all modules. This way you can put your modules anywhere in your project and it will be registered
With MVC 5 and Web API 2.2 I solved this problem by making sure I included the following NuGet packages:
Ninject.MVC5
Ninject.Web.WebApi.WebHost for Web API
This installed other Ninject dependencies and allowed me to RegisterServices through NinjectWebCommon.cs.
After searching a lot, it turns out there we can't use Ninject with web api and regular mvc. I mean, we have to configure the Repositories separately.
I then found a nice article which explains how you can use Ninject with asp.net mvc & web api: http://www.codeproject.com/Articles/412383/Dependency-Injection-in-asp-net-mvc4-and-webapi-us
And now, I don't get the error and it's working :D
Update 1:
Also try Writing a simple implementation of dependency injection in MVC 4 Web API with .NET Framework 4.5
Here is the simple solution that works fine for me:
In Visual studio, create new web application project named DemoApp and make sure you have selected Empty template with MVC and Web API references:
In Package manager console execute one by one:
Install-Package Ninject
Install-Package Ninject.MVC5
Add NinjectDependencyResolver.cs to IoC folder :
using Ninject;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Dependencies;
namespace DemoApp.IoC
{
public class NinjectDependencyResolver : IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return this;
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
public void Dispose() { } //it is not necessary to implement any dispose logic here
}
}
Make the following changes in App_Start/NinjectWebCommon.cs :
Add these lines in CreateKernel method:
NinjectDependencyResolver ninjectResolver = new NinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(ninjectResolver); //MVC
GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; //Web API
Add your bindings in RegisterServices method like:
kernel.Bind< IHelloService>().To< HelloService>();
Now NinjectWebCommon.cs should look like:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(DemoApp.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(DemoApp.App_Start.NinjectWebCommon), "Stop")]
namespace DemoApp.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using DemoApp.IoC;
using System.Web.Mvc;
using System.Web.Http;
using DemoApp.Config;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
NinjectDependencyResolver ninjectResolver = new NinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(ninjectResolver); //MVC
GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; //Web API
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IHelloService>().To<HelloService>();
}
}
}
Just for the completeness of the example, add some Mvc and Api controllers, and code for IHelloService, HelloService :
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DemoApp.Config;
namespace DemoApp.Controllers
{
public class HomeController : Controller
{
private IHelloService helloService;
public HomeController(IHelloService helloService)
{
this.helloService = helloService;
}
// GET: /Home/
public string Index()
{
return "home/index: " + helloService.GetMessage();
}
}
}
UserController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using DemoApp.Config;
namespace DemoApp.Controllers
{
public class UserController : ApiController
{
private IHelloService helloService;
public UserController(IHelloService helloService)
{
this.helloService = helloService;
}
[HttpGet]
public string Data()
{
return "api/user/data: " + helloService.GetMessage();
}
}
}
IHelloService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace DemoApp.Config
{
public interface IHelloService
{
string GetMessage();
}
}
HelloService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace DemoApp.Config
{
public class HelloService : IHelloService
{
public string GetMessage()
{
return "Hi";
}
}
}
The final structure should look like:
Now make some tests in browser. For me it was:
http://localhost:51156/home/index
http://localhost:51156/api/user/data
And that's it.
I think the issue is that you are not registering a ControllerFactory that uses Ninject to build the controllers (and resolve their dependencies), have you tried implementing your own ControllerFactory yet? See also here http://bubblogging.wordpress.com/2012/06/04/mvc-controller-factory-ninject/.
There is a more elegant solution for this by Nenad - it took me 3 extra hours because I first tried to implement the solutions here conflicting with existing infrastructure I had. It is in reply to another stack overflow question. I am duplicating that answer here just in case it helps others to save the time I lost.
There is a way to share same container between MVC and ASP.NET Web API.
You just need to implement both interfaces.
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(this.kernel.BeginBlock());
}
}
Check this article for solution:
Simple Way to share Dependency Resolvers between MVC and Web API

Resources