I'm working on my first API using MVC. I've gotten it working previously by creating an API and declaring/creating its data within the controller, like so:
public class ValuesController : ApiController
{
private northwndEntities db = new northwndEntities();
Product[] products = new Product[]
{
new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
};
public IEnumerable<Product> GetAllProducts()
{
return products;
}
public Product GetProduct(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
return (product);
}
}
Here is a model I created quickly to work with this: Product.cs
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
}
I don't believe it was necessary, but here is the script I used to make the call, even though for earlier testing, I just navigated to the appropriate URL, rather than trying to be fancy.
<script>
//var apiurl = "api/values";
var apiurl = "api/ordersapi";
$(document).ready(function() {
$.getJSON(apiurl).done(function(data) {
$.each(data, function(key, item) {
$('<li>', { text: formatItem(item) }).appendTo($('#products'));
});
});
});
function formatItem(item) {
return item.Name + ": $" + item.Price;
}
function find() {
var pId = $('#prdId').val();
$.getJSON(apiurl + '/' + pId)
.done(function (data) {
$('#product').text(formatItem(data));
})
.fail( function(jqxHr, textStatus, err) {
$('#product').text("Error: "+err);
});
}
</script>
With this in mind, a call to "api/values/2" would return the data for ID = 2 I can get this working no problem. Of course, I am also making sure to change the url variable I am using when trying to call the API that i'm about to outline below.
Next, I wanted to step up to using a separate API by calling from my pre-existing (database-first style) database.
I am using repository pattern and dependency injection so here is the code for my repository (named "repo.cs"), the API controller (named "OrdersAPI" controller), as well as my ninjectWebcommon.cs file
Repo.cs (the repository class)
public interface INorthwindRepository : IDisposable
{
IQueryable<Order> GetOrders();
Order GetOrderById(int id);
}
public class NorthwindRepository : INorthwindRepository
{
private northwndEntities _ctx;
public NorthwindRepository(northwndEntities ctx)
{
_ctx = ctx;
}
public IQueryable<Order> GetOrders()
{
return _ctx.Orders.OrderBy(o => o.OrderID);
}
public Order GetOrderById(int id)
{
return _ctx.Orders.Find(id);
}
public void Dispose()
{
_ctx.Dispose();
}
}
OrdersAPIController.cs
public class OrdersAPIController : ApiController
{
private INorthwindRepository db;
public OrdersAPIController(INorthwindRepository _db)
{
db = _db;
}
//api/ordersapi
public IEnumerable<Order> Orders()
{
return db.GetOrders();
}
//api/ordersapi/5
public Order SpecificOrder(int id)
{
Order order = db.GetOrderById(id);
return order;
}
}
NinjectWebCommon.cs (*Note the comment in CreateKernel() method)
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(RAD302PracticeAPI.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(RAD302PracticeAPI.App_Start.NinjectWebCommon), "Stop")]
namespace RAD302PracticeAPI.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using RAD302PracticeAPI.Models;
using System.Web.Http;
using Ninject.Web.Mvc;
using System.Web.Mvc;
//using System.Web.Http;
//using Ninject.Web.Mvc;
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);
//tried code from...
//http://haacked.com/archive/2012/03/11/itrsquos-the-little-things-about-asp-net-mvc-4.aspx/
//but it didnt work
//GlobalConfiguration.Configuration.ServiceResolver.SetResolver(DependencyResolver.Current.ToServiceResolver());
}
/// <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);
//this line is giving me an error saying:
//"Cannot implicitly convert type 'Ninject.Web.Mvc.NinjectDependencyResolver' to
//'System.Web.Http.Dependencies.IDependencyResolver'. An explicit conversion exists (are you missing a cast?)
//However from one or two places here it has been recommended as a possible solution to solve
//the dependency issue
//one place is here: http://stackoverflow.com/questions/17462175/mvc-4-web-api-controller-does-not-have-a-default-constructor
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
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<northwndEntities>().To<northwndEntities>();
}
}
}
From the link i've posted in the commented area of my ninject.cs page, it seems the problem is that I need to set a dependency resolver for my application. I THINK that this is done for you when you're not using an API, but in this situation you must. I'm open to correction on that. So, my hunch is that I need to create a dependency resolver class, but the line I left a comment on is not working, and is supposedly the solution I need, based on other SO pages.
Thank you to anybody who takes the time to offer any advice. Getting over this hurdle will allow me to get where I want to be, for now at least. I've put some effort into researching what the problem is. Just hoping a more experienced head can spot something subtle.
*Update: When I uncomment this line
"GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);"
ie - the line that was recommended to add in the link that I included as a comment in my code, I get the error in this image http://postimg.org/image/qr2g66yaj/
And when I include that line, the error that i'm given is this: http://postimg.org/image/9wmfcxhq5/