Trouble with MVC 4 DropDownListFor - c#

I am having trouble with displaying Dropdownlist in MVC 4 application.
It looks straightforward, However something is still missing which is not getting hold of.
ViewModel
public class vendorModel
{
public int vendorID { get; set; }
public int vendorTypeID { get; set; }
public string vendorName { get; set; }
public IEnumerable<vendorTypeModel> vendorTypes { get; set; }
}
public class vendorTypeModel
{
public int vendorTypeID { get; set; }
public string vendorTypeName { get; set; }
}
Controller
[HttpGet]
public ActionResult Vendor() {
vendorModel oVendor = new vendorModel();
oVendor.vendorTypes = blVendor.getAllVendorTypes();
return View(oVendor);
}
getAllVendorTypes Method
This is where I am fetching records from database and building and returning a List<vendorTypeModel> object.
and Finally on View am using following code.
#Html.DropDownListFor(m => m.vendorTypeID, new SelectList(Model.vendorTypes,"vendorTypeID","vendorTypeName"))
What am I doing wrong? I am getting following results on screen.
Instead of names of vendors.
Please suggest whats wrong with my code.

I suspect that oVendor.vendorTypes = blVendor.getAllVendorTypes(); may return a wrong list back. Set a breakpoint and check the oVendor.vendorTypes please.

According to https://stackoverflow.com/a/15195354/6741868, you could try alternative syntax such as:
#Html.DropDownListFor(m => m.vendorTypeID, Model.vendorTypes.Select(vendor => new SelectListItem()
{
Text = vendor.vendorTypeName,
Value = vendor.vendorTypeID
})

Related

I am using a List which contains items, in the view but it throws conversion error, why?

I am using .net core with EF and Razor pages.
List<BloodGroups> ListBloodGroups;
public void OnGet()
{
BloodGroupsModel.ListBloodGroups = _donorsDBContext.GetBloodGroups();
}
bloodgroups.cs
public class BloodGroups
{
public BloodGroups()
{
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int BloodGroupID { get; set; }
public string BloodGroupName { get; set; }
public List<BloodGroups> ListBloodGroups { get; set; }
}
in view
<select asp-for="BloodGroupsModel.BloodGroupID" asp-items="Model.BloodGroupsModel.ListBloodGroups"></select>
but error is
Cannot convert generic list to IEnumerable.
I a bit new to this and tried but it's not working I think it should have worked because technically I am calling methods based on model.
In DonorsDBContext class
public List<BloodGroups> GetBloodGroups()
{
var list = new List<BloodGroups>();
list = this.BloodGroups.ToList();
return list;
}
Change your code like below:
<select asp-for="BloodGroupsModel.BloodGroupID"
asp-items="#(new SelectList(Model.BloodGroupsModel.ListBloodGroups,"BloodGroupID","BloodGroupName"))"></select>
Be sure ListBloodGroups in your backend contains data.
My testing data in backend:
public BloodGroups BloodGroupsModel { get; set; }
public IActionResult OnGet()
{
BloodGroupsModel = new BloodGroups();
BloodGroupsModel.ListBloodGroups = new List<BloodGroups>()
{
new BloodGroups(){BloodGroupID=1,BloodGroupName="aaa"},
new BloodGroups(){BloodGroupID=2,BloodGroupName="bbb"},
new BloodGroups(){BloodGroupID=3,BloodGroupName="ccc"}
};
return Page();
}
Try this:
public List<SelectListItem> GetBloodGroups()
{
return _donorsDBContext.Select( i=> new SelectListItem
{
Value = i.BloodGroupID.ToString(),
Text = i.BloodGroupName
}).ToList();
}
and change your BloodGroups:
public List<SelectListItem> ListBloodGroups {get; set;}

Search method by string value MVC 5

A a part of my project i need to find a way to search my object by a string and show a result in view. Your help is appreciated.
in my MainMedia view i have a sidesection were i manually pass a string value to a SearchMedia method:
#section SideBar{
<ul>
<li> #Html.ActionLink("Astronomy", "SearchMedia", new {searchString = "Astronomy" })</li>
<li> #Html.ActionLink("World", "SearchMedia", new { searchString = "World" })</li>
<li> #Html.ActionLink("Movies", "SearchMedia", new { searchString = "Movies" })</li>
</ul>
}
This method should check every object if TagsEnum string and then display an object in SearchMedia view.
Here is my Media class
public class Media
{
public int Id { get; set; }
public string title { get; set; }
public string description { get; set; }
public string body { get; set; }
public string ImagePath { get; set; }
public string VideoLink { get; set; }
public string Source { get; set; }
public string tags { get; set; }
public TagsEnum TagsEnum { get; set; }
}
TagsEnum Class
public enum TagsEnum
{
[Display(Name = "Astronomy and space")]
Astronomy,
[Display(Name = "World around us")]
World,
[Display(Name = "Movies, video")]
Movies
}
and finaly MediaMainController SearchMedia method
public ActionResult SearchMedia(string searchString)
{
db.Medias.Where(i => i.TagsEnum.ToString() == searchString);
return View(db.Medias.OrderBy(it => it.Title));
}
As i understand .Where() should find a match and return an object, however it is not working. How i can sort it out? Perhaps there are other ways to do it? Thank you
Update
I have changed it like this:
var result = db.Medias.Where(TagsEnum => TagsEnum.ToString() == searchString);
return View(result.OrderBy(it => it.title));
but i still dont see the results to be sorted by search
Update 2
I have a class MediaViewModel which i use to create a list of objects, it looks like this:
public class MediaViewModel
{
public List<Media> media { get; set; }
public List<Video> video { get; set; }
}
If i set up SearchMedia View like this
#model PhClub.Models.MediaViewModel
#foreach (var b in Model.media)
{}
i'm getting an error:
The model item passed into the dictionary is of type System.Linq.Enumerable+WhereListIterator 1[PhClub.Models.Media], but this dictionary requires a model item of type PhClub.Models.MediaViewModel.
If i set it up as
`#model IEnumerable<PhClub.Models.Media>
#foreach (var b in Model)
{}`
it is saying Values of type 'Media' can not be converted to string.
I think i need to change SearchMedia method to support MediaView class, but i didnt figure it out yet. Help is appreciated
You should assign it to a variable and use it,
var result = db.Medias.Where(i => i.TagsEnum.ToString() == searchString);
return View(result.OrderBy(it => it.Title));

