I've recently been learning asp.net MVC 5 and EF6 and i've started to develop viewmodels for my views instead of stuffing values into the viewbag.
I this is my viewmodel called EmployeeCreate
namespace Rota.ViewModels
{
public class EmployeeCreate
{
public string FirstName { get; set; }
public string LastName { get; set; }
public IEnumerable<SelectListItem> Departments { get; set; }
}
}
what i would like to do is on the create [httpget] action method
to be able to populate a dropdown list
this is my Employee enitity
namespace Rota.Models
{
public class Employee
{
public int ID { get; set; }
[Required]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[ForeignKey("Department")]
[DisplayFormat(NullDisplayText="No Department")]
public int? DepartmentID { get; set; }
public virtual Department Department { get; set; }
public virtual ICollection<Schedule> Schedule { get; set; }
}
}
and this is my Department entity
namespace Rota.Models
{
public class Department
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ID { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
}
Edit this is my DbContext class
public class RotaContext : DbContext
{
public RotaContext() : base("RotaContext")
{
}
public DbSet<Department> Departments { get; set; }
public DbSet<Shift> Shifts { get; set; }
public DbSet<Employee> Employees { get; set; }
public DbSet<Schedule> Scheduled { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public System.Data.Entity.DbSet<Rota.ViewModels.EmployeeCreate> CreateEmployeeViewModels { get; set; }
}
this is my Create Action method in my controller
namespace Rota.Controllers
{
public class EmployeeController : Controller
{
//establish database connection
private RotaContext db = new RotaContext();
//GET: Employee/Create
[HttpGet]
public ActionResult Create()
{
EmployeeCreate ViewModel = new EmployeeCreate()
{
Departments = db.Departments.Select(department => new SelectListItem {
Value = department.ID.ToString(),
Text = department.Name
})
};
return View(ViewModel);
}
}
}
The trouble i've got is that i keep getting this error :
One or more validation errors were detected during model generation:
Rota.Entities.EmployeeCreate: : EntityType 'EmployeeCreate' has no key defined. Define the key for this EntityType. CreateEmployeeViewModels: EntityType: EntitySet 'CreateEmployeeViewModels' is based on type 'EmployeeCreate' that has no keys defined.
I have no idea why the application thinks my viewmodel is an entity, i can't see anything here that might suggest as such, to my knowledge, i thought i was populating an object with values from a database, and becuase the viewmodel has absolutely no association with the entities other than this, it doesn't need a key, because it doesn't need a unique identifier.
Full Stack Trace
[ModelValidationException: One or more validation errors were detected during model generation:
Rota.Entities.EmployeeCreate: : EntityType 'EmployeeCreate' has no key defined. Define the key for this EntityType. CreateEmployeeViewModels: EntityType: EntitySet 'CreateEmployeeViewModels' is based on type 'EmployeeCreate' that has no keys defined. ]
System.Data.Entity.Core.Metadata.Edm.EdmModel.Validate() +338
System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo) +370
System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection) +288
System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext) +94
System.Data.Entity.Internal.RetryLazy2.GetValue(TInput input) +248
1.Initialize() +72
System.Data.Entity.Internal.LazyInternalContext.InitializeContext() +543 System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) +26
System.Data.Entity.Internal.Linq.InternalSet
System.Data.Entity.Internal.Linq.InternalSet1.get_InternalContext() +21 System.Data.Entity.Infrastructure.DbQuery
1.System.Linq.IQueryable.get_Provider() +64 System.Linq.Queryable.Select(IQueryable1 source, Expression
1 selector) +85 Rota.Controllers.EmployeeController.Create() in d:\Development\Rota\Rota\Controllers\EmployeeController.cs:87
lambda_method(Closure , ControllerBase , Object[] ) +79
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) +242
2 parameters) +39
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
System.Web.Mvc.Async.AsyncControllerActionInvoker.b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +12
System.Web.Mvc.Async.WrappedAsyncResult2.CallEndDelegate(IAsyncResult asyncResult) +139
1.CallEndDelegate(IAsyncResult asyncResult) +111
System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() +112 System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +452 System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +15
System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +37 System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +241
System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +29
System.Web.Mvc.Async.WrappedAsyncVoid
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53 System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +19
1.CallEndDelegate(IAsyncResult asyncResult) +111
System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +51
System.Web.Mvc.Async.WrappedAsyncVoid
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +606 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288
public System.Data.Entity.DbSet<Rota.ViewModels.EmployeeCreate> CreateEmployeeViewModels { get; set; }
This is not required in your context class. If you have this, EF tries to create DB object for your viewmodel. For every "DbSet" you give in context class, EF creates DB object. Try removing this.