I've just started learning ASP.NET Core MVC based on this first-mvc-app tutorial
I have a database table 'tblProducts' and I can create a single table listing all products using
Model :
public class tblProducts
{
//SQL table is named tblProducts
[Key]
public int ID { get; set; }
public DateTime Date { get; set; }
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Product { get; set; } //<<Want separate tables split by this field
}
View :
@model IEnumerable<LearnMVC.Models.tblProducts>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Date)
</th>
<th>
@Html.DisplayNameFor(model => model.Field1)
</th>
<th>
@Html.DisplayNameFor(model => model.Field2)
</th>
<th>
@Html.DisplayNameFor(model => model.Product)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Date)
</td>
<td>
@Html.DisplayFor(modelItem => item.Field1)
</td>
<td>
@Html.DisplayFor(modelItem => item.Field2)
</td>
<td>
@Html.DisplayFor(modelItem => item.Product)
</td>
<td>
<a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
<a asp-action="Details" asp-route-id="@item.ID">Details</a> |
<a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Contoller : Default MVC Controller with views, using Entity Framework
public class tblProductsController : Controller
{
private readonly ApplicationDbContext _context;
public tblProductsController(ApplicationDbContext context)
{
_context = context;
}
// GET: tblProducts
public async Task<IActionResult> Index()
{
return View(await _context.tblProducts.ToListAsync());
}
// GET: tblProducts/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var tblProducts = await _context.tblProducts.SingleOrDefaultAsync(m => m.ID == id);
if (tblProducts == null)
{
return NotFound();
}
return View(tblProducts);
}
// GET: tblProducts/Create
public IActionResult Create()
{
return View();
}
// POST: tblProducts/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ID,Date,Field1,Field2,Product")] tblProducts tblProducts)
{
if (ModelState.IsValid)
{
_context.Add(tblProducts);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(tblProducts);
}
// GET: tblProducts/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var tblProducts = await _context.tblProducts.SingleOrDefaultAsync(m => m.ID == id);
if (tblProducts == null)
{
return NotFound();
}
return View(tblProducts);
}
// POST: tblProducts/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Date,Field1,Field2,Product")] tblProducts tblProducts)
{
if (id != tblProducts.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(tblProducts);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!tblProductsExists(tblProducts.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(tblProducts);
}
// GET: tblProducts/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var tblProducts = await _context.tblProducts.SingleOrDefaultAsync(m => m.ID == id);
if (tblProducts == null)
{
return NotFound();
}
return View(tblProducts);
}
// POST: tblProducts/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var tblProducts = await _context.tblProducts.SingleOrDefaultAsync(m => m.ID == id);
_context.tblProducts.Remove(tblProducts);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
private bool tblProductsExists(int id)
{
return _context.tblProducts.Any(e => e.ID == id);
}
}
Data\\ApplicationDbContext.cs :
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}
public DbSet<tblProducts> tblProducts { get; set; }
}
Please can someone help explain (or know of any good tutorials) how I can create multiple tables based on the same model fields but each table is split by the column 'Product'?
Say there are 5 products, I would expect to see 5 tables all with the same fields Date, Field1, Field2 & Product, but the Product would be unique to each table.
I won't know up front how many products there are so need some logic to determine how many tables are required. As I'm new to this I'm unsure if I need multiple models or if something clever can be done in the controller or view as the data is all from the same table.
I've tried a few searches but they seem to be either non-mvc or based on multiple different models (eg this is similar but has different data sources per table http://www.compilemode.com/2016/09/show-multiple-table-data-on-view-in-asp-net-mvc.html )
TL;DR : What is the ASP.NET MVC way of displaying multiple tables split by field from a single database table?
Updated the fiddle to better reflect your requirement regarding not knowing how many tables you'll need - sorry, missed that the first time around. As before, the fiddle doesn't run, but it should give you a good idea of where to go with it.
Personally, I prefer not to have that sort of logic in the view, and it's certainly possible to move it back to the controller, but think of this as more a proof of concept.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.