Reference to the enum from model in Index view - asp.net-mvc

I have a trouble with reference to my enum from model in Index view.
Here is my model's code:
public enum UnitOfMeasure {
Item,
Kilogram,
Liter, }
public class Product {
public Product() {
ProductOccurences = new List<ProductOccurence>(); }
[Key]
public int ProductId { get; set; }
public int ProductPhotoId { get; set; }
public UnitOfMeasure? UnitOfMeasure { get; set; }
public string ProductDescription { get; set; }
public virtual ProductPhoto Photo { get; set; }
public virtual ICollection<ProductOccurence> ProductOccurences { get; set; } }
In Index view I have search fields for filtering specific results. You can also search for UnitOfMeasure value (I use #Html.EnumDropDownListFor) - but I can't refer directly to the enum field from my model - because my view is strongly typed:
#model IEnumerable<Models.Product>
To show this field with the values of the selection I use the trick:
#Html.EnumDropDownListFor(model => model.FirstOrDefault().UnitOfMeasure, "Select unit of measure")
but it's terrible and ugly solution - also with unwanted value loaded by default.
What is the most elegant way to solve this issue in my situation?

You can use EnumHelper like this:
#Html.DropDownList("UnitOfMeasure", EnumHelper.GetSelectList(typeof(UnitOfMeasure)))
OR
You can do like this for strongly typed view:
#{ // you can put the following in a back-end method and pass through ViewBag
var selectList = Enum.GetValues(typeof(UnitOfMeasure))
.Cast<UnitOfMeasure>()
.Select(e => new SelectListItem
{
Value = ((int)e).ToString(),
Text = e.ToString()
});
}
#Html.DropDownListFor(m => m.UnitOfMeasure, selectList)

Related

how to add dropdownlistfor(dynamic object)

I have class include the following objects
public class ProductViewer
{
public J_Items Item { get; set; }
public List<J_ItemsImages> lstItemImages { get; set; }
}
how can i add DropDownListFor Item.ItemName
J_Items definition
public int ID { get; set; }
public string ItemName { get; set; }
public string ItemShortDesc { get; set; }
public string ItemLongDesc { get; set; }
#Html.DropdownlistFor(m => m.Item.ItemName)
Where m is your ProductViewer class, of course that should be made in to a viewmodel.
You can use the first argument of the Html.DropDownListFor() helper method to designate which property you want to bind to and then use the second to supply a collection to populate the actual drop down list with :
<!-- This would bind to the ItemName property, but would populate the list with
the contents of your lstItemImages property -->
#Html.DropDownListFor(m => m.Item.Name, new SelectList(Model.lstItemImages, "Name", "Name"))
Likewise, if you had a collection of values on your J_Items class, you could access those in the second parameter as well:
#Html.DropDownListFOr(m => m.Item.Name, new SelectList(Model.Item.SomeCollection,"Value,"Text")
This assumes that your parent ProductViewer class would be passed into the view.

MVC different models errors

I have trying to use a MetadatType model, but getting an error:
.edmx model/order.cs:
public partial class ORDER
{
public int Order_Number { get; set; }
public string Order_Type { get; set; }
}
metadatatype model:
MetadataType(typeof(ORDERMetadata))]
public partial class ORDER
{
// Note this class has nothing in it. It's just here to add the class-level attribute.
}
public class ORDERMetadata
{
[Display(Name = "Order Number")]
public Nullable<int> Order_Number { get; set; }
[Display(Name = "Order Type")]
public string Order_Type { get; set; }
}
Controller:
List<ORDERMetadata> result = db.ORDERS.
Where(p => p.Order_Number == id).
Select(x => new ORDERMetadata
{
Order_Number = x.Order_Number,
Order_Type = x.Order_Type
}).ToList();
Error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[Mvc5_Whitby.Models.ORDERMetadata]', but this dictionary requires a model item of type 'Mvc5_Whitby.Models.ORDERMetadata'
In the top of your view you probably have this:
#model Mvc5_Whitby.Models.ORDERMetadata
When you probably want this, to match what you are passing to the view:
#model IEnumerable<Mvc5_Whitby.Models.ORDERMetadata>
You haven't posted you view but it must have
#model Mvc5_Whitby.Models.ORDERMetadata
but you are passing it a collection (the result of your query). Either change the query to return a single item (e.g. .FirstOrDefault(), not .List()) or change the view to
#model List<Mvc5_Whitby.Models.ORDERMetadata>
depending on what you want

List of strings to DropDownListFor