Loading items from entity framework created database into dropdownlistfor helper

I have been struggling with a loading a display list of items from a database table that was created through the entity framework.
I have found code examples online but many have a static list of items created and then added to the dropdown list list like.
http://www.aspnetmvcninja.com/general/asp-net-mvc-dropdown-list-example. I found an article by Scott Allen that is the basis for what I have (http://odetocode.com/Blogs/scott/archive/2010/01/18/drop-down-lists-and-asp-net-mvc.aspx) but I think that issue is that Im not correctly loading the data into _jobs?
Here is the code that I have in my controller and other classes, any help or guidance is greatly appreciated as I feel that Im so close and yet not.
public class JobsController : Controller
{
var tasks = db.JobTypes.Select(c => new SelectListItem {Value = c.JobTypeID.ToString(), Text = c.JobDescription});
ViewBag.JobTypeAllNames = tasks;
return View();
}
I have two classs that are being used for my entity framework code first. The Job class references the JobTypes class.
public class Job
{
[Key]
[Display(Name="Job ID")]
public int JobID { get; set; }
[Display(Name = "Job Type")]
public int JobTypesID
{
get;
set;
}
private readonly List<JobType> _jobs;
public IEnumerable<SelectListItem> JobTypeItems
{
get
{
return new SelectList(_jobs, "JobTypesID", "JobDescription",1);
}
}
}
public class JobType
{
public int JobTypeID { get; set; }
[Display(Name = "Task")]
public string JobDescription { get; set; }
}
In my view I have
#Html.DropDownListFor(model => model.JobTypesID, Model.JobTypeItems);
This is not going to compile:
public class JobsController : Controller
{
var tasks = db.JobTypes.Select(c => new SelectListItem {Value = c.JobTypeID.ToString(), Text = c.JobDescription});
ViewBag.JobTypeAllNames = tasks;
return View();
}
You need to have an action that will return an ActionResult and I would use a model like you have within your view rather than use the ViewBag:
public class JobsController : Controller
{
public ActionResult Index()
{
var model = new Job();
var tasks = db.JobTypes.Select(c => new SelectListItem {Value = c.JobTypeID.ToString(), Text = c.JobDescription});
model.JobTypeItems = tasks;
return View(model);
}
}
ps You will need to adapt your Job model to include a setter and remove un-used _jobs:
public class Job
{
[Key]
[Display(Name="Job ID")]
public int JobID { get; set; }
[Display(Name = "Job Type")]
public int JobTypesID
{
get;
set;
}
public IEnumerable<SelectListItem> JobTypeItems
{
get; set;
}
}

