MVC DisplayTemplate for Lookup list - asp.net-mvc

I am calling a partial view on which I want to collapse a few dropdown controls(previously created by using DropDownListFor). Because the controls are readonly, I just need to show the selected value on each control. I have created a list called "salutations" in the controller, and pass it as ViewData to my partial view. On the partial view I need to see the selected salutation (e.g.. Mr/Miss/Dr)in my div using #Html.DisplayFor. I tried creating a DisplayTemplate according to an online posting, but I am still having issues getting this to work.
Lookup list declared like this in controller:
var salutations = (IEnumerable<lu_Salutation>)ViewData["salutations‌​"];
Here's my DisplayTemplate named LookupList.cshtml:
#model int
#using System.Linq
#vEmployee.SelectList1.Single(s => s.Value == Model.ToString()).Text
Of course, there's something wrong with the last line of the above code. vEmployee is the name of my model. How do I correct it?, and can I have a generic display template like the GridForeignKey Kendo EditorTemplate so I could easily pass the foreign key, the DisplayTemplate, and the lookup list to get just the text of the selected lookup value displayed?
Ideally, I will just like to have in my partial view, something like:
#Html.DisplayFor(model => model.id, "LookupList", SelectList((IEnumerable)ViewData["salutationList"], "TitleID", "Title"))
where TitleID and Title are respectively the value and text in the lookup list.
Models
public class lu_Salutation
{
public int TitleID { get; set; } // e.g. 1
public string Title { get; set; } // e.g. Mrs
}
ViewModel Class - I want to use just IDs here, but display the matching Texts from the lookup tables (e.g lu_Salutation) when needed
public class vEmployee
{
[Key]
public int EmployeeID { get; set; }
public int SalutationID { get; set; }
}
Controller
[HttpGet]
public ActionResult EmployeeDetails(int employeeID)
{
vEmployee SelectedEmployee = GetEmployees(employeeID).First();
ViewData["salutations"] = _db.lu_Salutation.OrderBy(e => e.Title);
return PartialView("_EmployeeDetails", SelectedEmployee);
}
private IEnumerable<vEmployee>GetEmployees(int employeeID)
{
IEnumerable<vEmployee> emp = (from e in _db.Employees
join c in _db.Contacts on e.EmployeeID equals c.EmployeeID
join u in _db.lu_Salutation on c.SalutationID equals u.TitleID into sal
from u in sal.DefaultIfEmpty()
where (e.EmployeeID == employeeID))
select new vEmployee
{
EmployeeID = e.EmployeeID,
SalutationID = c.SalutationID
}).AsEnumerable().OrderBy(m => m.EmployeeNumber).ThenBy(m => m.FirstName);
return emp;
}

Related

Show dropdownlist in the View

I am working on a project in which, i am getting the client names from database table using the HomeController>Index Action method.
I want to send this list to Index view and display this list in the dropdownlist.
Request you to please help me with the View accordingly as i am new to MVC.
Home Controller
public ActionResult Index()
{
var model = from c in
_mdlCntxtcls.clients
where (DateTime.Now<=c.End_Date)
select c;
return View(model);
}
Model
public class Client
{
public int ClientID { get; set; }
public string Client_Names { get; set; }
public DateTime Start_Date { get; set; }
public DateTime End_Date { get; set; }
}
Please help as early as possible
Thank you
You are passing a collection of Client objects to the view. So your view should be strongly typed to a collection of Client object to accept that as the (view) model data.
You can use the DropDownList html helper method to render a SELECT element from this view model data. You can create a SelectList object from this collection (your page model)
#model IEnumerable<YourNamespaceHere.Client>
#Html.DropDownList("StudentSelect",new SelectList(Model,"ClientID","Client_Names"))
This will render a SELECT element with name attribute value set to StudentSelect. Each options in the SELECT elemtn will have the ClientID as the value attribute value and Client_Names property value as the option text.
You can also use viewbag or viewdata for send list of Client from controller to view and then you can put it in dropdown list.
In Controller you can use like :
List<SelectListItem> ClientList = new List<SelectListItem>();
using (dbContext db = new dbContext())
{
var Clients = db.Client.ToList();
foreach (var i in Clients)
{
ClientList.Add(new SelectListItem { Text = i.Client_Name, Value = i.ClientID.ToString() });
}
}
ViewBag.ClientList = ClientList;
and in view side you can use that viewbag like :
#Html.DropDownListFor(x => x.Client, (IEnumerable<SelectListItem>)ViewBag.ClistList)