This is my model:
public class ContentPage
{
public BlogPost BlogPost { get; set; }
public List<BlogPost> BlogPosts { get; set; }
public List<string> Kategorier { get; set; }
}
I would like to use the values in the
public List<string> Kategorier { get; set; }
In a dropdownlistfor, this is what i got so far:
#Html.DropDownListFor(o => o.BlogPost.Kategori, "Here i want my list i guess?"(o => new SelectListItem { Text = o.Kategori, Value = o.Kategori }), "", null)
To clearify, I want to use the values in the List Kategorier in order to set the value for the o.BlogPost.Kategori
Any help appreciated.
There is a number of overloads you can use, but the one I find most readable is
#Html.DropDownListFor(model => model.BlogPost.Kategori,
Model.Kategorier.Select(kat => new SelectListItem { Text = kat, Value = kat })
Part of the reason why I like this overload is just that I prefer strong typing and being helped by the (aspnet) compiler. I generally avoid SelectList and its string-based constructors because they are brittle.
You may want to turn your List<string> into an IEnumerable<SelectListItem> in your view model instead of having to do it in the view.
EDIT:
I would do something like
public class ContentPage
{
public ContentPage(){} //Default constructor needed for model binding
public ContentPage(List<string> kategorier /* and possibly more arguments */)
{
Kategorier = kategorier.Select(k => new SelectListItem { Text = k, Value = k });
}
public BlogPost BlogPost { get; set; }
public List<BlogPost> BlogPosts { get; set; }
public IEnumerable<SelectListItem> Kategorier { get; set; }
}
Be aware that this should be fine for creating new blogposts, but if you want to edit existing blog posts, you will have to do a little more work (categories will have to be selected etc. when you render the page initially etc).

How to pass two LINQ joined tables from Controller to View

I have three objects:
public class Part
{
[Key]
public int ID { get; set; }
public string Number { get; set; }
public string Name { get; set; }
public int descID { get; set; }
}
public class Description
{
[Key]
public int descID { get; set; }
public string descName { get; set; }
public string description { get; set; }
}
public class GridPart
{
public string name{ get; set; }
public string number { get; set; }
public string description { get; set; }
}
I'm using LINQ to join Part and Description on the descID column:
public ActionResult Index()
{
var myParts = from p in db.Parts
join d in db.Description on p.descID equals d.DescriptorID
select new { Description = d.description, Name = p.name};
List<GridPart> partsList = new List<GridPart>();
foreach (var m in myParts)
{
GridPart gp = new GridPart();
gp.Name = m.name;
gp.description = m.description;
partsList.Add(gp);
}
return View(partsList);
}
If I was just using the Parts table, in the view I would do:
#model IEnumerable<MyApp.Models.Part>
What do I do if I'm using the joined table? This uses both Parts and Description, not to mention my List of GridParts, how do I pass this through to display all of the data I need?
Any advice is greatly appreciated.
If you pass an anonymous type to your view it won't be strongly typed. You can refer to your model like this instead
#Html.TextBox("Name")
or
#Html.Display("Name")
Although this will work I would advice against it - The better solution would be to go with a Viewmodel instead. This will make your view strongly typed.
Edit: Looking on this again I see that your actually not parsing the anonymous type to your view. Your parsing a list of GridParts.
You should be able to strongly type your view like your tried - just refer to GridParts instead of parts.
#model IEnumerable<MyApp.Models.GridPart>

How can I use DropDownListFor() on a dynamic type?

I get the following error in the DropDownListFor() "An expression tree may not contain a dynamic operation" because the lambda uses a dynamic type.
How can I set the selected option on the DropDownList without resorting to jQuery?
I would also rather not make a template or custom helper.
Model
public class Thing : Base {
public virtual Nullable<int> OptionID { get; set; }
public virtual Option Option { get; set; }
}
public class Option : Base {
public virtual ICollection<Thing> Things { get; set; }
}
public class Base {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
Controller
public ActionResult Edit(int Id) {
return View(new ViewModel(context, new Thing()));
}
View
#model MvcApp7.Models.ViewModel
#{
var Entity = (dynamic)Model.Entity;
}
#Html.DropDownListFor(x => Entity.OptionID , (System.Web.Mvc.SelectList)Model.Options)
ViewModel
public class ViewModel {
public ViewModel(Context context, object entity) {
this.Entity = entity;
this.Options = new SelectList(context.Options, "Id", "Name");
}
public dynamic Entity { get; set; }
public SelectList Options { get; set; }
}
EDIT: Please excuse me. I forgot that I could specify the selected option in the SelectList itself. I moved the responsibility into the ViewModel and will try to deal with it from there. However, it would still be good to know how to work around this in the View itself in case it was necessary.
I did this in the ViewModel
this.Options = new SelectList(context.Options, "Id", "Name", this.Entity.OptionID);
and this in the View
#Html.DropDownList("OptionID", Model.Options)
View
#model MvcApp7.Models.ViewModel
#Html.DropDownListFor(x => x.Entity.OptionID , (System.Web.Mvc.SelectList)Model.Options)
ViewModel
public class ViewModel {
public ViewModel(Context context, object entity) {
this.Entity = entity;
this.Options = new SelectList(context.Options, "Id", "Name");
}
public dynamic Entity { get; set; }
public SelectList Options { get; set; }
}

Resources