Reputation: 4685
I am using a standard ASP.Net MVC4 web application while working through a tutorial. I have followed all the steps in the first parts and when using the Moq mocking framework all worked well.
In the first part, it caused links to the standard .net application for login and registration to be removed, but the functionality was still there so I added them back in because I taught the problem was with the connection string.
Initially it was with the con string. But I resolved this. However when I change the code to refer to the local DB with the working con string I am still getting a Null Ref exception. I have gone through the code several times at this point and fail to see what is wrong. So I paste the example code below for reference with hope someone can help me.
Its a sample golf store application and it has only 1 table. Items. The structure of the project is a standard MVC4 web app with an additional project for Domain which contains folders for Abstract, Concrete, and Entities because it supposedly uses entity frameworks in a way I am not sure about.
Just to clarify, when I comment the last line in the Infrastructure\NinjectControllerFactory.cs and uncomment the moq code. Everything works. Its only when I comment out the code and uncomment the last line that I get the error. Even though the table does have 3 records in it.
Below is the code in the Domain Project Domain\Entities\Item.cs
public class Item
{
public int ItemId { get; set; }
public string ItemName { get; set; }
public string ItemDesc { get; set; }
public string Brand { get; set; }
public string Category { get; set; }
public decimal ItemPrice { get; set; }
}
Domain\Abstract\IItemRepository.cs
public interface IItemRepository
{
IQueryable<Item> Items { get; }
}
Domain\Concrete\EFItemRepository.cs
public class EFItemRepository : IItemRepository
{
private EFdbContext context = new EFdbContext();
public IQueryable<Item> Items
{
get { return context.Items; }
}
}
Domain\Concrete\EFdbContext.cs
class EFdbContext
{
public DbSet<Item> Items { get; set; }
}
I am probably wrong about this assumption but I fail to see where the above code is being used or how to actually alter my code to use it. Anyway, below is the MVC4 Web project. In it I have a folder for Infrastructure with one class as follows:
GolfStore.WebUI\Infrastructure\NinjectControllerFactory.cs
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel ninjectKernel;
public NinjectControllerFactory()
{
ninjectKernel = new StandardKernel();
AddBinding();
}
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
//return base.GetControllerInstance(requestContext, controllerType);
return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType);
}
private void AddBinding()
{
////Old binding to bind to moq item repo - All this works
//Mock<IItemRepository> mock = new Mock<IItemRepository>();
//mock.Setup(m => m.Items).Returns(new List<Item>
//{
// new Item{ItemId=1,ItemName="Trolley", ItemPrice=100M},
// new Item{ItemId=1,ItemName="Irons", ItemPrice=255M},
// new Item{ItemId=1,ItemName="Driver", ItemPrice=129.67M}
//}.AsQueryable());
//ninjectKernel.Bind<IItemRepository>().ToConstant(mock.Object);
//New binding to bind to real db
ninjectKernel.Bind<IItemRepository>().To<EFItemRepository>();
}
}
The above code is mostly comments because most of it is used by the Moq mocking framework. The last line (I may be wrong) seems to me to be the only one needed in this method for connecting to a live DB but it seems to not do anything.
Below is the Item Controller:
public class ItemController : Controller
{
private IItemRepository repository;
public ItemController(IItemRepository itemRepository)
{
this.repository = itemRepository;
}
public ViewResult Index()
{
return View(repository.Items);
}
}
Below is the Item View:
@model IEnumerable<SHGolfStore.Domain.Entities.Item>
@{
ViewBag.Title = "Index";
}
@{
//TODO FR: Part 6
}
<h2>MY DI Stuff Part 1</h2>
<br />
@foreach (var i in Model)
{
<div class="item">
<h4>@i.ItemName (€@i.ItemPrice)</h4>
</div>
}
Finally I added this line to the Global.asax.cs file in the MvcApplication class under the Application_Start() method:
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
Below are the 2 connections strings I am trying to use. The DefaultConnection works and lets me do a register and login no problem. But when I add the other one or rename it as recommended in the tutorial to EFDbContext, even though nothing else changes, I start getting errors. However even with the DefaultConnection unmodified, I still get the error explained below with regard to null ref in the view. This is actually what I am trying to fix.
<add name="EFDbContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-SHGolfStore.WebUI-20140413135241;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-SHGolfStore.WebUI-20140413135241.mdf" providerName="System.Data.SqlClient" />
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-SHGolfStore.WebUI-20140413135241;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-SHGolfStore.WebUI-20140413135241.mdf" providerName="System.Data.SqlClient" />
There is no obvious model that I can see. Also while I did add EF to the projects as explained, I don't see where it is being used as no EDMX file or dataset is generated. If it is being generated I don't understand how it is being used. So I would like some clarification on this please.
Just to reiterate, when I comment the last line in the Infrastructure\NinjectControllerFactory.cs and uncomment the moq code. Everything works. Its only when I comment out the code and uncomment the last line that I get the error. Even though the table does have 3 records in it.
I am getting a null reference exception on the View in the foreach part. I can understand why if the DB is not being accessed but I don't understand enough to fix it.
Thanks again for the help.
Upvotes: 1
Views: 233
Reputation: 4685
As I use StackOverflow as my own reference and I finally fixed the problem. I would like to document it here for both my own reference and encase others might have the same issue.
Essentially it was a problem with the connection string.
What I did not understand was the there are usually 2 connection strings in a project.
The first connection string (usually called DefaultConnection), is the actual connection string used to access the DB, mostly by the login / registration system as EF uses the second.
The second connection string is the one used by Entity Frameworks. If you have your projects separated as I did, I had my EF classes in another project away from the web application. The correct EF con string was stored in the App.Config there. When I pulled it out of there, and replaced the old one in the web.config with the one I got from there it almost worked.
I had to do some other basic restructuring to make my code refer to the new con string but essentially this was all that was needed.
If anyone else has any suggestions on how I could restructure or improve things, or would like more information, please feel free to add comments or answers and I will come back and edit this.
Upvotes: 1