MVC3 POST model binding not working for particular complex model

For some reason, when I post this view model back to the controller and add in the model for binding, it ends up being null. The application that I am working with is a massive one. Also I haven't written much of the code so this model is massive so I will just add the parts that matter, but could other properties be preventing the model binding?
I do know that it has been working but in the last little bit it started not. Maybe it's not even something with the model, would just love some help debugging it.
POST Action:
[HttpPost]
public ActionResult Categories(int applicationId, SqsApplicationViewModel model)
{
// Save away the ids they chose
_sqsApplicationCategoryService.SaveCategories(applicationId, model.Display_Categories.Where(i => i.Selected).Select(i => i.CategoryId).ToList());
// Complete the step
_sqsApplicationStepService.CompleteStep(applicationId, SqsStep.Categories);
return RedirectToAction("Documents");
}
View Model:
public class SqsApplicationViewModel : IMappable
{
public int Id { get; set; }
public int SupplierId { get; set; }
public int? SqsApprovalLevelId { get; set; }
// Other properties .....
public List<SqsChosenCategoryViewModel> Display_Categories { get; set; }
// Other properties .....
}
public class SqsChosenCategoryViewModel
{
public int CategoryId { get; set; }
public string Name { get; set; }
public string CategoryAmountString { get; set; }
public bool Selected { get; set; }
public IList<SqsDocumentComplianceViewModel> Documents { get; set; }
}
View:
#using (Html.BeginForm())
{
#Html.HiddenFor(m => m.Id)
#if (Model.Display_Categories != null && Model.Display_Categories.Count() > 0)
{
for (var i = 0; i < Model.Display_Categories.Count; i++)
{
#Html.HiddenFor(m => m.Display_Categories[i].CategoryId)
#Html.CheckBoxFor(m => m.Display_Categories[i].Selected)
#Model.Display_Categories[i].Name
}
}
}
Also, the values being sent back in firebug are:
Id:1061
Display_Categories[0].CategoryId:4
Display_Categories[0].Selected:true
Display_Categories[0].Selected:false
Display_Categories[1].CategoryId:1
Display_Categories[1].Selected:false
Display_Categories[2].CategoryId:2
Display_Categories[2].Selected:false
Display_Categories[3].CategoryId:3
Display_Categories[3].Selected:false
Display_Categories[4].CategoryId:6
Display_Categories[4].Selected:true
Display_Categories[4].Selected:false
Display_Categories[5].CategoryId:8
Display_Categories[5].Selected:false
Display_Categories[6].CategoryId:10
Display_Categories[6].Selected:false
Display_Categories[7].CategoryId:7
Display_Categories[7].Selected:false
Display_Categories[8].CategoryId:9
Display_Categories[8].Selected:false
Display_Categories[9].CategoryId:11
Display_Categories[9].Selected:false
Display_Categories[10].CategoryId:5
Display_Categories[10].Selected:true
Display_Categories[10].Selected:false
-------------EDIT----------------
I tried using the following test models and it worked. Is it possible that another property in the Model could be hindering the binding? I added some random ones in these too and it still worked.
public class TestViewModel
{
public int Id { get; set; }
public IList<TestSubViewModel> Display_Categories { get; set; }
public string TestProp { get { return "asdfasdfasdf"; } }
public TestSubViewModel TestGetFirst { get { return this.Display_Categories.FirstOrDefault(); } }
}
public class TestSubViewModel
{
public int CategoryId { get; set; }
public string Name { get; set; }
public string CategoryAmountString { get; set; }
public bool Selected { get; set; }
public IList<SqsDocumentComplianceViewModel> Documents { get; set; }
}
So I'm just going to answer my own question, though it isn't solved as much as there is another way to do it.
I believe that when you typehint the model and it binds it, in the background it uses "TryUpdateModel()" and so I just called this in the controller and for some reason it worked. Not sure if I miss out on anything else by doing it this way, but it has worked for me.
Also you can debug what might be the issue by doing it this way by the following:
var model = new ViewModel();
var isSuccess = TryUpdateModel(model);
if (!isSuccess)
{
foreach (var modelState in ModelState.Values)
{
foreach (var error in modelState.Errors)
{
Debug.WriteLine(error.ErrorMessage);
}
}
}
Taken from this post: How to find the exceptions / errors when TryUpdateModel fails to update model in asp.net mvc 3

