How to show contents from other Models in my view using .NET Core 6? - asp.net-core

I have an Index view that should display the name of each person's course, however, in the model used there is only the Course Id, the course name is in another model - CursosModel - and in another table in the database. How can I display the course name in my view?
Index view:
#model IEnumerable<FeedbackUnivicosa.Models.Professor>
#{
ViewData["Title"] = "Professores";
}
<h4>#ViewData["Title"]</h4>
<form asp-action="Index" method="get">
<div class="form-actions no-color">
<p>
<input type="text" name="SearchString" class="inputSearch" value="#ViewData["CurrentFilter"]" />
<button type="submit" class="botaoSearch fa fa-solid fa-magnifying-glass"></button>
<a asp-action="Index"><i class="espacoFiltro fa fa-solid fa-filter-circle-xmark"></i></a>
<a asp-action="Create" class="botaoCadastro btn btn-primary btn-sm">Cadastrar</a>
</p>
</div>
</form>
<table class="table">
<thead>
<tr>
<th></th>
<th>
<a asp-action="Index" asp-route-sortOrder="#ViewData["NameSortParm"]">Professor</a>
</th>
<th>
<a asp-action="Index" asp-route-sortOrder="#ViewData["EmailSortParm"]">Email</a>
</th>
<th>
<a asp-action="Index" asp-route-sortOrder="#ViewData["CursoSortParm"]">Curso</a>
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td class="fa-lg">
<a asp-action="Edit" asp-route-id="#item.Id"><i class="espacoIcone fa-solid fa-user-pen"></i></a>
<a asp-action="Delete" asp-route-id="#item.Id"><i class="espacoIcone fa-solid fa-trash-can"></i></a>
</td>
<td>
#Html.DisplayFor(modelItem => item.Nome)
</td>
<td>
#Html.DisplayFor(modelItem => item.EmailProfessor)
</td>
<td>
#Html.DisplayFor(modelItem => item.CursoId)
</td>
</tr>
}
</tbody>
</table>
I am trying to show the course name on the Index view.

From your description of this question, I think you can inject your DBContext into your view and get the value of course name from CursosModel table, Please refer to this simple demo:
Model:
public class CursosModel
{
public int id { get; set; }
public string CursoName { get; set; }
}
public class Professor
{
public int Id { get; set; }
public string Name { get; set; }
public int CourseId { get; set; }
}
Then in the view, You can inject dbcontext into your view then get the course Name by Professor's CourseId.
#using xxxx;
#model IEnumerable<Professor>
#inject ApplicationDbContext dbcontext
#foreach (var item in Model)
{
<tr>
<td class="fa-lg">
<a asp-action="Edit" asp-route-id="#item.Id"><i class="espacoIcone fa-solid fa-user-pen"></i></a>
<a asp-action="Delete" asp-route-id="#item.Id"><i class="espacoIcone fa-solid fa-trash-can"></i></a>
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.CourseId)
</td>
<td>
#dbcontext.cursosModels.Where(x => x.id == item.CourseId).Select(y => y.CursoName).FirstOrDefault();
</td>
<br>
</tr>
}
Demo:

because the Microsoft website teaches Add the model
so after you can reference the Microsoft site.
reference Microsoft website
public class CursosModel
{
public List<CursosModel> CursosModel { get; set; }
public List<Course> Course{ get; set; }
}

Related

Updating DB-How do I fix "ViewModel is not part of the model for the current context"

