I want to create an easy Admin panel for editing users roles. First I want to display users list with their roles.
First I edited some things in AccountModel:
Context:
public class UsersContext : DbContext
{
public UsersContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<UserRole> UserRole { get; set; }
}
User profile:
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string EmailId { get; set; }
public string Details { get; set; }
public virtual ICollection<UserRole> UserRole { get; set; }
}
User roles:
[Table("webpages_Roles")]
public class UserRole
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int RoleId { get; set; }
public string RoleName { get; set; }
public virtual ICollection<UserProfile> UserProfile { get; set; }
}
After that I created UserController with ActionResult Index:
public ActionResult Index()
{
using (var db = new UsersContext())
{
return View(db.UserProfiles.Include("UserRole").ToList());
}
}
And View:
#model IEnumerable<AnimeWeb.Models.UserProfile>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
User Name
</th>
<th>
User Role
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
#Html.DisplayFor(modelItem => item.UserRole)
</td>
</tr>
}
Partial View for UserRole looks like this:
#model AnimeWeb.Models.UserRole
<tr>
#Html.DisplayFor(model => model.RoleName),
</tr>
When I try to execute it I get InnerException error: "Invalid object name 'dbo.UserRoleUserProfiles'.". I dont quite get it. Could someone explain me why is this happening and how to resolve this?
Seems like the problem lies here
public virtual ICollection<UserRole> UserRole { get; set; }
And you don't have a mapping for these classes, so the default setting creates a UserRoleUserProfiles table(or class) and it doesn't exist in the database, so the problem occurs.
You can try remove this line of code and then try run the project again
Related
I have three relational models that I want to display in a view in one table. following, I will list 3 models then the controller and the view.
and an error that come out from the controller.
Model Documents
public class Documents
{
[Key]
public int DocId { get; set; }
public string DocName { get; set; }
[ForeignKey("Employee")]
public int EmpId_From { get; set; }
[ForeignKey("Employee")]
public int EmpId_To { get; set; }
[ForeignKey("Organization")]
public int OrganId_From { get; set; }
[ForeignKey("Organization")]
public int OrganId_To { get; set; }
public Employee _Employee { get; set; }
public Organization _Organization { get; set; }
}
Employee
public class Employee
{
[Key]
public int Emp_ID { get; set; }
public string EmpName { get; set; }
}
Organization
public class Organization
{
[Key]
public int OrgID { get; set; }
public string OrgName { get; set; }
}
The Controller
public IActionResult Index()
{
List<Documents> x = _context.Documents.Include(e => e.Employee).Include(o => o.Organization).ToList();
return View(x);
}
The View
#model IEnumerable<Documents>
#foreach (var item in Model.DocumentsList)
{
<tr>
<td>
#item.DocId
</td>
<td>
#item.DocName
</td>
<td> // I can see item.Employee.EmpName but how to display it for this FK EmpId_From & EmpId_To
#item.EmpId_From // item.Employee.EmpName for EmpId_From
</td>
<td>
#item.EmpId_To // item.Employee.EmpName for EmpId_To
</td>
<td>
#item.OrganId_From // item.Organization.OrgName for OrganId_From
</td>
<td>
#item.OrganId_To // item.Organization.OrgName for OrganId_To
</td>
</tr>
}
I get this error from the controller
Microsoft.Data.SqlClient.SqlException: 'Invalid column name '_EmployeeEmp_ID'.
Invalid column name 'OrganizationOrgID'.
Invalid column name 'EmployeeEmp_ID'.
Invalid column name 'OrganizationOrgID'.'
As far as I know, if want to add relationship between the Documents and Employee, Organization, you could directly add the employee and Organization as the property inside the Documents. Then you could directly get the related employee and Organization's value.
Your model class will like this:
public class Documents
{
[Key]
public int DocId { get; set; }
public string DocName { get; set; }
public Employee Emp_From { get; set; }
public Employee Emp_To { get; set; }
public Organization Organ_From { get; set; }
public Organization Organ_To { get; set; }
}
public class Employee
{
[Key]
public int Emp_ID { get; set; }
public string EmpName { get; set; }
}
public class Organization
{
[Key]
public int OrgID { get; set; }
public string OrgName { get; set; }
}
Home controller:
public IActionResult Index()
{
List<Documents> x = _dbContext.Documents.Include(e => e.Emp_From).Include(o => o.Emp_To).Include(o => o.Organ_From).Include(o => o.Organ_To).ToList();
return View(x);
}
View:
<table>
#foreach (var item in Model)
{
<tr>
<td>
#item.DocId
</td>
<td>
#item.DocName
</td>
<td>
#item.Emp_From.EmpName
</td>
<td>
#item.Emp_To.EmpName
</td>
<td>
#item.Organ_From.OrgName
</td>
<td>
#item.Organ_To.OrgName
</td>
</tr>
}
</table>
Result:
I am working on a small project and trying to display the fullname (which added by me on in ApplicationUser Model inhireted from IdentityUser) and below the Model:
public class ApplicationUser : IdentityUser
{
public int PersonnalNumber { get; set; }
public string FullName { get; set; }
}
here is SystemDetails Model have relationship with Application User:
public class SystemDetails
{
[Key]
public int Id { get; set; }
[Required]
[Display(Name = "System Name")]
public string SystemName { get; set; }
[Required]
[Display(Name = "Admin Name")]
public string SystemAdminId { get; set; }
public string ServerNames { get; set; }
[ForeignKey("SystemAdminId")]
public virtual ApplicationUser ApplicationUser { get; set; }
}
and here is the Index View:
#if (Model.Count() > 0)
{
<table class=" table table-striped border">
<tr class="table-secondary">
<th>
#Html.DisplayNameFor(m => m.SystemName)
</th>
<th>
#Html.DisplayNameFor(m => m.SystemAdminId)
</th>
<th></th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(m => item.SystemName)
</td>
<td>
#Html.DisplayFor(m => item.ApplicationUser.FullName)
</td>
<td>
<partial name="_TableButtonPartial" model="#item.Id" />
</td>
</tr>
}
Everything working fine except that FullName is not displayed on index page, I can display SystemAdminId which is the registered user Id but when i try to display the FullName using Applicationuser.FullName it is not displaying any thing! it is saved correctly on the database when I create record on SystemDetails Controller as below:
SystemAdminId
Here is create action:
[HttpPost,ActionName("Create")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreatePost()
{
List<ApplicationUser> userList = new List<ApplicationUser>();
if (!ModelState.IsValid)
{
return NotFound();
}
userList = await (from user in _db.ApplicationUser select user).ToListAsync();
ViewBag.usersList = userList;
_db.SystemDetails.Add(SystemDetails);
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
Appreciating any help
In controller , when querying the SystemDetails list you should load the related ApplicationUser :
using Microsoft.EntityFrameworkCore;
var result = _dbContext.SystemDetails.Include(f => f.ApplicationUser).ToList();
1st model:
public class VehicleMake
{
[Key]
public int MakeId { get; set; }
public string Make { get; set; }
}
2nd Model:
public class VehicleModel
{
[Key]
public int ModelId { get; set; }
public string Model { get; set; }
public DateTime Year { get; set; }
public int MakeId { get; set; }
public VehicleMake VehcileMake { get; set; }
}
How to pass two models as strongly typed view.
my view has 1) one dropdownlist which bind make and makeid from VehicleMake class
2) one textbox as Model which binds from vehicleModle class
Please suggest how to create a view using multiple models?
#model MvcApplication1.Data.ViewVMModel
....
<h2>CreateModel</h2>
<table>
<tr>
<td>#Html.Label("Select Make")</td>
<td>#Html.DropDownListFor(model=>model.VehicleMake,new SelectList(Model. "MakeId","Make")))</td>
</tr>
<tr>
<td>Enter Model </td>
<td>#Html.TextBoxFor(model=>model.VehcileModel)</td>
</tr>
</table>
You're editing data so first step is to create a view model (add other validation attributes as required).
public class VehicleVM
{
[Required(ErrorMessage = "...")]
public string Model { get; set; }
[Required(ErrorMessage = "...")]
public DateTime? Year { get; set; } // make nullable to protect against under-posting attacks
[Required(ErrorMessage = "...")]
[Display(Name = "Make")]
public int? SelectedMake { get; set; }
public IEnumerable<SelectListItem? MakesList { get; set; }
}
and in the GET method, initialize an instance of your view model, populate it and pass it to the view
var makes = db.VehicleMakes; // get the Makes from the database
VehicleVM vehicle = new VehicleVM()
{
MakesList = new SelectList(makes, "MakeId", "Make")
};
return View(vehicle);
and in the view
#model VehicleVM
....
#using (Html.BeginForm())
{
#Html.LabelFor(m => m.SelectedMake)
#Html.DropDownListFor(m => m.SelectedMake, Model.MakesList)
#Html.ValidationMessageFor(m => m.SelectedMake)
#Html.LabelFor(m => m.Model)
#Html.TextBoxFor(m => m.Model)
#Html.ValidationMessageFor(m => m.Model)
....
Which will post back to
public ActionResult Create(VehicleVM vehicle)
your Viewmodel should be something like this
public VehicleModel VehicleModel { get; set; }
public List<VehicleMake> VehcileMakeList { get; set; }
and in your view
#model MvcApplication1.Data.ViewVMModel
....
<h2>CreateModel</h2>
<table>
<tr>
<td>#Html.Label("Select Make")</td>
<td>#Html.DropDownListFor(model=>model.VehicleModel.MakeId ,new SelectList(Model.VehcileMakeList, "MakeId","Make")))</td>
</tr>
<tr>
<td>Enter Model </td>
<td>#Html.TextBoxFor(model=>model.VehcileModel.Model)</td>
<td>#Html.TextBoxFor(model=>model.VehcileModel.Year )</td>
</tr>
</table>
and in your action
ViewVMModel vm = new ViewVMModel();
vm.VehcileMakeList = //get list of make
vm.VehicleModel = new VehicleModel();
return view(vm);
Newbie to MVC, using MVC 5 and VS 2013.
Code first from existing database, EF6
Goal:
Want to show a listing of all models from the tblModel for an MVP listed in tblMVP
Below is the current state of the project and the runtime error:
Error:
System.Collections.Generic.IEnumerable<WebApplication2.Models.tblAccount>' does not contain a definition for 'tblModels' and no extension method 'tblModels' accepting a first argument of type System.Collections.Generic.IEnumerable<WebApplication2.Models.tblAccount> could be found (are you missing a using directive or an assembly reference?)
Models:
[Table("tblMVP")]
public partial class tblMVP
{
[Key]
public int ID { get; set; }
public int AccountID { get; set; }
public virtual tblAccount tblAccount { get; set; }
}
[Table("tblModel")]
public partial class tblModel
{
[Key]
public int ID { get; set; }
public int AccountID { get; set; }
public virtual tblAccount tblAccount { get; set; }
}
[Table("tblAccount")]
public partial class tblAccount
{
public tblAccount()
{
tblModels = new HashSet();
tblMVPs = new HashSet();
}
public int ID { get; set; }
public virtual ICollection tblModels { get; set; }
public virtual ICollection tblMVPs { get; set; }
}
Controller:
// GET: MVP
public ActionResult Index()
{
var tblAccounts = db.tblAccounts.Include(t => t.tblModels).Include(t => t.tblMVPs);
return View(db.tblAccounts.ToList());
}
View
#model IEnumerable<WebApplication2.Models.tblAccount>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.tblModels.partNumber)
</th>
<th>
#Html.DisplayNameFor(model => model.AccountName)
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.tblModels.partNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.AccountName)
</td>
</tr>
}
</table>
You're trying to do two different things. You have an IEnumerable<tblAccount>, which doesn't have properties, it just has a list of tblAccount.
So in the top, you're trying to get properties of the IEnumerable, but there aren't any.
In the bottom, you're iterating the IEnumerable, and getting properties of the tblAccount, which you are doing correctly.
So in the top section, you need to get a tblAccount from the IEnumerable so that you can get properties of it. Below is an example of how you can do it.
#model IEnumerable<WebApplication2.Models.tblAccount>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.First().tblModels.partNumber)
</th>
<th>
#Html.DisplayNameFor(model => model.First().AccountName)
</th>
</tr>
Ultimately this is is the bare essentials version of what worked. For better or worse a direct relationship between the tblModel and tblMVP was created and the model loading in the controller was rearranged.
Models:
[Table("tblMVP")]
public partial class tblMVP
{
public tblMVP()
{
tblModels = new HashSet();
}
public int ID { get; set; }
public int AccountID { get; set; }
public string Description { get; set; }
public virtual tblAccount tblAccount { get; set; }
public virtual ICollection tblModels { get; set; }
}
[Table("tblModel")]
public partial class tblModel
{
[Key]
public int ModelID { get; set; }
public int AccountID { get; set; }
[Required]
[StringLength(50)]
public string partNumber { get; set; }
[StringLength(5000)]
public string description { get; set; }
public int? MVPID { get; set; }
public virtual tblMVP tblMVP { get; set; }
}
[Table("tblAccount")]
public partial class tblAccount
{
public tblAccount()
{
tblModels = new HashSet();
tblMVPs = new HashSet();
}
public int ID { get; set; }
[StringLength(150)]
public string AccountName { get; set; }
public int? AccountNumber { get; set; }
public virtual ICollection tblModels { get; set; }
public virtual ICollection tblMVPs { get; set; }
}
**Controller:**
// GET: MVP
public ActionResult Index()
{
var tblModels = db.tblModels.Include(t => t.tblAccount).Include(t => t.tblMVP).ToList();
return View(tblModels.ToList());
}
View
#model IEnumerable<MDLX_Bootstrap_V5.Models.tblModel>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.tblAccount.AccountName)
</th>
<th>
#Html.DisplayNameFor(model => model.partNumber)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.tblAccount.AccountName)
</td>
<td>
#Html.DisplayFor(modelItem => item.partNumber)
</td>
</tr>
}
</table>
I'm working in ASP.NET MVC 4 and I have the problem that my model validation isn't working correctly. For some reason not all my required fields have to be filled in.
Here's my model:
public class MovieModel
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public DateTime ReleaseDate { get; set; }
[Required]
public string Genre { get; set; }
[Required]
public decimal Price { get; set; }
public virtual ICollection<RoleInMovie> RoleInMovie { get; set; }
}
Here's the View:
#using (Html.BeginForm())
{
<table>
<tr>
<td>
<label>Name:</label></td>
<td>#Html.EditorFor(m => m.Name)</td>
<td>#Html.ValidationMessageFor(m => m.Name)</td>
</tr>
<tr>
<td>
<label>Genre:</label></td>
<td>#Html.EditorFor(m => m.Genre)</td>
<td>#Html.ValidationMessageFor(m => m.Genre)</td>
</tr>
<tr>
<td>
<label>Price:</label></td>
<td>#Html.EditorFor(m => m.Price)</td>
<td>#Html.ValidationMessageFor(m => m.Price)</td>
</tr>
</table>
<button type="submit">Submit</button>
}
And here's my action:
[HttpPost]
public ActionResult Add(MovieModel model)
{
if(ModelState.IsValid)
{
return RedirectToAction("Index");
}
return View();
}
Now here's the thing: as soon as I enter only a price, modelstate.isvalid becomes true. When hovering over my model, it sais both name and genre are null. Ofcourse they are required, but the validation doesn't work.
Also, the validationmessagefor only works on price.
I hope I'm not overlooking something too ridiculous. Thanks for the help!
Return the invalid model back to the view:
[HttpPost]
public ActionResult Add(MovieModel model)
{
if(ModelState.IsValid)
{
return RedirectToAction("Index");
}
return View(model); // <----
}
Oh, and make sure that the required attribute is disallowing empty strings
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.requiredattribute.allowemptystrings.aspx
public class MovieModel
{
public int Id { get; set; }
[Required(AllowEmptyStrings = false)]
public string Name { get; set; }
public DateTime ReleaseDate { get; set; }
[Required(AllowEmptyStrings = false)]
public string Genre { get; set; }
[Required]
public decimal Price { get; set; }
public virtual ICollection<RoleInMovie> RoleInMovie { get; set; }
}