I'm following the tutorial listed here: http://dotnetawesome.blogspot.com/2014/07/nested-webgrid-with-expand-collapse-in-aspnet-mvc4.html using my VS2015 Enterprise IDE.
However when at step 8 I go to right click the List() ActionResult in OrderController and select Add View with the following:
I get the following error:
However in the tutorial they don't use a key for OrderVM. Even when I do add [Key]
and the proper using and after rebuilding I still get the same error and I'm at a complete loss as to why given I'm using getters and setters.
ViewModels: OrderVM
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using WebAppTest.Models;
namespace WebAppTest.ViewModels
{
public class OrderVM
{
[Key]
public OrderMaster order { get; set; }
public List<OrderDetail> orderDetails { get; set; }
}
}
Models (Generated from doing a CodeFirst from DB): MyModel
namespace WebAppTest.Models
{
using System;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
public partial class MyModel : DbContext
{
public MyModel()
: base("name=MyDatabaseEntities")
{
}
public virtual DbSet<OrderDetail> OrderDetails { get; set; }
public virtual DbSet<OrderMaster> OrderMasters { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<OrderDetail>()
.Property(e => e.Product)
.IsUnicode(false);
modelBuilder.Entity<OrderDetail>()
.Property(e => e.Rate)
.HasPrecision(10, 2);
modelBuilder.Entity<OrderDetail>()
.Property(e => e.Amount)
.HasPrecision(10, 2);
modelBuilder.Entity<OrderMaster>()
.Property(e => e.OrderAmount)
.HasPrecision(10, 2);
modelBuilder.Entity<OrderMaster>()
.Property(e => e.CustomerName)
.IsUnicode(false);
modelBuilder.Entity<OrderMaster>()
.Property(e => e.CustomerAddress)
.IsUnicode(false);
}
}
}
OrderDetail
namespace WebAppTest.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
public partial class OrderDetail
{
[Key]
public int OrderDetailsID { get; set; }
public int OrderID { get; set; }
[Required]
[StringLength(100)]
public string Product { get; set; }
public int Quantity { get; set; }
[Column(TypeName = "numeric")]
public decimal Rate { get; set; }
[Column(TypeName = "numeric")]
public decimal Amount { get; set; }
}
}
OrderMaster
namespace WebAppTest.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
[Table("OrderMaster")]
public partial class OrderMaster
{
[Key]
public int OrderID { get; set; }
public DateTime OrderDate { get; set; }
[Column(TypeName = "numeric")]
public decimal OrderAmount { get; set; }
[Required]
[StringLength(100)]
public string CustomerName { get; set; }
[StringLength(200)]
public string CustomerAddress { get; set; }
}
}
Controllers
OrderController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebAppTest.Models;
using WebAppTest.ViewModels;
namespace WebAppTest.Controllers
{
public class OrderController : Controller
{
// GET: Order
//public ActionResult Index()
//{
// return View();
//}
public ActionResult List()
{
List<OrderVM> allOrder = new List<OrderVM>();
// here MyDatabaseEntities is our data context
using (MyModel dc = new MyModel())
{
var o = dc.OrderMasters.OrderByDescending(a => a.OrderID);
foreach (var i in o)
{
var od = dc.OrderDetails.Where(a => a.OrderID.Equals(i.OrderID)).ToList();
allOrder.Add(new OrderVM { order = i, orderDetails = od });
}
}
return View(allOrder);
}
}
}
Here is the logic of Scaffolder to check for key field:
First finds all properties with this criteria:
Then Tries to find key based on name:
Tries to find key based on attributes:
Key
AttributeEdmScalarProperty
Attribute with value of EntityKeyPropety=true
Column
Attribute with value of IsPrimaryKey=true
So you should have a filed in your class that meets one of above criterias.
Also you should remove [Key]
from your order
property because complex types can not be key.
As an option you can add this property to your class:
[Key]
public int OrderID { get; set; }
And as another option your OrderVM
class can be like this:
public partial class OrderVM
{
public OrderVM()
{
orderDetails = new List<OrderDetails>();
}
[Key]
public int OrderID { get; set; }
public DateTime OrderDate { get; set; }
public decimal OrderAmount { get; set; }
[Required]
[StringLength(100)]
public string CustomerName { get; set; }
[StringLength(200)]
public string CustomerAddress { get; set; }
public List<OrderDetail> orderDetails { get; set; }
}