Receiving error message: System.Reflection.TargetException: Non-static method requires a target

2.4k views Asked by At

I'm using Visual Studio 2013 Update 2 and I'm getting an unhandled exception in one of my controllers and I can't figure where it's coming from. This is the controller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Data.Entity;
using Microsoft.AspNet.Identity;

namespace SophicCeramics.Controllers
{
public class ShopController : BaseController
{
public ActionResult Cart()
    {
        var order = FindOrCreateOrder();
        var m = new Models.Order.Cart();  //
        m.Date = order.OrderDate;
        m.Total = order.OrderLineItems.Sum(i => i.Quantity * i.UnitPrice);
        m.ItemCount = order.OrderLineItems.Count;
        m.Items = order.OrderLineItems.ToList();
        return View(m);
    }
    public async Task<ActionResult> AddItem(int productId)
    {
        var product = _context.Products.FirstOrDefault(p => p.ProductId == productId);
        var order = FindOrCreateOrder();
        var item = order.OrderLineItems.FirstOrDefault(i => i.ProductId == productId);
        if (item != null)
        {
            item.Quantity++;
            await _context.SaveChangesAsync();
        }
        else
        {
            item = new OrderLineItem();
            item.OrderHeader = order;
            item.Product = product;
            item.Quantity = 1;
            item.UnitPrice = product.Price;
            order.OrderLineItems.Add(item);
            await _context.SaveChangesAsync();
        }
        return RedirectToAction("Cart");
    }
    private OrderHeader FindOrCreateOrder()
    {
        var UserName = this.User.Identity.Name;
        var user = UserManager.FindByName(UserName);
        var customer = _context.Customers
            .Include(c => c.OrderHeaders.Select(o => o.OrderLineItems.Select(i => i.Product))).
            FirstOrDefault(c => c.UserId.Equals(user.Id));

        var order = customer.OrderHeaders
            .OrderBy(o => o.OrderDate)
            .LastOrDefault(o => o.Paid == false);

        if(order == null)
        {
            order = new OrderHeader();
            //var Customer = new Customer();
            order.Customer = customer;
            customer.OrderHeaders.Add(order);
            _context.SaveChanges();
        }
        return order;
    }
  }
}

This is the view model:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SophicCeramics.Models.Order
{
    public class Cart
    {
    public int ItemCount { get; set; }
    public DateTime Date { get; set; }
    public decimal Total { get; set; }
    public List<OrderLineItem> Items { get; set; }
    public decimal UnitPrice { get; set; }
    public int OrderHeaderId { get; set; }
    public string CustomerId { get; set; }
    public System.DateTime OrderDate { get; set; }
    public bool Paid { get; set; }
    public int OrderLineItemId { get; set; }
    public int ProductId { get; set; }
    public int Quantity { get; set; }
    public int CategoryId { get; set; }
    public int ArtistId { get; set; }
    public string Title { get; set; }
    public decimal Price { get; set; }
    public string ProductArtUrl { get; set; }
    public string ProductArtMain { get; set; }
    public string UserId { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    }
}

And this is the view:

@model SophicCeramics.Product
@{ ViewBag.Title = "Cart"; }
<div>
<h4>Product</h4>
<hr />
<dl class="dl-horizontal">
    <dt>
        @Html.DisplayNameFor(model => model.Title)
    </dt>
    <dd>
        @Html.DisplayFor(model => model.Title)
    </dd>
    <dt>
        @Html.DisplayNameFor(model => model.Price)
    </dt>
    <dd>
        @Html.DisplayFor(model => model.Price)
    </dd>
    <dt>
        @Html.DisplayNameFor(model => model.ProductArtUrl)
    </dt>
    <dd>
        @Html.DisplayFor(model => model.ProductArtUrl)
    </dd>
    <dt>
        @Html.DisplayNameFor(model => model.ProductArtMain)
    </dt>
    <dd>
        @Html.DisplayFor(model => model.ProductArtMain)
    </dd>
    <dt>
        @Html.DisplayNameFor(model => model.Artist.Name)
    </dt>
    <dd>
        @Html.DisplayFor(model => model.Artist.Name)
    </dd>
    <dt>
        @Html.DisplayNameFor(model => model.Category.Name)
    </dt>
    <dd>
        @Html.DisplayFor(model => model.Category.Name)
    </dd>
</dl>
</div>
<p>
@Html.ActionLink("Edit", "Edit", new { id = Model.ProductId }) |
@Html.ActionLink("Back to List", "Index")
</p>

The View has a layout page that is automatic. I keep getting the error pointing to this line of code:

var customer = _context.Customers
        .Include(c => c.OrderHeaders.Select(o => o.OrderLineItems.Select(i => i.Product))).
        FirstOrDefault(c => c.UserId.Equals(user.Id));

No matter how I rearrange the include statement it just won't work. Also, the controller is inheriting from another one called BaseController which has a connection to the database through _context. I've also tried adding pretty much everything from the relevant classes in the .tt files in the edmx, and still get the error. Also, when I put a break point on the customer variable and step through it, it goes straight to the dispose method in the BaseController.

1

There are 1 answers

1
ekad On BEST ANSWER

I would guess that user is null, so you get the error when accessing user.Id inside a lambda expression here

var customer = _context.Customers
    .Include(c => c.OrderHeaders.Select(o => o.OrderLineItems
    .Select(i => i.Product)))
    .FirstOrDefault(c => c.UserId.Equals(user.Id));

You need to check if user is null after this line

var user = UserManager.FindByName(UserName);

and only execute the rest of the code inside FindOrCreateOrder method when user is not null. You also need to decide what to do if user is null in the else block as follows

private OrderHeader FindOrCreateOrder()
{
    var UserName = this.User.Identity.Name;
    var user = UserManager.FindByName(UserName);
    if (user != null)
    {
        var customer = _context.Customers
            .Include(c => c.OrderHeaders.Select(o => o.OrderLineItems.Select(i => i.Product))).
            FirstOrDefault(c => c.UserId.Equals(user.Id));

        var order = customer.OrderHeaders
            .OrderBy(o => o.OrderDate)
            .LastOrDefault(o => o.Paid == false);

        if(order == null)
        {
            order = new OrderHeader();
            //var Customer = new Customer();
            order.Customer = customer;
            customer.OrderHeaders.Add(order);
            _context.SaveChanges();
        }
        return order;
    }
    else
    {
        // logic when user is null
    }
}