ASP.NET MVC get data from another table and link together - c#

I'm creating a system which lists all of data employees and their email and ext etc. I've got this working fine with a search.
Model:
namespace ServiceDirectory.Models
{
[Table("Employee")]
public class Employee
{
[Key]
public int EmployeeID { get; set; }
[DisplayName("First Name")]
public String Forename { get; set; }
[DisplayName("Surname")]
public String Surname { get; set; }
public String Ext { get; set; }
public String Email { get; set; }
public bool Active { get; set; }
}
}
View:
#model IEnumerable<ServiceDirectory.Models.Employee>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm("Index", "Employee", FormMethod.Get))
{
<b>Search By:</b> #Html.RadioButton("searchBy", "Surname", true) <text>Surname</text>
#Html.RadioButton("searchBy", "Forename") <text>ForeName</text><br />
#Html.TextBox("search") <input type="submit" value="Search" />
}
<table class="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Ext</th>
<th scope="col">Job Title & Location</th>
<th scope="col">Email</th>
</tr>
</thead>
#foreach (var Employee in Model)
{
<tr>
<td>#Employee.Forename #Employee.Surname</td>
<td>#Employee.Ext</td>
<td>Job Title here</td>
<td>#Employee.Email</td>
</tr>
}
</table>
Controller:
namespace ServiceDirectory.Controllers
{
public class EmployeeController : Controller
{
private ApplicationDbContext db;
public EmployeeController()
{
db = new ApplicationDbContext();
}
// GET: Employee
public ActionResult Index(string searchBy, string search)
{
if (searchBy == "Forename")
{
return View(db.Employee.Where(x => x.Forename.StartsWith(search)).Where(e => e.Active).ToList());
}
else
{
return View(db.Employee.Where(x => x.Surname.StartsWith(search)).Where(e => e.Active).ToList());
}
}
protected override void Dispose(bool disposing)
{
db.Dispose();
}
}
}
In my view you will see "Job Title here", what I want to do is get the job title to display for each employee, my issue is that its in another table called EmployeeDetails.
How can I link into EmployeeDetails to get the job title and link it into my employee view?
Any help would be appreciated, this is my 1st project :)

First, create a class (view model) something like this below. You would list down the properties you want to display. I name it EmpVM
public class EmpVM
{
public int EmployeeID { get; set; }
public String Forename { get; set; }
public String Surname { get; set; }
public String Ext { get; set; }
public String Email { get; set; }
public bool Active { get; set; }
public String JobTitle { get; set; }
}
Then in your controller you use Linq join to join Employee table and Employee detail and push the result as EmpVM class
public ActionResult Index(string searchBy, string search)
{
List<EmpVM> Employee = new List<EmpVM>();
var Emp = (from E1 in db.Employee
join E2 in db.EmployeeDetail
on E1.EmployeeID equals E2.EmployeeId
select new EmpVM
{
EmployeeID = E1.EmployeeID,
Forename = E1.Forename,
Surname = E1.Surname,
Ext = E1.Ext,
Email = E1.Email,
Active = E1.Active,
JobTitle = E2.JobTitle
});
if (searchBy == "Forename")
{
Emp.Where(a => a.Forename.StartsWith(search) && a.Active == true);
}
else
{
Emp.Where(a => a.Surname.StartsWith(search) && a.Active == true);
}
Employee = Emp.ToList();
return View(Employee);
}
The view will be very simple. You just need to display the collection. It goes like (remember to replace your own namepsace)
#model IEnumerable<Incendo.Web.Models.EmpVM>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#*Your search method here*#
<table class="table table-condensed ">
#foreach (var item in Model)
{
<tr>
<td>#item.Forename #item.Surname</td>
<td>#item.Ext</td>
<td>#item.Email</td>
<td>#item.JobTitle</td>
</tr>
}
</table>
I have not tested it life but I think it should work. Let me know your result.