I created a view model and associated controller and view, but it looks like there's a piece missing in both my head and my code. When I submit the page, with or without DB changes, I get the following. "The entity type ReportReviewViewModel is not part of the model for the current context."
Models (not all fields)
public partial class RFDS
{
public System.Guid rfds_processing_id { get; set; }
public string location_name { get; set; }
public string address { get; set; }
}
public partial class Sub_Clients_Xref
{
public int id { get; set; }
public string sub_client { get; set; }
public string sub_client_attn { get; set; }
public string sub_client_address { get; set; }
}
public partial class Engineering_License_Xref
{
public int id { get; set; }
public string state_name { get; set; }
public string license_number { get; set; }
}
ViewModel
public class ReportReviewViewModel
{
public RFDS rfds { get; set; }
public Sub_Clients_Xref subclient { get; set; }
public Engineering_License_Xref engineer { get; set; }
public States_Xref state { get; set; }
}
Controller
public ActionResult Review(Guid? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
RFDS rfds_db = db.RFDS.Find(id);
if (rfds_db == null)
{
return HttpNotFound();
}
List<RFDS> rfds1 = db.RFDS.ToList();
List<Sub_Clients_Xref> subclients = db.Sub_Clients_Xref.ToList();
List<Engineering_License_Xref> engineers = db.Engineering_License_Xref.ToList();
List<States_Xref> states = db.States_Xref.ToList();
var viewModel = (from r in rfds1
join s in subclients on r.sub_client equals s.sub_client
join st in states on r.state equals st.state
join e in engineers on r.engineer_name equals e.engineer_name
where r.rfds_processing_id == id && r.sub_client == s.sub_client &&
(r.engineer_name == e.engineer_name && e.state_name == st.state_name)
select new ReportReviewViewModel
{
rfds = r,
subclient = s,
engineer = e
});
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Review(ReportReviewViewModel viewModel)
{
if (ModelState.IsValid)
{
db.Entry(viewModel).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Review");
}
return View(viewModel);
}
UPDATED CONTROLLER
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Review(ReportReviewViewModel viewModel)
{
if (ModelState.IsValid)
{
db.Entry(viewModel.rfds).State = EntityState.Modified;
db.Entry(viewModel.engineer).State = EntityState.Modified;
db.Entry(viewModel.subclient).State = EntityState.Modified;
db.Entry(viewModel.state).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Review");
}
VIEW example
#model IEnumerable<TeamWeb.ViewModels.ReportReviewViewModel>
#{
ViewBag.Title = "Review";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="container2">
<div class="nav col-md-3">
#Html.ActionLink("BACK TO LIST", "Index")
</div>
<hr />
<table class="rev-table-main" border="0">
<!----------------------------- EDIT DATA ----------------------------->
#using (Html.BeginForm("Review", "RFDS", FormMethod.Post))
{
#Html.AntiForgeryToken()
foreach (var item in Model)
{
#Html.HiddenFor(model => item.rfds.rfds_processing_id)
<tr>
<td class="rev-values-td">
<table class="rev-table-values" border="0">
#*<tr class="rev-tr">
<td> </td>
</tr>*#
<tr class="rev-tr">
<td style="font-size:medium;font-weight:600;text-align:center;" colspan="2">
Edit Report Information
</td>
</tr>
<tr>
<td style="text-align:right;" width="40%">
Site Name:
</td>
<td width="60%">
#Html.EditorFor(model => item.rfds.location_name)
</td>
</tr>
<tr>
<td align="right">
FA Location Code:
</td>
<td>
#Html.EditorFor(model => item.rfds.fa_location_code)
</td>
</tr>
<tr>
<td align="right">
Site Address:
</td>
<td>
#Html.EditorFor(model => item.rfds.address)
</td>
</tr>
<tr>
<td align="right">
Site City:
</td>
<td>
#Html.EditorFor(model => item.rfds.city)
</td>
</tr>
<tr>
<td align="right">
Site State:
</td>
<td>
#Html.EditorFor(model => item.rfds.state)
</td>
</tr>
<tr>
<td align="right">
Site Zip Code:
</td>
<td>
#Html.EditorFor(model => item.rfds.zip_code)
</td>
</tr>
<tr>
<td colspan="2">
<hr />
</td>
</tr>
<tr>
<td align="right">
Sub Client:
</td>
<td>
#Html.EditorFor(model => item.subclient.sub_client)
</td>
</tr>
<tr>
<td align="right">
Sub Client Attn:
</td>
<td>
#Html.EditorFor(model => item.subclient.sub_client_attn)
</td>
</tr>
<tr>
<td align="right">
Sub Client Address:
</td>
<td>
#Html.EditorFor(model => item.subclient.sub_client_address)
</td>
</tr>
<tr>
<td align="right">
Sub Client City:
</td>
<td>
#Html.EditorFor(model => item.subclient.sub_client_city)
</td>
</tr>
<tr>
<td align="right">
Sub Client State:
</td>
<td>
#Html.EditorFor(model => item.subclient.sub_client_state)
</td>
</tr>
<tr>
<td align="right">
Sub Client Zip Code:
</td>
<td>
#Html.EditorFor(model => item.subclient.sub_client_zip)
</td>
</tr>
<tr>
<td colspan="2">
<hr />
</td>
</tr>
<tr>
<td align="right">
Capability %:
</td>
<td>
#Html.EditorFor(model => item.rfds.capability)
</td>
</tr>
<tr>
<td colspan="2">
<hr />
</td>
</tr>
<tr>
<td align="right">
Report Date:
</td>
<td>
#Html.EditorFor(model => item.rfds.submit_date)
</td>
</tr>
<tr>
<td align="right">
Job Number:
</td>
<td>
#Html.EditorFor(model => item.rfds.job_number)
</td>
</tr>
<tr>
<td align="right">
Revision:
</td>
<td>
#Html.EditorFor(model => item.rfds.revision)
</td>
</tr>
<tr>
<td colspan="2">
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="Save" />
</td>
</tr>
</table>
</td>
</tr>
}
}
</table>
</div>

During View data not getting captured in the Controller in ASP.Net Core 2.0 MVC. I am new to ASP.Net core MVC

I am trying to implement Update/Edit functionality in ASP.Net Core using Razor. Below is the view page.
After clicking Submit button the view page is POSTed to the "GetCustomerForEdit" method of the controller as mentioned below in the code. But unfortunately the edited data from the view is not transferred to the controller method "GetCustomerForEdit", parameter "EditCustomer" of type "GetAllCustDetails".
Since i am new to ASP.net Core is there something i am missing or not doing right in the View or Controller?
VIEW CODE:
<form asp-action="GetCustomerForEdit">
<div>
<table class="tables1">
#foreach (var item in Model.Custs)
{
<tr>
<th style="width:300px;" colspan="2">Update Customers
Details</th>
</tr>
<tr style="visibility:hidden">
<td><input asp-for="#item.CustomerId" type="hidden" />/td>
</tr>
<tr>
<td>First Name</td>
<td><input asp-for="#item.FirstName" autofocus
class="textbox1" /></td>
</tr>
<tr>
<td>Last Name</td>
<td><input asp-for="#item.LastName" class="textbox1" />
</td>
</tr>
<tr>
<td>Sex</td>
<td><select asp-for="#item.Sex" class="textbox1" asp-
items="#(new SelectList(ViewBag.listofitems, "Sex", "Sex"))"></select>
</td>
</tr>
<tr>
<td>Age</td>
<td><input asp-for="#item.Age" class="textbox1"
type="text" /></td>
</tr>
<tr>
<td style="width: 177px">Address1</td>
<td><input asp-for="#item.Address1" class="textbox1"
type="text" /></td>
</tr>
<tr>
<td>Address2</td>
<td><input asp-for="#item.Address2" class="textbox1"
type="text" /></td>
</tr>
<tr>
<td>State</td>
<td><input asp-for="#item.State" class="textbox1"
type="text" /></td>
</tr>
<tr>
<td>City</td>
<td><input asp-for="#item.City" class="textbox1"
type="text" /></td>
</tr>
<tr>
<td>Pin</td>
<td><input asp-for="#item.Pin" class="textbox1"
type="text" /></td>
</tr>
<tr>
<td>Phone</td>
<td><input asp-for="#item.Phone" class="textbox1"
type="text" /></td>
</tr>
<tr>
<td>Mobile</td>
<td><input asp-for="#item.Mobile" class="textbox1"
type="text" /></td>
</tr>
<tr>
<td>Email</td>
<td><input asp-for="#item.Email" class="textbox1"
type="text" /></td>
</tr>
}
<tr class="trfooter">
<td colspan="2">
<input class="submit" type="submit" value="Save" />
<input type="reset" class="submit" value="Reset" />
<input type="button" class="submit" value="Cancel" />
</td>
</tr>
</table>
#if (TempData["RecordSave"] != null)
{
<p>#TempData["RecordSave"]</p>
}
</div>
</form>
MODEL CODE:
public class GetAllCustDetails
{
public int CustomerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Customer> Custs;
}
Where Customer model:
public class Customer
{
public int CustomerId { get; set; }
[Required(ErrorMessage =" Please enter First Name!")]
public string FirstName { get; set; }
[Required(ErrorMessage =" Please enter Last Name!")]
public string LastName { get; set; }
[Required(ErrorMessage =" Please enter Sex!")]
public string Sex { get; set; }
[Range(0,99)]
[Required(ErrorMessage =" Please enter valid Age!")]
public int Age { get; set; }
[Required(ErrorMessage =" Please enter valid Adddress!")]
public string Address1 { get; set; }
public string Address2 { get; set; }
[Required(ErrorMessage =" Please enter State!")]
public string State { get; set; }
[Required(ErrorMessage =" Please enter valid State!")]
public string City { get; set; }
[Required(ErrorMessage =" Please enter valid Pin!")]
public int Pin { set; get; }
public long Phone { set; get; }
public long Mobile { get; set; }
[EmailAddress(ErrorMessage =" Please enter valid Email!")]
[Required(ErrorMessage = "Email is required field!")]
public string Email { get; set; }
}
CONTROLLER CODE: [HttpGet is working fine]
[HttpGet]
public IActionResult GetCustomerForEdit(Int16? Id)
{
GetAllCustDetails getCustForEdit;
clsCustomerDAL getCust;
getCust = new clsCustomerDAL();
getCustForEdit = getCust.GetCustomerForUpdate(Id);
SexDropDown();// this is dropdown getting populated from DB
return View(getCustForEdit);
}
[HttpPost]
public IActionResult GetCustomerForEdit([Bind] GetAllCustDetails
EditCustomer)
{
bool retVal = false;
int CustId = 0;
string Fname;
string Lname;
if(ModelState.IsValid)
{
clsCustomerDAL updateCust = new clsCustomerDAL();
retVal = updateCust.DALEditCustomer(EditCustomer);
if(retVal == true)
{
ModelState.Clear();
}
return View("getCustomerDetails");
}
return View("IndexPage");
}
Since you need to pass a List of Customer from View to controller, for model binding, you could specify name property for each input.
Edit view:
#model GetAllCustDetails
<form asp-action="GetCustomerForEdit">
<div>
<table class="tables1">
#{int i = 0;}
#foreach (var item in Model.Custs)
{
<tr>
<th style="width:300px;" colspan="2">
Update Customers
Details
</th>
</tr>
<tr style="visibility:hidden">
<td><input asp-for="#item.CustomerId" type="hidden" name="Custs[#i].CustomerId" />/td>
</tr>
<tr>
<td>First Name</td>
<td>
<input asp-for="#item.FirstName" name="Custs[#i].FirstName" autofocus class="textbox1" />
</td>
</tr>
//other <tr> properties
<tr>
<td>Email</td>
<td>
<input asp-for="#item.Email" name="Custs[#i].Email" class="textbox1" type="text" />
</td>
</tr>
i++;
}
<tr class="trfooter">
<td colspan="2">
<input class="submit" type="submit" value="Save" />
<input type="reset" class="submit" value="Reset" />
<input type="button" class="submit" value="Cancel" />
</td>
</tr>
</table>
#if (TempData["RecordSave"] != null)
{
<p>#TempData["RecordSave"]</p>
}
</div>
</form>
Post action:
[HttpPost]
public IActionResult GetCustomerForEdit([Bind] GetAllCustDetails EditCustomer)

Space generated in action string

I am building a Asp.Net Core 2.1 EF MVC solution.
Instead of writing separate lines for each CRUD button (Edit, Create, Delete) in each of my Index views, I am trying to generate the buttons dynamically from a partial view as follows.
Models/AdmSchool
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace FACEZ.Models
{
public partial class AdmSchool
{
[Display(Name = "Id")]
public int AdmSchoolId { get; set; }
[Required]
[MaxLength(10)]
[Display(Name = "Code")]
public string AdmSchoolCode { get; set; }
[Required]
[MaxLength(100)]
[Display(Name = "School Name")]
public string AdmSchoolDescr { get; set; }
[MaxLength(100)]
[Display(Name = "Generic Email Principal")]
public string EmailPrincipal { get; set; }
[MaxLength(100)]
[Display(Name = "Generic Email Accounts")]
public string EmailAccounts { get; set; }
[MaxLength(100)]
[Display(Name = "Generic Email Registrar")]
public string EmailRegistrar { get; set; }
[Display(Name = "Obsolete")]
public bool Obsolete { get; set; }
}
}
Views/Shared/_IndividualButtonPartial
#model FACEZ.Models.IndividualButtonPartial
<a type="button" class="btn btn-sm #Model.ButtonType"
href="#Url.Action(Model.Action) #Model.ActionParameters">
<span class="glyphicon glyphicon-#Model.Glyph"></span>
<span class="sr-only">#Model.Text</span>
</a>
Views/Shared/_TableButtonPartial
#model FACEZ.Models.IndividualButtonPartial
<td style="width: 150px;">
<div class="btn-group" role="group">
#await Html.PartialAsync("_IndividualButtonPartial",
new IndividualButtonPartial {
Action="Edit",
ButtonType="btn-primary",
Glyph = "pencil",
Text = "Edit",
Id=Model.Id
})
#await Html.PartialAsync("_IndividualButtonPartial",
new IndividualButtonPartial {
Action="Details",
ButtonType="btn-success",
Glyph = "list",
Text = "Details",
Id=Model.Id
})
#await Html.PartialAsync("_IndividualButtonPartial",
new IndividualButtonPartial {
Action="Delete",
ButtonType="btn-danger",
Glyph = "trash",
Text = "Delete",
Id=Model.Id
})
</div>
</td>
Areas/Adm/Views/AdmSchools/Index.cshtml
#using Microsoft.EntityFrameworkCore.SqlServer.Query.ExpressionTranslators.Internal
#model IEnumerable<FACEZ.Models.AdmSchool>
#{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
<div class="form-border">
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.AdmSchoolCode)
</th>
<th>
#Html.DisplayNameFor(model => model.AdmSchoolDescr)
</th>
<th>
#Html.DisplayNameFor(model => model.EmailPrincipal)
</th>
<th>
#Html.DisplayNameFor(model => model.EmailAccounts)
</th>
<th>
#Html.DisplayNameFor(model => model.EmailRegistrar)
</th>
<th>
#Html.DisplayNameFor(model => model.Obsolete)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.AdmSchoolCode)
</td>
<td>
#Html.DisplayFor(modelItem => item.AdmSchoolDescr)
</td>
<td>
#Html.DisplayFor(modelItem => item.EmailPrincipal)
</td>
<td>
#Html.DisplayFor(modelItem => item.EmailAccounts)
</td>
<td>
#Html.DisplayFor(modelItem => item.EmailRegistrar)
</td>
<td>
#Html.DisplayFor(modelItem => item.Obsolete)
</td>
<td>
#await Html.PartialAsync("_TableButtonPartial", new IndividualButtonPartial {Id=item.AdmSchoolId})
#* I am trying to replace the following code with the line above
<a asp-action="Edit" asp-route-id="#item.AdmSchoolId">Edit</a> |
<a asp-action="Details" asp-route-id="#item.AdmSchoolId">Details</a> |
<a asp-action="Delete" asp-route-id="#item.AdmSchoolId">Delete</a>
*#
</td>
</tr>
}
</tbody>
</table>
When I run the app, I can see the school info in the Index view.
However, the action link that is being created, is getting a space in it from somewhere?
like https://localhost:44399/Adm/AdmSchools/Edit /1 instead of
like https://localhost:44399/Adm/AdmSchools/Edit/1
How can i remove the space after the action name.
In your _IndividualButtonPartial you do have a space between #Url.Action(Model.Action) and #Model.ActionParameters. This is what is getting reflected.

