Why enum values are not showing in View - c#

I want to allow the user to download the report, when it is approved by a supervisor. At the moment, I'm working with manager account, where he can check many reports and change their state to either verified or denied, but I don't understand why the report states enum list is not displaying, even though it is shown in the console.
HTML code
Model:
public class Report
{
public int ID { get; set; }
[Display(Name = "Report Name")]
public string reportName { get; set; }
public virtual User reportManager { get; set; }
[Display(Name = "State")]
public ReportState reportState { get; set; }
public byte[] reportData { get; set; }
}
public enum ReportState
{
Accepted,
Pending,
Denied
}
Controller:
public async Task<IActionResult> Index()
{
ViewBag.Reports = await _context.Reports.ToListAsync();
ViewBag.ReportStates = new SelectList(Enum.GetNames(typeof(ReportState)));
return View();
}
#model variable_pay_system.Models.Report
#{
ViewData["Title"] = "Reports";
}
<div class="container">
<h5>Reports</h5>
<table>
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.reportName)
</th>
<th>
#Html.DisplayNameFor(model => model.reportState)
</th>
</tr>
</thead>
<tbody>
#foreach (Report report in ViewBag.Reports)
{
<tr>
<td>
#Html.DisplayFor(modelItem => report.reportName)
</td>
<td>
<select asp-for="#report.reportState" asp-items="Html.GetEnumSelectList<ReportState>()"></select>
</td>
</tr>
}
</tbody>
</table>

If you are going to use enums in View, you can show these enums as a list. and I recommend using it by printing it to a dropdown. EnumDropDownListFor()
Model :
public enum ReportState
{
Accepted,
Pending,
Denied
}
View:
#Html.EnumDropDownListFor(model => model.ReportState)
Using Tag Helper (ASP.NET MVC 6):
<select asp-for="#Model.SelectedValue" asp-items="Html.GetEnumSelectList<ReportState>()">

Ok so the problem was because, I was missing this code at the end.
<script>
$(document).ready(function () {
$('select').formSelect();
});

Related

How to edit/update a database entity column with a button in ASP.NET MVC C#