You can achieve by having a view model. I assume your EmployeeDetail class like below
public class EmployeeDetail
{
public int Id { get; set; }
public int EmployeeId { get; set; }
public string JobDescription { get; set; }
}
Create a ViewModel for the purpose and name it as EmployeeVM
public class EmployeeVM
{
public List<Employee> Employees { get; set; }
public List<EmployeeDetail> EmployeeDetails { get; set; }
}
In your Controller
public ActionResult Index(string searchBy, string search)
{
List<EmpVM> Employee = new List<EmpVM>();
var Emp = (from E1 in db.Employee
join E2 in db.EmployeeDetail
on E1.EmployeeID equals E2.EmployeeId
select new EmpVM
{
EmployeeID = E1.EmployeeID,
Forename = E1.Forename,
Surname = E1.Surname,
Ext = E1.Ext,
Email = E1.Email,
Active = E1.Active,
JobTitle = E2.JobTitle
});
if (searchBy == "Forename")
{
if (!String.IsNullOrEmpty(search))
{
Emp = Emp.Where(a => a.Forename.StartsWith(search) && a.Active == true);
}
}
else
{
if (!String.IsNullOrEmpty(search))
{
Emp = Emp.Where(a => a.Surname.StartsWith(search) && a.Active == true);
}
}
Employee = Emp.ToList();
return View(Employee);
}
In your View
#model IEnumerable<Incendo.Web.Models.EmpVM>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
<b>Search By:</b> #Html.RadioButton("searchBy", "Surname", true)
<text>Surname</text>
#Html.RadioButton("searchBy", "Forename") <text>ForeName</text>
<br />
#Html.TextBox("search")
<input type="submit" value="Search" />
}
<table class="table table-condensed ">
#foreach (var item in Model)
{
<tr>
<td>#item.Forename #item.Surname</td>
<td>#item.Ext</td>
<td>#item.Email</td>
<td>#item.JobTitle</td>
</tr>
}
</table>

Related

C# Html.ValidationMessageFor not working when form post

I have an issue with validation messages.
Controller:
[HttpGet]
[Authorize]
public ActionResult Others(string bid)
{
return View(ret);
}
[HttpPost]
public ActionResult OthersUser(Others info)
{
return RedirectToAction("Others", "User", new { bid = "1" });
}
[HttpPost]
public ActionResult OthersPass(Others info)
{
if (ModelState.IsValid)
{
}
return RedirectToAction("Others", "User", new { bid = "2" }); ;
}
Password Confirm Class:
public class PassConfirm
{
[Key]
public int ID { get; set; }
public User User { get; set; }
public virtual int UserID { get; set; }
public string Key { get; set; }
[Required]
public string Password { get; set; }
[NotMapped]
[Compare("Password", ErrorMessage = "Passwords not matching!")]
public string ConfirmPassword { get; set; }
}
Others Class:
public class Others
{
public int BID { get; set; }
public PassConfirm PassChg { get; set; }
public String OldPsw { get; set; }
public User User { get; set; }
public string UserCheck { get; set; }
}
View:
<div style="display: flex; align-items: center;">
#using (Html.BeginForm("OthersPass", "User", FormMethod.Post))
{
<table>
<tr>
<td><label for="oldpsw">Eski Şifre:</label></td>
<td>#Html.TextBoxFor(x => x.OldPsw ,new { #id = "oldpsw", #type = "password" })</td>
</tr>
<tr>
<td><label for="newpsw">Yeni Şifre:</label></td>
<td>#Html.TextBoxFor(x => x.PassChg.Password, new { #id = "newpsw", #type = "password" })</td>
<td>#Html.ValidationMessageFor(x => x.PassChg.Password)</td>
</tr>
<tr>
<td><label for="confpsw">Şifreyi Doğrula:</label></td>
<td>#Html.TextBoxFor(x => x.PassChg.ConfirmPassword, new { #id = "confpsw", #type = "password"})</td>
<td>#Html.ValidationMessageFor(x => x.PassChg.ConfirmPassword)</td>
</tr>
</table>
<button class="btn btn-success" formmethod="post">Onayla</button>
}
</div>
When the user clicked the button with the wrong values, it returns nothing. I think the problem is caused by 2 post method. Maybe because of the values ​​returned by ActionResult elements. So what could be the source of the problem?

