I was wondering how to generate a Controller for a derived Model. Let me give you a big picture. There is a Man class from which the User class is inherited. As I read in several EF tutorials, I didn't define DbSet in DatabaseContext class. Thus, as you may know there would be generated only one table on the SQL containing all the properties of Man and User classes besides a discriminator column.
The problem appeared as I was trying to figure out a Controller class for User, but as it is not mentioned in the DatabaseContext, MVC cannot create it and ends up with an error. Hence, I created a Controller for Man class, the parent class. I also have done some modifications in the Controller to explicitly point to the User. I mean, using OfType<> and as such. But as I came to the View which is created based on MVC scaffolding, I could not find any User properties, those that are dedicated to this class.
The Following is the Man class:
public class Man
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public long ID { get; set; }
//------------------------------------------------------------//
[Required, MaxLength(20)]
[LocalizedAttribute("FName")]
public string FName { get; set; }
//------------------------------------------------------------//
[Required, MaxLength(20)]
[LocalizedAttribute("LastName")]
public string LastName { get; set; }
//------------------------------------------------------------//
[Required]
[RegularExpression("^[0-9]+$", ErrorMessageResourceName = "ErrorOnlyNumbers", ErrorMessageResourceType = typeof(MAHAL_E_MA_Model.Properties.Resources))]
[LocalizedAttribute("Mobile")]
public string Mobile { get; set; }
//------------------------------------------------------------//
[LocalizedAttribute("Phone")]
[RegularExpression("^[0-9]+$", ErrorMessageResourceName = "ErrorOnlyNumbers", ErrorMessageResourceType = typeof(MAHAL_E_MA_Model.Properties.Resources))]
public string HomePhone { get; set; }
//------------------------------------------------------------//
[RegularExpression("^[0-9]+$")]
[LocalizedAttribute("IDCardNumber")]
public string IDCardNumber { get; set; }
//------------------------------------------------------------//
[RegularExpression("^[0-9]+$")]
[LocalizedAttribute("NationalCode")]
public string NationalCode { get; set; }
//------------------------------------------------------------//
[MaxLength(10)]
[LocalizedAttribute("DOB")]
public int DOB { get; set; }
//------------------------------------------------------------//
[Required]
public int CityID { get; set; }
[ForeignKey("CityID")]
public virtual City CityParent { get; set; }
//------------------------------------------------------------//
[MaxLength(100)]
[LocalizedAttribute("Address")]
public string Address { get; set; }
//------------------------------------------------------------//
[LocalizedAttribute("PostalCode")]
public string PostalCode { get; set; }
//------------------------------------------------------------//
[MaxLength(255)]
[LocalizedAttribute("PhotoPath")]
public string PhotoPath { get; set; }
}
Here the User Class:
public class User : Man
{
[MaxLength(20)]
[LocalizedAttribute("Username")]
public string UserName { get; set; }
//------------------------------------------------------------//
[DataType(DataType.Password)]
[MaxLength(100), MinLength(6, ErrorMessageResourceType = typeof(MAHAL_E_MA_Model.Properties.Resources), ErrorMessageResourceName = "ErrorPasswordLength")]
[LocalizedAttribute("Password")]
public string Password { get; set; }
//------------------------------------------------------------//
[DataType(DataType.Password)]
[Compare("Password", ErrorMessageResourceType = typeof(MAHAL_E_MA_Model.Properties.Resources), ErrorMessageResourceName = "ErrorConfirmPassword")]
[LocalizedAttribute("ConfirmPassword")]
public string ConfirmPassword { get; set; }
//------------------------------------------------------------//
[DataType(DataType.EmailAddress, ErrorMessageResourceType = typeof(MAHAL_E_MA_Model.Properties.Resources), ErrorMessageResourceName = "ErrorEmailInvalid")]
[MaxLength(20)]
[RegularExpression(@"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}")]
[LocalizedAttribute("Email")]
public string Email { get; set; }
//------------------------------------------------------------//
[MaxLength(30)]
[LocalizedAttribute("Title")]
public string Title { get; set; }
//------------------------------------------------------------//
[MaxLength(10)]
[LocalizedAttribute("HireDate")]
public int HireDate { get; set; }
//------------------------------------------------------------//
[LocalizedAttribute("ReportsTo")]
public long ReportsTo { get; set; }
[ForeignKey("ReportsTo")]
public virtual IList<User> ReportsChild { get; set; }
}
Additionally, I did use OfType in my controller and view as such:
//
// GET: /User/
public ViewResult Index()
{
//var mans = db.Mans.Include(m => m.CityParent);
return View(unitOfWork.UserRepository.Get(orderBy: us => us.OrderByDescending(u => u.ID)).OfType<User>().ToList());
}
// POST: /User/Create
[HttpPost]
public ActionResult Create(Man man)
{
if (ModelState.IsValid)
{
//db.Mans.Add(man);
//db.SaveChanges();
MAHAL_E_MA_Model.POCO.User user = (MAHAL_E_MA_Model.POCO.User)man;
unitOfWork.UserRepository.InsertData(user);
unitOfWork.UserRepository.Save();
return RedirectToAction("Index");
}
// ViewBag.CityID = new SelectList(db.Cities, "CityID", "Name", man.CityID);
return View(man);
}
And in the view:
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.FName.OfType<MAHAL_E_MA_Model.POCO.User>())
</td>
<td>
@Html.DisplayFor(modelItem => item.LastName.OfType<MAHAL_E_MA_Model.POCO.User>())
</td>
<td>
@Html.DisplayFor(modelItem => item.Mobile.OfType<MAHAL_E_MA_Model.POCO.User>())
</td>
<td>
@Html.DisplayFor(modelItem => item.HomePhone.OfType<MAHAL_E_MA_Model.POCO.User>())
</td>
<td>
@Html.DisplayFor(modelItem => item.IDCardNumber.OfType<MAHAL_E_MA_Model.POCO.User>())
</td>
<td>
@Html.DisplayFor(modelItem => item.NationalCode.OfType<MAHAL_E_MA_Model.POCO.User>())
</td>
<td>
@Html.DisplayFor(modelItem => item.DOB)
</td>
<td>
@Html.DisplayFor(modelItem => item.CityParent.Name.OfType<MAHAL_E_MA_Model.POCO.User>())
</td>
<td>
@Html.DisplayFor(modelItem => item.Address.OfType<MAHAL_E_MA_Model.POCO.User>())
</td>
<td>
@Html.DisplayFor(modelItem => item.PostalCode.OfType<MAHAL_E_MA_Model.POCO.User>())
</td>
<td>
@Html.DisplayFor(modelItem => item.PhotoPath.OfType<MAHAL_E_MA_Model.POCO.User>())
</td>
<td>
@Html.ActionLink(GeneralResource.Edit, "Edit", new { id = item.ID }) |
@Html.ActionLink(GeneralResource.ViewDetails, "Details", new { id = item.ID }) |
@Html.ActionLink(GeneralResource.Delete, "Delete", new { id = item.ID })
</td>
</tr>
By the way, I never mentioned the DbSet<User>
whereas mentioned DbSet<Man>
. The reason; EF will create ONE table with all the Properties of User and Man called Man table. Distingushing between different inherited classes such as Customer (not mentioned in this question) and the User is possible using the Discriminator column.
Sorry if the story gets long, But how Can I handle it? That is, how may I have the User Properties in the View? Do I have to add them on myself but if so I don't have any access to them as spreading out some DisplayFor() contained in the foreeach loop which creates the data entry form.
Hope I could transfer the problem successfully.. Can anyone help me on this? Regards,