MVC drop down list input post value and name - asp.net

I'm writing a form which uses drop down menus for value selection. I'd like to know if it is possible to post Value and Name of the SelectList back to the Controller or add values for every list item? I need to set LateralityId = Value and LateralityName = Text.
I'll just post some snippets of the code to get the idea across. The model I'm using is
public class Condition
{
public string LateralityName { get; set; }
public string LateralityId { get; set; }
}
and the values are posted with
#Html.DropDownListFor( m => m.Condition.LateralityId, GetLateralities() )
where
public static List<SelectListItem> GetLateralities()
{
return new List<SelectListItem>
{
new SelectListItem { Text = "", Value = "900" },
new SelectListItem { Text = "Left", Value = "1001" },
new SelectListItem { Text = "Right", Value = "1002" },
new SelectListItem { Text = "Midline", Value = "1003" },
new SelectListItem { Text = "Left Midline", Value = "1004" },
new SelectListItem { Text = "Right Midline",Value = "1005" },
new SelectListItem { Text = "Both Sides", Value = "1006" },
new SelectListItem { Text = "Unknown", Value = "990" },
new SelectListItem { Text = "Unspecified", Value = "997" },
new SelectListItem { Text = "N/A", Value = "999" },
};
}
Any help is much appreciated. Thanks!

Solution thanks to Stephen Muecke
In the controller I simply use
LateralityName = GetLateralities().FirstOrDefault( x => x.Value == m.Condition.LateralityId )?.Text;

Related

Error "An item with the same key has already been added" in asp.net MVC

i have added drop with some static value but its showing error
#Html.DropDownListFor(model => model.MRStype, new SelectList(new List
{
new { Value = "0", Text = "--Select--" },enter code here
new {Value = "1", Text = "Internal Issue" },
new { Value = "2" , Text = "External Issue" }
},
"value",
"text"
), new { #class = "form-control", #id = "ddlSourceType" })
Change your Code to this one (use List instead of List)
#Html.DropDownListFor(model => model.GlobalStudentId, new SelectList(new List<object> { new { Value = "0", Text = "--Select--" }, new { Value = "1", Text = "Internal Issue" }, new { Value = "2", Text = "External Issue" } }, "value", "text"), new { #class = "form-control", #id = "ddlSourceType" })

Using an MVC SelectList in webforms

I would like to have grouped items within an asp.net dropdownlist and I thought of using the SelectList functionality from MVC to my webforms project. Here's what I have tried and the result. Can you help please with the binding?
<asp:DropDownList runat="server" id="ddlGroupBySelGeo" AutoPostBack="True"
DataTextField="Text" DataValueField="Value"
SelectMethod="GetMapItems" OnSelectedIndexChanged="ddlGroupBySelGeo_OnSelectedIndexChanged">
</asp:DropDownList>
public SelectList GetMapItems(object sender, EventArgs e)
{
var items = new List<SelectListItem>();
var group1 = new SelectListGroup() { Name = "Select" };
var group2 = new SelectListGroup() { Name = "Group" };
items.Add(new SelectListItem() { Text = "display selected", Value = "select", Group = group1 });
items.Add(new SelectListItem() { Text = GetLocalResourceObject("Region").ToString(), Value = "Regional", Group = group2 });
items.Add(new SelectListItem() { Text = GetLocalResourceObject("Municipality").ToString(), Value = "Municipio", Group = group2 });
items.Add(new SelectListItem() { Text = GetLocalResourceObject("Locality").ToString(), Value = "Localidade", Group = group2 });
items.Add(new SelectListItem() { Text = GetLocalResourceObject("Neighborhood").ToString(), Value = "Bairro", Group = group2 });
return new SelectList(items);
}
Have you tried setting the Value and Text parameters in the SelectList before you return it?
return new SelectList(items, "Value", "Text");

Creating a populated dropdownlist with items in the view

I'm trying to create a dropdownlist that contains a list of items:
#Html.DropDownList("displayCount", new SelectList(
new[]
{
new SelectListItem { Value = "25", Text = "25" },
new SelectListItem { Value = "50", Text = "50" },
new SelectListItem { Value = "100", Text = "100" },
}
));
When I look at my dropdownlist, it just has 3 options that say "System.Web.Mvc.SelectListItem"
What do I need to do differently here?
Try:
#Html.DropDownList("displayCount", new SelectList(
new[]
{
new SelectListItem { Value = "25", Text = "25" },
new SelectListItem { Value = "50", Text = "50" },
new SelectListItem { Value = "100", Text = "100" },
},
"Value",
"Text"
));
You need to tell the SelectList what fields to use:
new SelectList(..., "Value", "Text")
The reason why you got "System.Web.Mvc.SelectListItem" listed in your dropdown is because you didn't specify which attribute of the List Item you want to use for the Text and Value of the dropdown list. Right now, it is being displayed based on the .ToString() of each item in the list, which returns the full name of the SelectListItem class
#Html.DropDownList("displayCount", new SelectList(
new[]
{
new SelectListItem { Value = "25", Text = "25" },
new SelectListItem { Value = "50", Text = "50" },
new SelectListItem { Value = "100", Text = "100" },
},
"Value",
"Text"
));