How to display data from multiple table in list view asp.net MVC 5 or 6 using viewModel

How can I achieve the same result using my view Model
Model 1:
public class Unit
{
public int Id { get; set; }
[Required]
public string UnitName { get; set; }
public virtual ICollection<Staff> Staffs { get; set; }
}
Model 2:
public class Staff
{
public int Id { get; set; }
public string FullName { get; set; }
public int UnitId { get; set; }
public virtual Unit Unit { get; set; }
}
My ViewModel:
public class StaffVM
{
public int Id { get; set; }
public string FullName { get; set; }
public int UnitId { get; set; }
public string UnitName { get; set; }
}
Controller Index function:
// GET: Staffs
public ActionResult Index()
{
var query = from c in db.MyStaff
join d in db.MyUnit on c.UnitId equals d.Id
select new StaffVM
{
Id = c.Id,
FullName = c.FullName,
UnitName = d.UnitName
};
ViewBag.query = query;
return View();
}
My View Index view:
#model IEnumerable<MVC5WAuth.ViewModels.StaffVM>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.FullName)
</th>
<th>
Unit
</th>
<th></th>
</tr>
#foreach (var item in ViewBag.query) {
<tr>
<td>
#item.FullName
</td>
<td>
#item.UnitName
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
#Html.ActionLink("Details", "Details", new { id=item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id=item.Id })
</td>
</tr>
}
</table>

Related data not showing asp.net c#

After reading this tutorial http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/reading-related-data-with-the-entity-framework-in-an-asp-net-mvc-application I have created some models, controllers and views.
The recipes are showing just fine in the view, but I can't get the RecipeLines to show.
RecipeModel
public class RecipeModel
{
[Key]
public int RecipeId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string ImageUrl { get; set; }
public virtual ICollection<RecipeLine> RecipeLines { get; set; }
}
RecipeLine
public class RecipeLine
{
[Key]
public int RecipeLineId { get; set; }
public int RecipeId { get; set; }
public double Quantity { get; set; }
public UnitOfMeasureModel UnitOfMeasure { get; set; }
public IngredientModel Ingredient { get; set; }
}
RecipeViewModel
public class RecipeViewModel
{
public IEnumerable<RecipeModel> RecipeModels { get; set; }
public IEnumerable<RecipeLine> RecipeLines { get; set; }
}
Recipecontroller
public class RecipeController : Controller
{
private RecipeApplicationDb db = new RecipeApplicationDb();
[HttpGet]
public ActionResult Index(int? id)
{
var viewModel = new RecipeViewModel();
viewModel.RecipeModels = db.Recipes
//.Include(i => i.Name)
.Include(i => i.RecipeLines);
if (id != null)
{
ViewBag.RecipeId = id.Value;
viewModel.RecipeLines = viewModel.RecipeModels.Where(i => i.RecipeId == id.Value).Single().RecipeLines;
}
return View(viewModel);
}
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
RecipeModel recipeModel = db.Recipes.Find(id);
if (recipeModel == null)
{
return HttpNotFound();
}
return View(recipeModel);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
And the view
#model RecipeApplication.Models.RecipeViewModel
#{
ViewBag.Title = "Recepten";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
Naam
</th>
<th>
Omschrijving
</th>
<th>
Afbeelding
</th>
</tr>
#foreach (var item in Model.RecipeModels) {
string selectedRow = "";
if(item.RecipeId == ViewBag.RecipeId)
{
selectedRow = "success";
}
<tr class="#selectedRow" valign="top">
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#if (item.ImageUrl != null)
{
#Html.DisplayFor(modelItem => item.ImageUrl)
}
</td>
<td>
#Html.ActionLink("Select", "Index", new { id = item.RecipeId}) |
#Html.ActionLink("Edit", "Edit", new { id=item.RecipeId }) |
#Html.ActionLink("Details", "Details", new { id=item.RecipeId }) |
#Html.ActionLink("Delete", "Delete", new { id=item.RecipeId })
</td>
</tr>
}
</table>
#if (Model.RecipeLines != null)
{
foreach (var item in Model.RecipeLines)
{
string selectedRow = "";
if (item.RecipeId == ViewBag.id)
{
<p>#item.Quantity #item.UnitOfMeasure #item.Ingredient</p>
}
}
}
When selecting the recipe, the line does get a proper color, and I see an id-value in the URL-string.
If someone could help with this one, that would be awesome.
You're comparing item.RecipeId to ViewBag.id, which doesn't exist. The ViewBag member you set in the controller action was ViewBag.RecipeId.
However, you don't need this conditional at all. All of the recipe lines are already for that recipe id, because you specifically set only those recipe items in Model.RecipeLines.
//change your controller action
[HttpGet]
public ActionResult Index(int? id)
{
if(id == null) return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var model = new RecipeViewModel();
var data = db.RecipeModel.Include(i => i.RecipeLines)
.Where(x=>x.RecipeId == id)
.ToList();
model.RecipeModels = data;
return View(model);
}
//change your viewModel
public class RecipeViewModel
{
public IEnumerable<RecipeModel> RecipeModels { get; set; }
}
//this is in the view
#if (Model.RecipeLines != null)
{
foreach (var item in Model.RecipeModels.RecipeLines)
{
<p>
#item.Quantity
#item.UnitOfMeasure
#item.Ingredient
</p>
}
}