I am stuck on a function I want to create and can't figure out how to implement it. I have a database table called "OrderDetails" and in the table I have a column called "StatusID". The StatusID has 3 possible values (1) which = "Pending" ,(2) which = "Shipped", and (3) which = "Completed. I have a partial view created on a main dashboard page that pulls up the OrderDetails table from database and only shows the orders that have a StatusID value of 1 or 2. I put two buttons on the table and what I'd like to accomplish is when the user clicks on button1, it would change the StatusID to 2 (which is "Shipped"). And if the user clicks on button2, it would change the StatusID to 3 (which is "Completed"). By change I mean, whatever record (or Order#) the button is on, it would edit/update that value in the database. I can't seem to get it to work from a button click, I've tried everything I can think of and no luck, but just as a disclaimer, I am very new to ASP.net MVC C# and web development in general so I'm definitely not an expert with extensive knowledge. Is what I'm trying to do possible with buttons?
Here is my model:
namespace AMS_ITAMSdb.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
using System.Web;
using System.Web.Mvc;
public partial class OrderDetail
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage",
"CA2214:DoNotCallOverridableMethodsInConstructors")]
public OrderDetail()
{
this.ProductOrders = new HashSet<ProductOrder>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Name = "Order ID")]
public int OrderID { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
public Nullable<System.DateTime> Order_Date { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
[Display(Name = "Date Needed")]
public Nullable<System.DateTime> Date_Requested { get; set; }
[Display(Name = "Order Status")]
public Nullable<int> StatusID { get; set; }
public virtual OrderStatu OrderStatu { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<ProductOrder> ProductOrders { get; set; }
}
}
Here is my controller:
namespace AMS_ITAMSdb.Controllers
{
public class DashboardsController : Controller
{
private ItamsEntities db = new ItamsEntities();
public ActionResult Index()
{
return View();
}
public ActionResult Admin()
{
return View();
}
//GET: OpenOrders
public ActionResult OpenOrders(OrderDetail orderDetail)
{
var orderDetails = db.OrderDetails.Where(o => o.StatusID < 3).ToList();
return PartialView("OpenOrders", orderDetails);
}
}
}
and Here is my view page:
#model IEnumerable<AMS_ITAMSdb.Models.OrderDetail>
#{
Layout = null;
}
<div class="container">
<table class="table">
<tr class="table-hdr">
<th class="open-lbl">
Open
</th>
<th class="ord-lbl">
Order #
</th>
<th class="orderDate-lbl">
Order Date
</th>
<th class="products-lbl">
Products
</th>
<th class="dateNeeded-lbl">
Date Needed
</th>
<th class="status-lbl">
Status
</th>
<th>
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td class="open-ctl">
<u>Open</u>
</td>
<td class="ord-ctl">
#Html.DisplayFor(modelItem => item.OrderID)
</td>
<td class="orderDate-ctl">
#Html.DisplayFor(modelItem => item.Order_Date)
</td>
<td class="products-ctl">
<a>#Html.ActionLink("View", "ProductOrder", "Dashboards", new { id = item.OrderID })</a>
</td>
<td class="dateNeeded-ctl">
#Html.DisplayFor(modelItem => item.Date_Requested)
</td>
<td class="status-ctl">
#Html.DisplayFor(modelItem => item.OrderStatu.Status)
</td>
<td>
<button class="button" type="submit"><span class="fa-solid fa-truck-fast"></span></button>
<button class="button" type="submit"><span class="fa-solid fa-clipboard-check"></span></button>
<button class="button"><span class="fa-solid fa-print"></span> Print</button>
</td>
</tr>
}
</table>
</div>
I have tried doing a function in the controller called "ToShipped" and "ToCompleted" where I called up from the button when it is clicked but it didn't work. This is the code I tried:
//POST: Dashboards/ToShipped
[HttpPost]
public ActionResult ToShipped(OrderDetail orderDetail)
{
if (ModelState.IsValid)
{
orderDetail.StatusID = 2;
db.Entry(orderDetail).State = EntityState.Modified;
db.SaveChanges();
}
var orderDetails = db.OrderDetails.Include(o => o.Department).Include(o => o.OrderStatu).Where(o => o.StatusID < 3).ToList();
return PartialView("OpenOrders", orderDetails);
}
//POST: Dashboards/ToCompleted
[HttpPost]
public ActionResult ToCompleted(OrderDetail orderDetail)
{
if (ModelState.IsValid)
{
orderDetail.StatusID = 3;
db.Entry(orderDetail).State = EntityState.Modified;
db.SaveChanges();
}
var orderDetails = db.OrderDetails.Where(o => o.StatusID < 3).ToList();
return PartialView("OpenOrders", orderDetails);
}
And then in my view on the input button, I tried calling the function by doing a Url.Action:
<input class ="button" type="submit" formaction="#Url.Action("ToShipped", "Dashboards")" formmethod="post" />
I don't know where I'm going wrong, any help or suggestions, would be greatly appreciated!!!

InvalidOperationException: The model item passed into the ViewDataDictionary is of type Dbset[*] but this ViewDataDictionary of type [*]