Reducing Ajax data footprint by binding on a DataTable with nested objects?

There seems to be many questions relating to binding on a DataTable, but none that I could find touch on my exact situation.
I'm currently ajax binding on a list of objects like such:
public class MyObject
{
public string Name { get; set; }
public string Something1{ get; set; }
public string Something2{ get; set; }
public string Something3 { get; set; }
public MyObjectMyObject2 { get; set; }
}
public class MyObject2
{
public string Color { get; set; }
public string Something4 { get; set; }
}
[GridAction]
public ActionResult GetData()
{
var data = QueryDatabaseAndInstantiateAListOfMyObjects();
return View(new GridModel(data));
}
And with a view like such:
<%= Html.Telerik().Grid<MyObject>()
.DataBinding(dataBinding => dataBinding.Ajax().Select("GetData", new { action = "GetData" }))
.Name("Grid1")
.Columns(columns =>
{
columns.Bound(o => o.Name).Title("Name1");
columns.Bound(o => o.MyObject2.Color).Title("Color");
columns.Bound(o => o.Something1).Hidden(true);
columns.Bound(o => o.Something2).Hidden(true);
columns.Bound(o => o.Something3).Hidden(true);
columns.Bound(o => o.MyObject.Something4).Hidden(true);
})
%>
This works great and all as I'm able to sort, group, and all the above.
My situation is I have many properties on MyObject and some edges cases are popping up that are yielding a couple megabytes of response data. The reason being there are many many hidden columns that are situational dependent that a user can right-click to show. The problem is, data for all these extra hidden columns are included in the response data even when they're not used per say. And since the act of grouping, un-grouping, showing and hiding columns fetches for data anyways, why does all the extra data have to come with it?
If I could have only the data returned that is necessary to populate the visible columns plus say a couple that I could mark somehow with a custom attribute, that would immensely help cut back on the size of the returned data.
So I took to converting my list of objects to a DataTable that I could then conditionally add columns + data for and then feed that to the GridModel. This worked well up until trying to group by a column that is in a nested object such as o.MyObject2.Color.
I run into this exception:
Property with specified name: MyObject2.Color cannot be found on type: System.Data.DataRowView
I guess this makes sense, but how do I overcome this? When I use Object Shredder, it sets each property of MyObject loosely typed such as ["Name"] as a string and ["MyObject2"] as a MyObject2. But everything past ["MyObject2"] is strongly typed: (dataRow["MyObject2"] as MyObject2).Color. And this is where is gets over my head.
Is there another way to overcome my initial issue of all that extra data being sent that isn't used? Or, is there any advice with the DataTable bit? I've also tried converting the DataTable to a IEnumerable with no such luck. The serialized Json is quite empty. I've also tried flattening all nested objects such as having datarow["MyObject2.Color"] as string, but this wreaks havok when referencing this column in JavaScript so I had to go with an underscore delimiter ["MyObject2_Color"] but this really screws up binding Columns in the UI. There has to be a way!
I don't see any reason to bring back your full object just to show Color and Something4. Try flattening it out. Something like this where you just assign the values of Color and Something4 to the properties of the model.
public class MyObject
{
public string Name { get; set; }
public string Something1{ get; set; }
public string Something2{ get; set; }
public string Something3 { get; set; }
public string Something4 { get; set; }
public string Color { get; set; }
}
[GridAction]
public ActionResult GetData()
{
var data = QueryDatabaseAndInstantiateAListOfMyObjects();
data.Something4 = MyObject2.Something4;
data.Color = MyObject2.Color;
return View(new GridModel(data));
}
This is the true Answer, but I'm giving credit to Alfalfa for the idea.
I continue along with the DataTable idea, but use getters to expose each nested object property. It's a bit conveluded and brittle, but it works!
public class MyObject
{
public string Name { get; set; }
public string Something1{ get; set; }
public string Something2{ get; set; }
public string Something3 { get; set; }
[ScriptIgnore()]
public MyObjectMyObject2 { get; set; }
public string Color { get { return this.MyObject2.Color; } }
public string Something4 { get { return this.MyObject2.Something4; } }
}
public class MyObject2
{
public string Color { get; set; }
public string Something4 { get; set; }
}

Categories

Resources