Passing parameters on button click in strongly-typed view to another controller

I have a strongly-typed view (bound to userController) which lists the User with particular Roles and below that I have a dropdownlist containing all the Roles with a submit button. All I need is to assign new Role to that User. The ActionResult method is in UserRolesController. how can i pass userId and RoleId on button click to ActionResult Method.
ActionResult Method in UserRolesController:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddRole(UserRole userRole, int roleId, int userId)
{
if (!ModelState.IsValid) return View(userRole);
var check = db.UserRoles.Any(x => x.RoleID == roleId && x.UserID == userId);
if (check)
ViewBag.ResultMessage = "This user already has the role specified !";
else
db.UserRoles.Add(userRole);
db.SaveChanges();
ViewBag.ResultMessage = "User added to the role succesfully !";
return RedirectToAction("Index");
}
View like this:
#model IEnumerable<MvcAppCRUD.user>
#{
ViewBag.title = "AssignRole";
}
<h2>Assign Role</h2>
#if (!Model.Any())
{
#Html.Label("No Roles assigned for this user")
}
else
{
<table>
<tr>
<th>
#Html.DisplayName("Email")
</th>
<th>
#Html.DisplayName("Role Name")
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.email)
</td>
<td>
#Html.DisplayFor(modelItem => item.RoleName)
</td>
<td>
#Html.ActionLink("Delete", "Delete", new {id = item.id})
</td>
</tr>
}
</table>
}
<hr />
<div class="display-label">
#Html.DisplayName("Add Role")
</div>
<div class="display-field">
#Html.DropDownList("Roles", (SelectList) ViewBag.Roles)
</div>
#using (Html.BeginForm("AddRole", "UserRoles"))
{
<div class="message-success">#ViewBag.ResultMessage</div>
}
<p>
<input type="submit" value="Assign" />
</p>
<p>
#Html.ActionLink("Back to List", "Index")
</p>
Model Entities:
public partial class UserRole
{
public int ID { get; set; }
public int UserID { get; set; }
public int RoleID { get; set; }
public int Status { get; set; }
public virtual user Users { get; set; }
public virtual Role Roles { get; set; }
}
public partial class user
{
public user()
{
Roles = new List<SelectListItem>();
}
public long id { get; set; }
public string email { get; set; }
public string password { get; set; }
public System.DateTime reg_date { get; set; }
public byte validated { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
public int RoleId { get; set; }
public string RoleName { get; set; }
public IEnumerable<SelectListItem> Roles { get; set; }
//public IEnumerable<Role> Roles { get; set; }
}
public partial class Role
{
public int ID { get; set; }
public string RoleName { get; set; }
public string Desc { get; set; }
public int Status { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
}
On Button click nothing happens. Is is possible to pass the values as parameters from one model view to another?
There are numerous problems with you code. In particular your passing IEnumerable<user> to the model not including or rendering any controls in your form so nothing posts back, and in any case you cant post back UserRole because its a complex object and a dropdownlist only returns a single value. And there is no point displaying all roles in the dropdown, then checking if its already been selected on postback - just include only those roles that the user does not already have when you create the view. And assigning a message to ViewBag and then redirecting is pointless - its immediately lost.
Create a view model to represent what you want to display and edit (note I have excluded properties for displaying existing roles)
public class UserRoleVM
{
public int ID { get; set; } // user ID for post back
public int Name { get; set; } // user name for display in the view
[Display(Name="Select new role")]
public int SelectedRole { get; set; }
public SelectList RoleList { get; set; }
}
Controller
public ActionResult AddRole(int ID)
{
UserRoleVM model = new UserRoleVM();
var user = // Get the user based on the ID
model.ID = ID;
model.Name = user.??
var roles = // Get all roles and remove those that the user already has
model.RoleList = new SelectList(roles, "ID", "RoleName");
return View(model);
}
View
#model UserRoleVM
#using(Html.BeginForm())
{
<h2>#Model.Name</h2> // users name
#Html.LabelFor(m => m.SelectedRole)
#Html.DropDownListFor(m => m.SelectedRole, Model.RoleList)
<input type="submit" value="Add Role" />
}
Post method
[HttpPost]
public ActionResult AddRole(UserRoleVM model)
{
// model is now populated with the ID of the user and the ID of the selected role
// save and redirect
}

The model item passed into the dictionary is of type 'yyyy', but this dictionary requires a model item of type 'xx'

I have two model and I want to show in one view. So I'm using
#Html.Partial
This is my first Model.
public partial class graduandModel :BaseNopEntityModel
{
public graduandModel()
{
this.AvailableCeremony = new List<SelectListItem>();
}
public string first_name { get; set; }
public string middle_name { get; set; }
public string last_name { get; set; }
public int student_id { get; set; }
public int ceremony_id { get; set; }
public DateTime ceremony_date { get; set; }
public int graduand_id { get; set; }
public IList<SelectListItem> AvailableCeremony { get; set; }
public graduandDegreeModel graduandDegreeGroup { get; set; }
}
This is my second Model.
public class graduandDegreeModel
{
public graduandDegreeModel()
{
this.AvailableDegree = new List<SelectListItem>();
}
public string degree_id { get; set; }
public int graduand_id { get; set; }
public string degree_name { get; set; }
public IList<SelectListItem> AvailableDegree { get; set; }
}
This is mu controller
public ActionResult CheckData(int ceremony_id, string first_name, string middle_name, string last_name)
{
graduandModel model = new graduandModel();
graduandDegreeModel model_1 = new graduandDegreeModel();
var graduandList = _graduandService.GetGraduandByStudent(ceremony_id, first_name, middle_name, last_name);
if (graduandList.Count != 0)
{
model.ceremony_id = ceremony_id;
model.first_name = first_name;
model.middle_name = middle_name;
model.last_name = last_name;
// var degreeList = "";
foreach (var c in graduandList)
{
var degreeList = _graduandDegreeService.getAllDegreeIdBtGraduandId(c.graduand_id);
foreach (var d in degreeList)
{
model_1.AvailableDegree.Add(new SelectListItem() { Text = d.Degree.degree_name, Value = d.degree_id });
}
}
}
return View(model);
}
This is my views
#{
Layout = "~/Views/Shared/_ColumnsThree.cshtml";
}
#model graduandModel
#using Nop.Web.Models.Hire;
#using Nop.Web.Framework;
#using Telerik.Web.Mvc.UI;
#using System.Linq;
#using (Html.BeginForm())
{
<table >
<tr>
<td >
Ceremony :
</td>
<td>
Ceremony at #Model.ceremony_date
</td>
</tr>
<tr>
<td >
Name :
</td>
<td >
#Model.first_name #Model.middle_name #Model.last_name
</td>
</tr>
</table>
<div>
#Html.Partial("_DegreeDetailsByGraduand", Model.graduandDegreeGroup)
</div>
}
This is my Partial view
#{
Layout = "~/Views/Shared/_ColumnsThree.cshtml";
}
#model graduandDegreeModel
#using Nop.Web.Models.Hire;
#using Nop.Web.Framework;
#using Telerik.Web.Mvc.UI;
#using System.Linq;
<table >
<tr>
<td >
AAAAAA
</td>
<td>
#Html.DropDownListFor(model => model.degree_id, Model.AvailableDegree)
#* #Html.ValidationMessageFor(model => model.ceremony_id)*#
</td>
</tr>
</table>
there is error
The model item passed into the dictionary is of type 'Nop.Web.Models.Hire.graduandModel', but this dictionary requires a model item of type 'Nop.Web.Models.Hire.graduandDegreeModel'.
How can I slove it???
You didn't create an instance for graduandModel's graduandDegreeGroup property. So this line:
#Html.Partial("_DegreeDetailsByGraduand", Model.graduandDegreeGroup)
will throw an exception like you said. Simply because the second parameter is NULL.
You can try to modify graduandModel's constructor as below:
public graduandModel()
{
this.AvailableCeremony = new List<SelectListItem>();
this.graduandDegreeGroup = new graduandDegreeModel();
}
The exception should be gone.
You may also find this link helpful: ASP.NET MVC renderpartial, model item passed into the dictionary is of type
Another option for you may be to create a new view model which combines the two models above into one. That way it has properties for all of the data you require for this view. Then you don't need to specify a model in your call to the partial view, it will automatically use the parent's model. Alternatively, you may not need to separate the view into partials at all with the use of a combined model. It is not uncommon to have a unique view model for each different view. In some applications, it can be rare that two different views require the same data.
The combined view model:
public class CheckDataViewModel
{
public CheckDataViewModel ()
{
this.AvailableCeremony = new List<SelectListItem>();
this.AvailableDegree = new List<SelectListItem>();
}
public string first_name { get; set; }
public string middle_name { get; set; }
public string last_name { get; set; }
public int student_id { get; set; }
public int ceremony_id { get; set; }
public DateTime ceremony_date { get; set; }
public int graduand_id { get; set; }
public IList<SelectListItem> AvailableCeremony { get; set; }
public graduandDegreeModel graduandDegreeGroup { get; set; }
public string degree_id { get; set; }
public string degree_name { get; set; }
public IList<SelectListItem> AvailableDegree { get; set; }
}
The combined view:
#{
Layout = "~/Views/Shared/_ColumnsThree.cshtml";
}
#model CheckDataViewModel
#using Nop.Web.Models.Hire;
#using Nop.Web.Framework;
#using Telerik.Web.Mvc.UI;
#using System.Linq;
#using (Html.BeginForm())
{
<table >
<tr>
<td >
Ceremony :
</td>
<td>
Ceremony at #Model.ceremony_date
</td>
</tr>
<tr>
<td >
Name :
</td>
<td >
#Model.first_name #Model.middle_name #Model.last_name
</td>
</tr>
</table>
<div>
<table >
<tr>
<td >
AAAAAA
</td>
<td>
#Html.DropDownListFor(model => model.degree_id, Model.AvailableDegree)
#* #Html.ValidationMessageFor(model => model.ceremony_id)*#
</td>
</tr>
</table>
</div>
}

Categories

Resources