I just can't understand I tried everything I could so I hope you guys can help me.
Error message :
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1[BookStore1.Models.Book]', but this ViewDataDictionary instance requires a model item of type 'BookStore1.Models.Account'.
That's like an online book-store and I was trying to make an action with which you can display all books in the database and edit them as an admin.
That's my book model:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BookStore1.Models
{
public class Book
{
[Key]
public int Id { get; set; }
[Required]
public string? Name { get; set; }
[Required]
public string? Author { get; set; } = "Unknown";
[Required]
public int Price { get; set; }
[NotMapped]
public IFormFile? Image { set; get; }
}
}
that's my admin controller:
using BookStore1.Data;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using BookStore1.Models;
namespace BookStore1.Controllers
{
[Authorize(Policy = "HasToBeAdmin")]
public class AdminController : Controller
{
private readonly AppDataContext _database;
private readonly IWebHostEnvironment _webHostEnvironment;
public AdminController(AppDataContext database, IWebHostEnvironment webHostEnvironment)
{
_database = database;
_webHostEnvironment = webHostEnvironment;
}
public IActionResult ShowBooks()
{
var books = _database.Books;
return View(books);
}
[HttpGet]
public IActionResult AddBook()
{
return View();
}
public async Task<IActionResult> AddBook(Book book)
{
if (ModelState.IsValid)
{
string wwwRootPath = _webHostEnvironment.WebRootPath;
string fileName = Path.GetFileNameWithoutExtension(book.Image.FileName);
string extention = Path.GetExtension(book.Image.FileName);
string path = Path.Combine(wwwRootPath + "/booksImages", fileName);
using (var fileStream = new FileStream(path, FileMode.Create))
{
await book.Image.CopyToAsync(fileStream);
}
_database.Books.Add(book);
_database.SaveChanges();
return RedirectToAction("ShowBooks", "Admin");
}
return View(book);
}
}
}
The view that won't view:
#model IEnumerable<BookStore1.Models.Book>
#{
ViewData["Title"] = "ShowBooks";
}
<h1>ShowBooks</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Author)
</th>
<th>
#Html.DisplayNameFor(model => model.Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Author)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</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>
database context:
using Microsoft.EntityFrameworkCore;
using BookStore1.Models;
namespace BookStore1.Data
{
public class AppDataContext: DbContext
{
public AppDataContext(DbContextOptions<AppDataContext> options): base(options)
{
}
public DbSet<Account> Accounts { get; set; }
public DbSet<Book> Books { get; set; }
}
}
If the view you shown above is ShowBooks.You only need to use _database.Books.ToList() as Serge said.
You use #model IEnumerable<BookStore1.Models.Book> in the view,and you pass System.Collections.Generic.List1[BookStore1.Models.Book]` to the view,it's correct.
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Collections.Generic.List`1[BookStore1.Models.Book]', but this ViewDataDictionary instance requires a model item of type 'BookStore1.Models.Account'.
For the error,the view will contains #model BookStore1.Models.Account.You need to find the view which contains it,and check the data passed from action.
you have to fix the action, to convert a dbset to a list and add name of the view to the action if name is not "ShowBooks.cshtml"
public IActionResult ShowBooks()
{
var books = _database.Books.ToList();
return View("viewName", books);
}

ASP.NET MVC Complex Object property stays null on form submit

I'm getting myself acquainted with ASP.NET MVC but i'm running into something probably trivial. I have a model called ToDoList, this is a complex type with a list of ToDoItems:
public class ToDoList
{
public Guid Id {get;set;}
public string Name { get; set; }
public virtual ICollection<ToDoItem> Items {get;set;}
}
public class ToDoItem
{
public int Id { get; set; }
public string Task { get; set; }
public bool IsDone { get; set; }
public virtual ToDoList ToDoList { get; set; }
}
My Details page with form looks like this:
#model DataLayer.TomTest.Entities.ToDoList
<h2>#Model.Name</h2>
#using (#Html.BeginForm())
{
#Html.AntiForgeryToken()
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.Items.First().Id)
</th>
<th>
#Html.DisplayNameFor(model => model.Items.First().Task)
</th>
<th>
#Html.DisplayNameFor(model => model.Items.First().IsDone)
</th>
</tr>
#foreach (var toDoItem in Model.Items)
{
<tr>
<td>
#toDoItem.Id
</td>
<td>
#Html.EditorFor(model => toDoItem.Task)
</td>
<td>
#Html.EditorFor(model => toDoItem.IsDone, new {htmlAttributes = new {#Style = "margin-left: 10px;"}})
</td>
</tr>
}
</table>
<input type="submit" value="Save" class="btn btn-default"/>
}
And this is the method it posts to:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Details([Bind(Include = "Id,Name,Items")] ToDoList todoList)
{
if (ModelState.IsValid)
{
_context.Entry(todoList).State = EntityState.Modified;
await _context.SaveChangesAsync();
return View();
}
return View();
}
As you can see I included the [Bind] attribute as I read somewhere that would ensure i get the correct properties passed. When I debug this however, only the Id property is filled the rest remains null.
What can I do to fix this? Is it a mistake in the View? Or is it possible Entity Framework isn't setup correctly?
Thanks in advance for your help.
Model binding to a list doesn't work with a foreach; you need to use a for loop instead.
You'll also need hidden inputs for any properties which don't have editors within the loop.
#for (int index = 0; index < Model.Items.Count; index++)
{
<tr>
<td>
#Html.HiddenFor(m => m.Items[index].Id)
#Model.Items[index].Id
</td>
<td>
#Html.EditorFor(m => m.Items[index].Task)
</td>
<td>
#Html.EditorFor(m => m.Items[index].IsDone, new { htmlAttributes = new { #Style = "margin-left: 10px;" } })
</td>
</tr>
}
ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries - Scott Hanselman's Blog

foreach statement cannot operate because does not contain a public definition for 'GetEnumerator' with Tuples ASP.NET MVC

I want to build my view and join 2 tables using LINQ but i got this error in view in foreach in Model
#foreach (var item in Model)
This is my classes :
public partial class Lab_orders_Cash
{
[Display(Name = "Order Id")]
public int cash_order_id { get; set; }
[Display(Name = "Order Date")]
public Nullable<System.DateTime> order_date { get; set; }
[Display(Name = "MRN File No.")]
public Nullable<int> patient_no { get; set; }
public string invoice_order_no { get; set; }
public string order_description { get; set; }
public string user_id { get; set; }
[Display(Name = "Order Status")]
public Nullable<int> order_status { get; set; }
public Nullable<int> catid { get; set; }
public Nullable<int> almansoor { get; set; }
public Nullable<int> prio_id { get; set; }
}
public partial class Lab_Sample_status
{
public int status_id { get; set; }
public string status_name { get; set; }
}
this my controller :
public ActionResult ordersCash()
{
var OrdersList = from o in db.Lab_orders_Cash
Join os in db.Lab_Sample_status on o.order_status equals os.status_id into tablestatus
where o.patient_no == (int)Session["UserpatientNo"]
select o;
return View(OrdersList);
}
In view i used Tuples :
#using AljawdahNewSite.Models;
#model Tuple<Lab_orders_Cash,Lab_Sample_status>
#{
#{
ViewBag.Title = "ordersCash";
Layout = "~/Views/Shared/_LayoutPatients.cshtml";
}
<h2>Orders List </h2>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(Tuple => Tuple.Item1.cash_order_id)
</th>
<th>
#Html.DisplayNameFor(Tuple => Tuple.Item1.order_date)
</th>
<th>
#Html.DisplayNameFor(Tuple => Tuple.Item1.patient_no)
</th>
<th>
#Html.DisplayNameFor(Tuple => Tuple.Item2.status_name)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(Tuple => Tuple.Item1.cash_order_id)
</td>
<td>
#Html.DisplayFor(Tuple => Tuple.Item1.order_date)
</td>
<td>
#Html.DisplayFor(Tuple => Tuple.Item1.patient_no)
</td>
<td>
#Html.DisplayFor(Tuple => Tuple.Item2.status_name)
</td>
<td>
#Html.ActionLink("Details", "Details", new { id=item.cash_order_id })
</td>
</tr>
}
</table>
in foreach when select model i got this error , also i tried to use IEnumerable in view like this
#model Tuple<IEnumerable<Lab_orders_Cash>,IEnumerable<Lab_Sample_status>>
but same error when i select Model it shows the error
What i need to change to solve this error.
you can use another way like the following steps :
1- Create new class and put your tables in that class
public class Tables
{
public Lab_orders_Cash LabOrdersCash { get; set; }
public Lab_Sample_status LabOrderStatus { get; set; }
}
2- Write the controller like the following :
public ActionResult ordersCash()
{
List<Lab_orders_Cash> ordercash = db.Lab_orders_Cash.ToList();
List<Lab_Sample_status> samplestatus = db.Lab_Sample_status.ToList();
var OrdersList = from o in ordercash
join st in samplestatus on o.order_status equals st.status_id
where o.patient_no == (int)Session["UserpatientNo"]
select new Tables{ LabOrdersCash = o , LabOrderStatus = st };
return View(OrdersList);
}
3- Create your view use the following code :
#model IEnumerable<AljawdahNewSite.Models.Tables>
#{
ViewBag.Title = "ordersCash";
Layout = "~/Views/Shared/_LayoutPatients.cshtml";
}
<h2>Orders List</h2>
<table class="table">
<tr>
<td> Order No. </td>
<td> order date </td>
<td> Patient No </td>
<td> Status </td>
</tr>
#foreach (var item in Model)
{
<tr>
<td>#item.LabOrdersCash.cash_order_id</td>
<td>#item.LabOrdersCash.order_date</td>
<td>#item.LabOrdersCash.patient_no</td>
<td>#item.LabOrderStatus.status_name</td>
</tr>
}
</table>
This way more effective and easily you can add all your tables in this tables class and call this class any where in your project and easier than Tuples.

C# Entity Overview Table of one to many checkbox

I can't seem to find how to build a proper solution for a one to many checkbox.
So what do i have :
I have an article and an admin user can set user rights to that article.
So in my article right page you have an overview with all the users.
My article:
public partial class Artikel
{
public Artikel()
{
this.ArtikelLinks = new HashSet<ArtikelLink>();
this.ArtikelRights = new HashSet<ArtikelRight>();
}
public int id { get; set; }
public string code { get; set; }
public string naam { get; set; }
public virtual ICollection<ArtikelLink> ArtikelLinks { get; set; }
public virtual ICollection<ArtikelRight> ArtikelRights { get; set; }
}
My rights class
public partial class ArtikelRight
{
public int id { get; set; }
public System.Guid userId { get; set; }
public int artikelId { get; set; }
public bool hasRight { get; set; }
public virtual Artikel Artikel { get; set; }
}
How do i build my view? i tried several ways but i can't seem to save my data.
this is my rights view at the moment:
#using (Html.BeginForm()) {
<table width="90%" align="center" class="table table-striped">
<thead>
<tr>
<th align="left">Gebruiker</th>
<th align="left">Heeft toegang</th>
</tr>
</thead>
#Html.EditorFor(x => Model.ArtikelRights, "ArtikelRight")
</table>
<br />
<div class="pull-right">
<input type="submit" value="Opslaan" class="btn btn-sm beige" />
</div>
}
And this is my partial Artikel right view:
#model IEnumerable<GtiProducts.Models.ArtikelRight>
#foreach (var item in Model) {
<tr>
<td>
#Membership.GetUser(item.userId).UserName
</td>
<td>
#Html.EditorFor(x => item.hasRight)
</td>
</tr>
}
My save action is:
public ActionResult Rights(Artikel art)
{
repo.SaveChanges();
return View(art);
}
When i debug my art.ArtikelRights is null.
How can i fix this and what's the best solution to do this with the entity framework?
Rename the partial to make it an EditorTemplate- /Views/Shared/EditorTemplates/ArtikelRight.cshtml, then make the following modifications
#model GtiProducts.Models.ArtikelRight // not IEnumerable
<tr>
<td>
#Html.CheckBoxFor(m => m.hasRight)</td>
#Html.LabelFor(m => m.hasRight, "....") // the users name?
#Html.HiddenFor(m > m.id) // or what ever property you need to identify the ArtikelRight.cshtml
</td>
</tr>
Then in the main view
<tbody>
#Html.EditorFor(x => Model.ArtikelRights)
</tbody>
This will correctly name you controls with indexers so they can be bound to your model on post back, for example
<input type="checkbox" name="ArtikelRights[0].hasRight" ...>
<input type="checkbox" name="ArtikelRights[1].hasRight" ...>
Side note: You should not be using #Membership.GetUser(item.userId).UserName in the view. Instead create a view model with only those properties you need in the view (which appears to be id and hasright, and include a property for the users display name (and populate it in the controller).

Categories

Resources