What's wrong with this linqTOsql self referencing object mapping?

I'm trying to create a self referencing object using linqTOsql mapping. So far, I am definitely in over my head. Here's the code I have:
[Table]
public class Category
{
[Column(IsPrimaryKey=true, IsDbGenerated=true, AutoSync=AutoSync.OnInsert)]
public Int64 catID { get; set; }
public Int64 parentCatID { get; set; }
public string catName { get; set; }
public string catDescription { get; set; }
internal EntityRef<IEnumerable<Category>> _category;
[Association(ThisKey = "parentCatID", Storage = "_category")]
public IEnumerable<Category> category {
get { return _category.Entity; }
set { _category.Entity = value; }
}
}
My fakeRepository is defined like this:
// Fake hardcoded list of categories
private static IQueryable<Category> fakeCategories = new List<Category> {
new Category { catID = 1, parentCatID = 0, catName = "Root", catDescription = "" },
new Category { catID = 2, parentCatID = 1, catName = "Category w/subs", catDescription = "" },
new Category { catID = 3, parentCatID = 1, catName = "Category no subs but now has subs", catDescription = "" },
new Category { catID = 4, parentCatID = 2, catName = "Zub Cat", catDescription = "" },
new Category { catID = 5, parentCatID = 2, catName = "Sub Cat", catDescription = "" },
new Category { catID = 6, parentCatID = 0, catName = "Another Root", catDescription = "" },
new Category { catID = 7, parentCatID = 0, catName = "Ze German Root", catDescription = "" },
new Category { catID = 8, parentCatID = 3, catName = "Brand new cats", catDescription = "" },
new Category { catID = 9, parentCatID = 8, catName = "Brand new cats sub", catDescription = "" },
}.AsQueryable();
I pass Category to the view like this:
public ActionResult CategoryTree()
{
IQueryable<Category> cats = genesisRepository.Category
.Where(x => x.parentCatID == 0)
.OrderBy(x => x.catName);
return View(cats);
}
The problem that I'm running into is that all of this compiles, but I don't get anything beyond the root categories. Model[0].category is returning null.
What is wrong with my self-referencing object?
Edit
I wonder if it's not working because I don't have a real linq-to-sql data context in my fakeRepository. If that's the case, is there a way around that? Can I can get this to work without a connection to a database?
Yeah, you hit the nail on the head. It's not working because you're using a fake repository.
Linq-to-Sql does all the wiring up for you and sets the related collections based on the properties (& their attributes) that you setup in your model.
I don't know how to accomplish this without a connection to the database because internal EntityRef<IEnumerable<Category>> _category; is completely foreign to me - I'm more of a POCO model type of guy.
After a quick google, I found this - How to: Map Database Relationships (LINQ to SQL)
Could you change your model to read:
[Column(IsPrimaryKey=true, IsDbGenerated=true, AutoSync=AutoSync.OnInsert)]
public Int64 CatId { get; set; }
[Column]
public Int64 ParentCatId { get; set; }
[Column]
public string CatName { get; set; }
[Column]
public string CatDescription { get; set; }
private EntitySet<Category> _ChildCategories;
[Association(Storage = "_ChildCategories", OtherKey = "ParentCatId")]
public EntitySet<Category> ChildCategories
{
get { return this._ChildCategories; }
set { this._ChildCategories.Assign(value); }
}
private EntityRef<Category> _ParentCategory;
[Association(Storage = "_ParentCategory", ThisKey = "ParentCatId")]
public Category ParentCategory
{
get { return this._ParentCategory.Entity; }
set { this._ParentCategory.Entity = value; }
}
Now because your ChildCategories is of type EntitySet<Category> (which inherits from IList<T>) you should be able to wire fake relationships up yourself.
So you could do something like this:
private static IQueryable<Category> GetFakeCategories()
{
var categories = new List<Category> {
new Category { CatId = 1, ParentCatId = 0, CatName = "Root", CatDescription = "" },
new Category { CatId = 2, ParentCatId = 1, CatName = "Category w/subs", CatDescription = "" },
//Blah
new Category { CatId = 8, ParentCatId = 3, CatName = "Brand new cats", CatDescription = "" },
new Category { CatId = 9, ParentCatId = 8, CatName = "Brand new cats sub", CatDescription = "" }
};
//Loop over the categories to fake the relationships
foreach (var category in categories)
{
category.ChildCategories = new EntitySet<Category>(); //new up the collection
foreach (var subLoopCategory in categories)
{
if (category.ParentCatId == subLoopCategory.CatId)
category.ParentCategory = subLoopCategory;
if (category.Id == subLoopCategory.ParentCatId)
category.ChildCategories.Add(subLoopCategory);
}
}
return categoies.AsQueryable();
}
It works in my head at least... :-)
HTHs,
Charles
EDIT: Re: Comment below about a null reference on _childCategories.
You could change the model to look like:
private EntitySet<Category> _ChildCategories = new EntitySet<Category>();
It is supposed to be null. You are getting all categories where the ParentId = 0 ... and you don't have a child with an Id of 0. So that seems right to me.
It is not showing any subcategories because it has no subcategories to show. Try this:
IQueryable<Category> cats = genesisRepository.Category
.Where(x => x.parentCatID != 0)
.OrderBy(x => x.catName);
The parentCatId needs to point to a valid CatId for it to be a subcategory. This query should get you all the categories that are subcategories.