Value of HttpFileCollectionBase Isnull on Postback

I'm curious instead of using HTTPFileWrapper, i created a model with HttpFileCollectionBase type of property.
public class UserLoginModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "password")]
public string Password { get; set; }
public HttpFileCollectionBase Resume { get; set; }
}
My View
#using (Html.BeginForm("", "User", FormMethod.Post, new { enctype = "multipart/form-data", #class = "form-horizontal" }))
{
// #Html.AntiForgeryToken()
<table>
<tr>
<td>
#Html.LabelFor(x => x.UserName)
</td>
<td>
#Html.EditorFor(x => x.UserName)
</td>
</tr>
<tr>
<td>
#Html.LabelFor(x => x.Password)
</td>
<td>
#Html.EditorFor(x => x.Password)
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="login" onclick="return Upload();">
</td>
</tr>
<tr>
<td colspan="2">
#Html.TextBoxFor(x => x.Resume, new { type = "file" })
</td>
</tr>
<tr>
<td colspan="2">
#Html.ValidationSummary(true)
</td>
</tr>
</table>
}
And my Controller for postback
[HttpPost]
public ActionResult Index(UserLoginModel obj)
but when I checked the value of model.Resume on the controller the value was null. what could be the reason for that? thanks
You using the wrong class. Your property needs to be HttpPostedFileBase
public class UserLoginModel
{
....
public HttpPostedFileBase Resume { get; set; }
}