MVC - Create object and related objects in one go

I want to create a parent object with child/related objects in the same view.
An example would be: create one Father (with some name) along with all his sons (with their names). I have created a view model:
public class FatherViewModel {
public Father father {get; set;} // has 1 property Name
public List<Son> {get; set;} // has 1 property Name
}
My question is, how do I get the list of Sons back from the view when the post is performed?
I have tried using HiddenFor for each Son id, but no matter what, the list is empty when returned to the controller.
UPDATE:
I tried the Editor Template example by Shyju described below, but my editor is never called.
I have 1 object:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int? FatherId { get; set; }
public virtual ICollection<Person> Children { get; set; }
}
I did this:
Scaffolded a full controller for Person with index, create, edit...
Created EditorTemplates folder in Views->Person
Created Person.cshtml:
#model TestEditorTemplate.Models.Person
<div>
<h4>Child</h4>
#Html.TextBoxFor(s => s.Name)
#Html.HiddenFor(s => s.Id)
</div>
Added #Html.EditorFor(m => m.Children) to Create.cshtml
Questions:
How can #Html.EditorFor(m => m.Children)possibly work with the
editor template when m.Children is a collection of Person and not a single
Person?
I want to create (not edit) a father including children at the same time. That means that I have no Ids to pass to the Create view to start with. How can this work? From the example by Shyju, the Ids are already created beforehand?? Or did I just misunderstand the example?
You can use EditorTemplates to handle this. Here is a working sample.
So i have a viewmodel to represent the father-child relationship
public class PersonVM
{
public int Id { set; get; }
public string Name { set; get; }
public int? ParentId { set; get; }
public List<PersonVM> Childs { set; get; }
}
And in my GET action method, i create an object of my view model and load the Father -childs data to it.
public ActionResult EditorTmp(int id = 1)
{
//Hard coded for demo, you may replace with actual DB values
var person = new PersonVM {Id = 1, Name = "Mike"};
person.Childs = new List<PersonVM>
{
new PersonVM {Id = 2, Name = "Scott", ParentId = 11},
new PersonVM {Id = 2, Name = "Gavin", ParentId = 12}
};
return View(person);
}
Now i will create an EditorTemplate. To do that, Go to your Views folder, and Create a directory called EditorTemplates under the directory which has same name as the controller, and add a view with name PersonVM.cshtml
Now, go to this view and add the below code.
#model ReplaceWithYourNameSpaceNameHere.PersonVM
<div>
<h4>Childs </h4>
#Html.TextBoxFor(s => s.Name)
#Html.HiddenFor(s => s.Id)
</div>
Now let's go back to our main view. We need to make this view strongly typed to our original PersonVM. We will use the EditorFor html helper method in this view to call our editor template
#model ReplaceWithYourNameSpaceNameHere.PersonVM
#using (Html.BeginForm())
{
<div>
#Html.TextBoxFor(s => s.Name)
#Html.HiddenFor(s => s.Id)
</div>
#Html.EditorFor(s=>s.Childs)
<input type="submit"/>
}
Now have an HttpPost method in the controller to handle the form posting
[HttpPost]
public ActionResult EditorTmp(PersonVM model)
{
int fatherId = model.Id;
foreach (var person in model.Childs)
{
var id=person.Id;
var name = person.Name;
}
// to do : Save ,then Redirect (PRG pattern)
return View(model);
}
Now, If you put a break point in your HttpPost action method, you can see the Id's of childs are passed to this action method.
One important thing to remember is, Your Editor Template view's name should be same as the type you are binding to it.

