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.
Related
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;
}
Am trying to Bind Dropdown in MVC using Enum and it works great !! Here is sample code
//Enum Set up
public enum Name
{
Name1,
Name2,
Name3
}
public enum Number
{
11,
12,
13
}
public Name nameDropDown { get; set; }
public Number numberDropDown { get; set; }
//Like this i have have 10 Enums
//View
#Html.EnumDropDownListFor(m => m.numberDropDown) or #Html.EnumDropDownListFor(m => m.nameDropDown)
Here is where i got struck !!I am going to load only one dropdown in my view based on the condition. I can have if else if and load the drop down based on the condition. But as i have large list it wont be that good.
Is there a alternative way i can decide which enum to bind in my view ? Like dynamically locating based on the condition. Please suggest
There is no easy way to achieve this. One way would be to create an extension method, something like:
public enum Name { Name1, Name2, Name3 }
public enum Number { Number1, Number2, Number3 }
public class ViewModel
{
public Name nameDropDown { get; set; }
public Number numberDropDown { get; set; }
// x number of other enum properties
}
public static class MyHtmlHelpers
{
public static MvcHtmlString MyEnumDropDownListFor(this HtmlHelper html, string propertyName)
{
var propertyInfo = typeof(ViewModel).GetProperty(propertyName);
if (propertyInfo == null) return null;
var expParam = Expression.Parameter(typeof(ViewModel));
var expProp = Expression.Property(expParam, propertyName);
var expression = Expression.Lambda(expProp, expParam);
var htmlStr = (MvcHtmlString) typeof(SelectExtensions)
.GetMethods()
.First(m => m.Name == "EnumDropDownListFor" && m.IsGenericMethod)
.MakeGenericMethod(typeof(ViewModel), propertyInfo.PropertyType)
.Invoke(null, new object[] { html, expression });
return htmlStr;
}
}
And your view could fetch the property name from the query string and based on that show the dropdown list:
#model ViewModel
#{
var propertyName = Request["property"] ?? "numberDropDown";
}
#Html.MyEnumDropDownListFor(propertyName)
I am new in mvc 4 but getting progress. I'm getting crazy with something which how i can select an item in select list in view model.
here is my controller code;
ViewBag.DepartmanListesi = new SelectList(VeriTabani.UnvanDepartmanlaris, "UDepId", "Departman");
and in my view model I am listing a diffirent database but in this list one field includes an id of the UnvanDepartmanlaris.instead of showing the id, I want to show name of the id. but what I have tried is not worked. can you please help me.
I searched many things but most of them was about how to set dropdownlist. I couldnt find any answer of my question.
Thank you in advance. I will be waiting for any response
Try this,
Controller
public List<CustomerModel> GetCustomerName()
{
// Customer DropDown
using (dataDataContext _context = new dataDataContext())
{
return (from c in _context.Customers
select new CustomerModel
{
CustomerId = c.CID,
customerName = c.CustomerName
}).ToList<CustomerModel>();
}
}
[HttpGet]
public ActionResult CustomerInfo()
{
var List = GetCustomerName();
ViewBag.CustomerNameID = new SelectList(List, "CustomerId", "customerName");
return View();
}
View
#Html.DropDownList("CustomerId", (SelectList)ViewBag.CustomerNameID, "--Select--")
Model
public class CustomerModel
{
public int CustomerId { get; set; }
public string customerName { get; set; }
public List<SelectListItem> customerNameList { get; set; }
}
I'm using following approach. Hope it helps:
Create helper class (I'm having here all my selectlists)
Public static class Helper
{
public static List<SelectListItem> GetList()
{
var result = new List<SelectListItem>();
var ctx = new YourContext();
var items = from n in ctx.Clients
select new SelectListItem
{
Text = n.Client.Name,
Value = n.ClientID.ToString()
};
foreach (var item in items)
result.Add(item);
return result;
}
}
Than in your View:
#Html.DropDownList("GetClients", Helper.GetList())
Works for me.
I'm kind of new to razor MVC, and I'm wondering how can I read the values I return in the view?
My code is like this:
public ActionResult Subject(int Category)
{
var db = new KnowledgeDBEntities();
var category = db.categories.Single(c => c.category_id == Category).name;
var items = from i in db.category_items
where i.category_id == Category
select new { ID = i.category_id, Name = i.name };
var entries = from e in db.item_entry
where items.Any(item => item.ID == e.category_item_id)
select new { ID = e.category_item_id, e.title };
db.Dispose();
var model = new { Name = category, Items = items, Entries = entries };
return View(model);
}
Basically, I return an anonymous type, what code do I have to write to read the values of the anonymous type in my view?
And if this is not possible, what would be the appropriate alternative?
Basically, I return an anonymous type
Nope. Ain't gonna work. Anonymous types are emitted as internal by the compiler and since ASP.NET compiles your views into separate assemblies at runtime they cannot access those anonymous types which live in the assembly that has defined them.
In a properly designed ASP.NET MVC application you work with view models. So you start by defining some:
public class MyViewModel
{
public string CategoryName { get; set; }
public IEnumerable<ItemViewModel> Items { get; set; }
public IEnumerable<EntryViewModel> Entries { get; set; }
}
public class ItemViewModel
{
public int ID { get; set; }
public string Name { get; set; }
}
public class EntryViewModel
{
public int ID { get; set; }
public string Title { get; set; }
}
and then you adapt your controller action to pass this view model to the view:
public ActionResult Subject(int Category)
{
using (var db = new KnowledgeDBEntities())
{
var category = db.categories.Single(c => c.category_id == Category).name;
var items =
from i in db.category_items
where i.category_id == Category
select new ItemViewModel
{
ID = i.category_id,
Name = i.name
};
var entries =
from e in db.item_entry
where items.Any(item => item.ID == e.category_item_id)
select new EntryViewModel
{
ID = e.category_item_id,
Title = e.title
};
var model = new MyViewModel
{
CategoryName = category,
Items = items.ToList(), // be eager
Entries = entries.ToList() // be eager
};
return View(model);
}
}
and finally you strongly type your view to the view model you have defined:
#model MyViewModel
#Model.Name
<h2>Items:</h2>
#foreach (var item in Model.Items)
{
<div>#item.Name</div>
}
<h2>Entries:</h2>
#foreach (var entry in Model.Entries)
{
<div>#entry.Title</div>
}
By the way to ease the mapping between your domain models and view models I would recommend you checking out AutoMapper.
Oh, and since writing foreach loops in a view is kinda ugly and not reusable I would recommend you using display/editor templates which would basically make you view look like this:
#model MyViewModel
#Model.Name
<h2>Items:</h2>
#Html.DisplayFor(x => x.Items)
<h2>Entries:</h2>
#Html.DisplayFor(x => x.Entries)
and then you would define the respective display templates which will be automatically rendered for each element of the respective collections:
~/Views/Shared/DisplayTemplates/ItemViewModel:
#model ItemViewModel
<div>#item.Name</div>
and ~/Views/Shared/DisplayTemplates/EntryViewModel:
#model EntryViewModel
<div>#item.Title</div>
I would like to use Linq and strongly typed views in the right way. at the moment I do the following:
Make a Model to verify agianst:
public class Menu
{
public int Id { get; private set; }
public string Text { get; private set; }
public string Action { get; private set; }
public string Controller { get; private set; }
public string Parameter { get; private set; }
public string Langue { get; private set; }
public Menu(int id, string controller, string action, string parameter, string text)
{
Id = id;
Controller = controller;
Action = action;
Text = text;
Parameter = parameter;
}
Use Linq to get the data from the database into the model:
public static List<Menu> GetTabListForMenu(string langue)
{
Page_dbEntities entity = new Page_dbEntities();
var tabList = (from ml in entity.wpmenulangue
where ml.Langue == langue
from m in entity.wpmenu
where ml.Menu == m.Id
from l in entity.wplangue
where ml.Langue == l.Langue
from p in entity.wppage
where p.Id == m.Page
select new { m.Id, p.Controller, p.Action, p.Parameter, ml.Text}).ToList();
List<Menu> menu = new List<Menu>();
foreach (var item in tabList)
{
menu.Add(new Menu(item.Id, item.Controller, item.Action, item.Parameter, item.Text));
}
return menu;
}
I am pretty convinced that this is not the optimal way to do this and have 2 questions:
When I get the data from the database I first use a var and then have to move it to the object with a foreach. this seems like a waste of both my time and less effeicent then getting it with sql.
I have been told that I can just verify up agianst the entitymodel. Even if i use multiple entities in a view. is this true? (the one telling me this wes not able to get it to work and I have not been able to find anything about it online).
I will try to look back on this post in the next couple of hours, but might have to wait 24 hours.
public static List<Menu> GetTabListForMenu(string langue)
{
Page_dbEntities entity = new Page_dbEntities();
return (from ml in entity.wpmenulangue
where ml.Langue == langue
from m in entity.wpmenu
where ml.Menu == m.Id
from l in entity.wplangue
where ml.Langue == l.Langue
from p in entity.wppage
where p.Id == m.Page
select new Menu(m.Id, p.Controller, p.Action, p.Parameter, ml.Text)
).ToList();
}
As for the validation is concerned you shouldn't use multiple entities in the view. You should use a single entity which is called ViewModel. This ViewModel is a class that represents the data on the view. If you are using DataAnnotations for validation you could decorate this view model properties with attributes that indicate how to be validated.