Cannot Access ViewModel Class member inside razor view

I cannot access a member of my class inside the view. All other members are accessible.
The following member "ListOfCategories" is not available in intellisense or at run time inside the view.
Error: There is no ViewData item of type 'IEnumerable' that has the key 'ListOfCategories'
My ViewModelClass
public class ArticleEditViewModel
{
public int ID { get; set; }
[Required]
public string Title { get; set; }
public List<Category> ListOfCategories = new List<Category>();
}
My Razor View
#model rrrr.ViewModels.Article.ArticleEditViewModel
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_LayoutSecure.cshtml";
}
<div>
#Html.ActionLink("Back to Articles", "Index")
</div>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.ID)
<div class="tableHeader">
<h2>Update Article</h2>
</div>
<table id="RegistrationForm">
<tbody>
<tr>
<td>Title</td>
<td>
#Html.TextBoxFor(model => model.Title, new { #class = "registerinput" })
</td>
<td class="leftWarning">
#Html.ValidationMessageFor(model => model.Title)
</td>
</tr>
<tr>
<td>Category</td>
<td>
#Html.DropDownList(model => model.ListOfCategories, Model.CategoryID)
</td>
<td class="leftWarning">
#Html.ValidationMessageFor(model => model.CategoryID)
</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="Update Article" class = "css_button_4" />
</td>
</tr>
</tbody>
</table>
}
Use DropdownListFor instead. The code will be something like this:
#Html.DropDownListFor(model => model.CategoryId, Model.ListOfCategories.Select(c => new SelectListItem { Text = c.CategoryName, Value = c.CategoryId }))