Display description instead of code in .net MVC 5

I have a table where I store all the different code/value keywords that I need in my app:
public class Keyword
{
public int id { get; set;}
public string name { get; set; }
public string valuecode { get; set; }
public string valuename { get; set; }
}
Then I use Keyword to store records like these
name valuecode valuename
.DealState 1 Draft
.DealState 2 Final
.DealState 3 Cancelled
.DealType NEW New Business
.DealType RNW Renewal
.DealType WFA Waiting for approval
Then in other models I have fields that are filled using these keywords. For example,
public class Deal
{
....
public string state { get; set; }
public string type { get; set; }
....
}
I have managed to have the fields filled with "valuecode" while displaying "valuename" in Create and Edit views (I use DropDownList with a SelectList built in the controller), but I cannot find a way to display valuename instead of valuecode in Index and Details views.
I'm trying to pass the same SelectList in the ViewBag for Index, but then I do not know which syntax to use in order to replace the "state" code with the state "description" for each record returned.
Any hint?
PS: I'm quite new to .net and mvc, usually work with RoR and ActiveRecord...
EDIT
In my KeywordController I have a method
public SelectList selectKeywordValues(string kwname, object selectedKeyword = null)
{
var keywordsQuery = from d in db.Keywords
where d.name == kwname
orderby d.valuename
select d;
SelectList kwlist = new SelectList(keywordsQuery, "valuecode", "valuename", selectedKeyword);
return kwlist;
}
Then in my DealController i have the index method
public ActionResult Index()
{
var kw = new KeywordController();
ViewBag.state = kw.selectKeywordValues(".DealState");
return View(db.Deals.ToList());
}
SOLVED
In DealController the index method is the following
public ActionResult Index()
{
var kw = new KeywordController();
SelectList states = kw.selectKeywordValues(".DealState");
SelectList types = kw.selectKeywordValues(".DealType");
foreach (var item in db.Deals.ToList())
{
SelectListItem mystate = states.Where(row => row.Value == item.state).ElementAt(0);
SelectListItem mytype = types.Where(row => row.Value == item.type).ElementAt(0);
item.state = mystate.Text;
item.type = mytype.Text;
}
return View(db.Deals.ToList());
}
Now the db.Deals.ToList() is filled with descriptions and not with codes.
You can define a view model called DealViewModel that contains DealState and DealType properties. Then populate the DealViewModel with joins in LINQ before passing to the views that reference the view model.
Another approach is to use enums in EF5.

The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[System.Int32]'

