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.
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
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.