I am new to MVC and Entity Framework and have decided to use the Code First approach using ViewModels.
I have tried many different tutorials but no one that i've tried has used Code First in EF Core with ViewModels.
My Models
public class Intermediary
{
public int IntermediaryID { get; set; }
public string RegisteredName { get; set; }
public string TradingName { get; set; }
public int Registration { get; set; }
public int VATNumber { get; set; }
public int FSPNumber { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedBy { get; set; }
public ICollection<Branch> Branches { get; set; }
}
public class Branch
{
public int BranchID { get; set; }
public string Name { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedBy { get; set; }
public Intermediary Intermediary { get; set; }
}
My ViewModel
public class IntermediariesViewModel
{
public int ID { get; set; }
public Intermediary Intermediary { get; set; }
public virtual ICollection<Branch> Branches { get; set; }
}
My Data Context Class
public class BizDevHubContext : DbContext
{
public BizDevHubContext(DbContextOptions<BizDevHubContext> options) : base(options)
{
}
public DbSet<Intermediary> Intermediaries { get; set; }
public DbSet<Branch> Branches { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Intermediary>().ToTable("Intermediary");
modelBuilder.Entity<Branch>().ToTable("Branch");
}
}
My Initializer Class
public static class DbInitializer
{
public static void Initialize(BizDevHubContext context)
{
context.Database.EnsureCreated();
if (context.Intermediaries.Any())
{
return; // DB has been seeded
}
var intermediaries = new Intermediary[]
{
new Intermediary{RegisteredName="Carson",TradingName="Alexander",CreatedDate=DateTime.Now,CreatedBy="System"},
new Intermediary{RegisteredName="Meredith",TradingName="Alonso",CreatedDate=DateTime.Now,CreatedBy="System"},
new Intermediary{RegisteredName="Arturo",TradingName="Anand",CreatedDate=DateTime.Now,CreatedBy="System"},
new Intermediary{RegisteredName="Gytis",TradingName="Barzdukas",CreatedDate=DateTime.Now,CreatedBy="System"},
new Intermediary{RegisteredName="Yan",TradingName="Li",CreatedDate=DateTime.Now,CreatedBy="System"},
new Intermediary{RegisteredName="Peggy",TradingName="Justice",CreatedDate=DateTime.Now,CreatedBy="System"},
new Intermediary{RegisteredName="Laura",TradingName="Norman",CreatedDate=DateTime.Now,CreatedBy="System"},
new Intermediary{RegisteredName="Nino",TradingName="Olivetto",CreatedDate=DateTime.Now}
};
foreach (Intermediary i in intermediaries)
{
context.Intermediaries.Add(i);
}
context.SaveChanges();
var branches = new Branch[]
{
new Branch{Name="Bloemfontein",CreatedDate=DateTime.Now,CreatedBy="System"},
new Branch{Name="Cape Town",CreatedDate=DateTime.Now,CreatedBy="System"},
new Branch{Name="Durban",CreatedDate=DateTime.Now,CreatedBy="System"},
new Branch{Name="Nelspruit",CreatedDate=DateTime.Now,CreatedBy="System"},
new Branch{Name="Johannesburg",CreatedDate=DateTime.Now,CreatedBy="System"},
new Branch{Name="Port Shepstone",CreatedDate=DateTime.Now,CreatedBy="System"},
new Branch{Name="Pretoria",CreatedDate=DateTime.Now,CreatedBy="System"}
};
foreach (Branch b in branches)
{
context.Branches.Add(b);
}
context.SaveChanges();
}
}
This all seems to work fine and the database gets created ok, but I am stuck now trying to create the Controller and Views
I managed to do it with a single model but cannot seem to get it right putting the entire viewmodel.
My Controller
using BizDevHub.ViewModels;
public async Task<IActionResult> Index()
{
return View(await _context.Intermediaries.ToListAsync());
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ID")] Intermediaries Intermediaries)
{
if (ModelState.IsValid)
{
_context.Add(Intermediaries);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(Intermediaries);
}
The same goes for my views
My View
#model IEnumerable<BizDevHub.Models.Intermediary>
#{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.RegisteredName)
</th>
<th>
#Html.DisplayNameFor(model => model.TradingName)
</th>
<th>
#Html.DisplayNameFor(model => model.Registration)
</th>
<th>
#Html.DisplayNameFor(model => model.VATNumber)
</th>
<th>
#Html.DisplayNameFor(model => model.FSPNumber)
</th>
<th>
#Html.DisplayNameFor(model => model.CreatedDate)
</th>
<th>
#Html.DisplayNameFor(model => model.CreatedBy)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.RegisteredName)
</td>
<td>
#Html.DisplayFor(modelItem => item.TradingName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Registration)
</td>
<td>
#Html.DisplayFor(modelItem => item.VATNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.FSPNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.CreatedDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.CreatedBy)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.IntermediaryID">Edit</a> |
<a asp-action="Details" asp-route-id="#item.IntermediaryID">Details</a> |
<a asp-action="Delete" asp-route-id="#item.IntermediaryID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
What am I doing wrong?
Thanks in advance.
#Anonymous is correct that you need to redesign the View model. There is no point having a view model if you are just assigning entities as the properties, the purpose of the view model is to separate you controller and view from your datacontext
public class IntermediariesViewModel
{
public int Id { get; set; }
public string RegisteredName { get; set; }
public string TradingName { get; set; }
//other properties
IEnumerable<BranchViewModel> Branches { get; set; }
}
public class BranchViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
View:
#model IEnumerable<BizDevHub.Models.IntermediariesViewModel>
EDIT : but how would you combine both view models in a single controller and view with methods like Index, Edit and Delete?
Controller:
public IActionResult Update([FromBody]IntermediariesViewModel model)
{
var intermediary = _context.Intermediaries.Where(x=> x.IntermediaryID == model.Id).FirstOrDefault();
if(intermediary != null)
{
intermediary.RegisteredName = model.RegisteredName ;
//rest of updates
_context.SaveChanges();
}
}
public IActionResult Delete([FromBody]int IntermediariesId)
{
var intermediary = _context.Intermediaries.Where(x=> x.IntermediaryID == IntermediariesId).FirstOrDefault();
if(intermediary != null)
{
_context.Intermediaries.Remove(intermediary);
_context.SaveChanges();
}
}
View:
#Html.DisplayNameFor(model => model.RegisteredName)
#Html.DisplayNameFor(model => model.BranchViewModel[0].Name)// first branch name, you may want to iterate
public ActionResult Details(int id)
{
//Employee employee = new Employee()
//{
// EmployeeId = 101,
// Name = "rehan",
// Gender = "Male",
// City = "Hafizabad"
//};
//return View(employee);
EmployeeContext employeeContext = new EmployeeContext();
Employee employee= employeeContext.Employees.Single(emp => emp.EmployeeId == id);
return View(employee);
}
I can't got the table's values in view
namespace NewMvcDemo.Models
{
[Table("tblEmploee")]
public class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public string City { get; set; }
}
}
And this is my view
#model NewMvcDemo.Models.Employee
#{
ViewBag.Title = "EmployeeDetails";
}
<h2>EmployeeDetails</h2>
<table style="font-family:Arial">
<tr>
<td>EmployeeId</td>
<td>#Model.EmployeeId</td>
</tr>
<tr>
<td>EmployeeName</td>
<td>#Model.Name</td>
</tr>
<tr>
<td>EmployeeGender</td>
<td>#Model.Gender</td>
</tr>
<tr>
<td>EmployeeCity</td>
<td>#Model.City</td>
</tr>
</table>
<ul>
#foreach (string strcountry in ViewBag.Countries)
{
<li>#strcountry</li>
}
</ul>
So please help me to use the entity framework in the write way
There is the error during the rendring.There is no compilation error
ViewBag.Countries never defined in your controller!
I suggest you to use ViewModel to pass your data from controller to view.
I have created a view which contains 2 tables.
What I want is to filter each table data according to their transaction type for example table1 should show only Payables List and table2 should show only Reciveable List.
here is the code
Note When I navigate to the view server shows me The resource cannot be found.other views are fine. here is my code.
My project has BOL(EF Model) BLL(Business object) DAL(Data Access layer) and my main Mvc project
View
#model shinwari_traders.Areas.Shinwari.Models.ADetailsVm
#{
ViewBag.Title = "Index";
}
<h2>AccountDetails</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table id="Payables" class="table">
<tr>
<th>
Date
</th>
<th>
Discription
</th>
<th>
Amount
</th>
</tr>
#foreach (var item in Model.Payables)
{
<tr>
<td>
#item.Date
</td>
<td>
#item.Discription
</td>
<td>
#item.Amount
</td>
</tr>
}
</table>
<table id="Reciveables" class="table">
<tr>
<th>
Date
</th>
<th>
Discription
</th>
<th>
Amount
</th>
</tr>
#foreach (var item in Model.Reciveables)
{
<tr>
<td>
#item.Date
</td>
<td>
#item.Discription
</td>
<td>
#item.Amount
</td>
</tr>
}
</table>
Controller
public class AccountDetailsController : Controller
{
private TransictionBs objbs;
public AccountDetailsController()
{
objbs = new TransictionBs(int accountid);
}
// GET: Shinwari/AccountDetails
public ActionResult Index(int accountid)
{ var v= new ADetails();
v.Payable = objbs.GetALL().Where(p => p.AId==accountid&& p.tbl_TransictionType.Type.Contains("Payable"));
v.Reciveable = objbs.GetALL().Where(r => r.AId==accountid && r.tbl_TransictionType.Type.Contains("Reciveable"));
return View(v);
}
}
}
Model Class
public class ADetailsVm
{
public List<BOL.tbl_Transiction> Payables { get; set; }
public List<BOL.tbl_Transiction> Reciveables { get; set; }
}
DatabaseTable
public partial class tbl_Transiction
{
public int TId { get; set; }
public Nullable<System.DateTime> Date { get; set; }
public Nullable<int> AId { get; set; }
public string Discription { get; set; }
public Nullable<double> PKR { get; set; }
public Nullable<double> Rate { get; set; }
public Nullable<double> Amount { get; set; }
public Nullable<int> TTId { get; set; }
public virtual tbl_Accounts tbl_Accounts { get; set; }
public virtual tbl_TransictionType tbl_TransictionType { get; set; }
}
You need a new view model with 2 collection properties one for each collection.
public class AccountDetailsVm
{
public List<BOL.tbl_Transiction> Reciveable {set;get;}
public List<BOL.tbl_Transiction> Payable {set;get;}
}
And in your GET action, create an object of this view model, fill these 2 properties.
public ActionResult Index(int accountid)
{
var v=new AccountDetailsVm();
//Load both the collection properties
v.Payables = objbs.GetALL()
.Where(p => p.AId==accountid && p.tbl_TransictionType.Type.Contains("Payable"));
v.Reciveable = objbs.GetByID(accountid).tbl_TransictionType.Type.Contains("Reciveable");
return View(v);
}
And your view is bound to the new view model. I just added the minimal code here. You can convert the rendering to a table.
#model AccountDetailsVm
<h1>Reciveable</h1>
#foreach(var item in Model.Reciveable)
{
<p>#item.Amount</p>
}
<h1>Payable</h1>
#foreach(var item in Model.Payable)
{
<p>#item.Amount</p>
}
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 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