ASP.Net MVC 4
I am trying to populate a list of Countries (data from Country table in DB) in a dropdownlist. I get the following error:
The model item passed into the dictionary is of type
System.Collections.Generic.List`1[System.Int32]', but this dictionary requires a model item of type 'BIReport.Models.Country'.
I am new to ASP.Net MVC and I don't understand that error. What I feel is what Index method is returning doesn't match with the model that I am using in the View.
Model::
namespace BIReport.Models
{
public partial class Country
{
public int Country_ID { get; set; }
public string Country_Name { get; set; }
public string Country_Code { get; set; }
public string Country_Acronym { get; set; }
}
}
Controller::
public class HomeController : Controller
{
private CorpCostEntities _context;
public HomeController()
{
_context = new CorpCostEntities();
}
//
// GET: /Home/
public ActionResult Index()
{
var countries = _context.Countries.Select(arg => arg.Country_ID).ToList();
ViewData["Country_ID"] = new SelectList(countries);
return View(countries);
}
}
View::
#model BIReport.Models.Country
<label>
Country #Html.DropDownListFor(model => model.Country_ID, ViewData["Country_ID"] as SelectList)
</label>
Where am I going wrong?
You are selecting CountryIDs, therefore you will have a list of integers passed into the view.
I think you really want something like this:
public ActionResult Index()
{
var countries = _context.Countries.ToList();
ViewData["Country_ID"] = new SelectList(countries, "Country_ID", "Country_Name");
return View();
}
I'm not really sure why you have single country as a model for your view.
Update:
I'm still not sure why the model is a country, if you are just going to post the ID of the selected country you don't necessarily need a model at all (or just have an integer). This will be just fine though:
View
#model MvcApplication1.Models.Country
#Html.DropDownListFor(m => m.Country_ID, ViewData["Country_ID"] as SelectList)
the problem is in line 1 of your view. change it like this :
#model IEnumerable<BIReport.Models.Country>
also there is no need to pass the model to view if you already did it by :
ViewData["Country_ID"] = new SelectList(countries);
When you say #model BIReport.Models.Country it means your view is expecting a model consisting single country details. On the contrary you need a list of countries to be displayed in the drop-down list. Hence you should tell the view to look for a list of country details instead.
Therefore #model IEnumerable.

pass an anonymous type to my ASP.NET MVC view

I have a problem, I have the next controller
namespace RolesMVC3.Areas.Administrador.Controllers
{
[Authorize(Roles = "Adminr")]
public class HomeController : Controller
{
private BASEDATOSCJ_2Entities db = new BASEDATOSCJ_2Entities();
public ActionResult Index()
{
string username = User.Identity.Name;
MembershipUser user = Membership.GetUser(username);
Guid key = (Guid)Membership.GetUser().ProviderUserKey;
var Universities = (from u in db.UNIVERSITy
join s in db.CAMPUS_UNIVERSITy on u.IdUniversity equals s.IdUniversity
join c in db.CIUDAD_CAMPUS on s.IdCiudadSede equals c.IdCiudadSede
join co in db.OFFICE on s.Idoffice equals co.Idoffice
join uxc in db.USERxOFFICE on co.Idoffice equals uxc.Idoffice
where uxc.UserId == key
select new { u.Name, namecity = c.Nombre, s.Idoffice}).ToList();
return View(Universities);
}
With this controller I just want send to View u.Name, and s.Idoffice. How I do? (in fact do not know if this controllet is fine), I want to send fields belong to different tables. I want to send the query as a list and present at the View, ViewBag go with it?, How do I pass these data to the view and display with a foreach?.
I use razor
If you change the following line:
select new { u.Name, namecity = c.Nombre, s.Idoffice}
To
select new { Name = u.Name, Idoffice = s.Idoffice }
This only selects the two fields into a list. In your view you can do the following:
#model List<dynamic>
#foreach(dynamic d in Model) {
<p>#d.Name</p>
<p>#d.Idoffice</p>
}
Edit:
You might want to define a ViewModel to contain your data.
public class MyViewModel {
string Name {get;set;}
string Idoffice {get;set;}
}
Now you can change your select statement as follows:
select new MyViewModel { Name = u.Name, Idoffice = s.Idoffice }
And update your Razor file as such:
#model List<MyViewModel>
#foreach(MyViewModel d in Model) {
<p>#d.Name</p>
<p>#d.Idoffice</p>
}
I would use a view model. I have learnt not to expose my domain objects to the view, I rather map my domain object to the view model and return this view model to the view.
Separate you data access logic from your view logic. You can put that whole statement into a repository class and then you just call this method from the controller.
Here is a partial view model, you might have more properties if you need more data to be displayed:
public class UniversityViewModel
{
IEnumerable<University> Universities { get; set; }
}
University class:
public class University
{
public string Name { get; set; }
public string Idoffice { get; set; }
}
In my action method of my controller it would look something like this:
public ActionResult Index(int id)
{
UniversityViewModel viewModel = new UniversityViewModel
{
Universities = universityRepository.GetAll()
};
return View(viewModel);
}
And in my view I would have the following:
<table>
#foreach(University university in Model.Universities)
{
<tr>
<td>Name:</td>
<td>university.Name</td>
</tr>
}
</table>
This is just a basic display of data in the view, you can use 3rd party components to display your data with some features.

Resources