How to test custom Model Binders in ASP.NET MVC?

I've written some custom model binders (implementing IModelBinder) in our ASP.NET MVC application. I'm wondering what is a good approach to unittest them (binders)?
I did it this way:
var formElements = new NameValueCollection() { {"FirstName","Bubba"}, {"MiddleName", ""}, {"LastName", "Gump"} };
var fakeController = GetControllerContext(formElements);
var valueProvider = new Mock<IValueProvider>();
var bindingContext = new ModelBindingContext(fakeController, valueProvider.Object, typeof(Guid), null, null, null, null);
private static ControllerContext GetControllerContext(NameValueCollection form) {
Mock<HttpRequestBase> mockRequest = new Mock<HttpRequestBase>();
mockRequest.Expect(r => r.Form).Returns(form);
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Expect(c => c.Request).Returns(mockRequest.Object);
return new ControllerContext(mockHttpContext.Object, new RouteData(), new Mock<ControllerBase>().Object);
}
And then I just passed in the bindingContext variable to the BindModel method of the object that implements the IModelBinder interface.
Here's a simple no-mocks way I wrote for you on my blog assuming you use the ValueProvider and not the HttpContext: http://www.hanselman.com/blog/SplittingDateTimeUnitTestingASPNETMVCCustomModelBinders.aspx
[TestMethod]
public void DateTime_Can_Be_Pulled_Via_Provided_Month_Day_Year_Hour_Minute_Second_Alternate_Names()
{
var dict = new ValueProviderDictionary(null) {
{ "foo.month1", new ValueProviderResult("2","2",null) },
{ "foo.day1", new ValueProviderResult("12", "12", null) },
{ "foo.year1", new ValueProviderResult("1964", "1964", null) },
{ "foo.hour1", new ValueProviderResult("13","13",null) },
{ "foo.minute1", new ValueProviderResult("44", "44", null) },
{ "foo.second1", new ValueProviderResult("01", "01", null) }
};
var bindingContext = new ModelBindingContext() { ModelName = "foo", ValueProvider = dict };
DateAndTimeModelBinder b = new DateAndTimeModelBinder() { Month = "month1", Day = "day1", Year = "year1", Hour = "hour1", Minute = "minute1", Second = "second1" };
DateTime result = (DateTime)b.BindModel(null, bindingContext);
Assert.AreEqual(DateTime.Parse("1964-02-12 13:44:01"), result);
}
dict could be refactored like this
FormCollection form = new FormCollection
{
{ "month1", "2" },
{ "day1", "12" },
{ "year1", "1964" },
{ "hour1", "13" },
{ "minute1", "44" },
{ "second1", "01" }
};
var bindingContext = new ModelBindingContext() { ModelName = "foo", ValueProvider = form.ToValueProvider() };

Resources