Difference between DropDownlist or DropDownListFor Html helper - asp.net

It seems weird that I couldn't find an explanation of the difference between those two helpers, so I would assume that is something obvious but I missed.
Basically I am trying to decide which one I should use for my case, with the following simple Model:
public class Booking
{
public int ID { get; set; }
public Room Room { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public ICollection<Equipment> Equipments { get; set; }
public string Who { get; set; }
}
and I want display a simple Room DropDownlist for Adding and Editing Booking record.
After doing a lots of Google around, it seems that I probably need a DropDopwListFor, but not sure why and how?

Take the following two examples:
#Html.DropDownListFor(
x => x.EquipmentId,
new SelectList(Model.Equipments, "Id", "Text")
)
and:
#Html.DropDownList(
"EquipmentId",
new SelectList(Model.Equipments, "Id", "Text")
)
It is obvious that with the second example the name of the property you are binding the dropdown to is hardcoded as a magic string. This means that if you decide to refactor your model and rename this property Tooling support that you might be using has no way of detecting this change and automatically modifying the magic string you hardcoded in potentially many views. So you will have to manually search & replace everywhere this weakly typed helper is used.
With the first example on the other hand we are using a strongly typed lambda expression tied to the given model property so tools are able to automatically rename it everywhere it is used if you decide to refactor your code. Also if you decide to precompile your views you will get a compiler time error immediately pointing to the view that needs to be fixed. With the second example you (ideally) or users of your site (worst case scenario) will get a runtime error when they visit this particular view.
Strongly typed helpers were first introduced in ASP.NET MVC 2 and the last time I used a weakly typed helper was in an ASP.NET MVC 1 application long time ago.

DropDownListFor will automatically select the selected value by using the specified property:
// Will select the item in model.Equipments that matches Model.EquipmentId
#Html.DropdownListFor(m => m.EquipmentId, Model.Equipments);
Another comment:
Don't have ICollection<Equipment> Equipments in your view model. You should have a property that returns an IEnumerable<SelectListItem>.

When you want to add a view (aspx file) where this DropDownList or DropDownListFor will be inside, rightclick->add view then select "Create a strongly typed view" then in list select Booking class. After that add this page.
You can write in it as follows:
#Html.DropdownListFor(m => m.Equipments , Model.Equipments);
because we add strongly typed view as Booking, you can have:
m => m.ID, m => m.Room, m => m.StartTime
... etc.
In your services you can have methods to take data from database, then use this service's method in your controller to pass data from database to view. You can use ViewData in your controller:
ViewData["Equipments"] = new servicename().getdatalistfromdatabase().AsEnumarable();
Putting AsEnumarable() at the end of your list taken from database makes it IEnumarable.
Then in your view, you can also have :
#Html.DropdownList("MyEquipments" , ViewData["Equipments"]);
A link on ViewData usage:
http://msdn.microsoft.com/en-us/library/dd410596.aspx
I hope that helps you.

DropdownListFor is support strongly type and it name assign by lambda Expression so it shows compile time error if have any error.
DropdownList not support this.

Related

Is it possible to force the Telerik MVC MultiSelect to post just an ID back to the controller?

I'm trying to migrate a Html.ListBoxFor() over to a Html.Telerik().MultiSelectFor() to gain a bit of fancy UI, but the HTTP form posts are incompatible with the Model, and it seems excessive to make a new model binder to avoid it.
public class Settings
{
public int[] UserIds { get; set; }
public IEnumerable<SelectListItem> UserSelectList { get; set; }
}
When I use the Html.ListBoxFor helper, the HTTP form post includes just the value of the Select List Item (i.e. an array of UserIds), as expected.
UserIds[0] = 1
UserIds[1] = 2
#Html.ListBoxFor(model => model.UserIds, Model.UserSelectList)
When I use the Kendo MultiSelect, the HTTP form post includes two properties. Which is not expected.
UserIds[0].Text = Adrian
UserIds[0].Value = 1
...
#Kendo().MultiSelectFor(model => Model.UserIds).BindTo(Model.UserSelectList)
Does anyone know a way to get the Kendo MultiSelect to just post the id value back, or is there a ready-made Model Binder?
You just need to set the Primitive value to true which will get only the value list.
.ValuePrimitive(true)
For reference:
Is Primitive Sample

How can I create more than one Model in a view? Preferably using Partial Views and a dynamic number of models

I have list of "skills" that I want a user to be able to go through, selecting appropriate levels from the list. So Skill looks something like this:
public class Skill
{
public String SkillName { get; set; }
public SkillLevel CurrentSkillLevel { get; set; }
public Boolean IsRequired { get; set; }
public Skill(String Name)
{
this.SkillName = Name;
this.IsRequired = true;
this.CurrentSkillLevel = SkillLevel.None;
}
}
There could be hundreds of skills - and the exact number is unknown at the moment, and certainly it needs to be dynamic, so I don't want to make the user go through the process of clicking on each skill, filling out the form, and submitting each time. I'd like to display all of the skills in the same page (one row each), allow the user to select all the values, then click submit once at the end.
Unfortunately, I've not had any experience with using MVC for anything other than singleton creation. I would normally use a separate ViewModel for several models bundled together, but I don't see how that would work with a dynamic list, and since they are all the same type ("Skill"), I guess the ViewModel would look exactly like a list of the model.
Does anyone have an appropriate solution?
Thanks
Building on DaveA's answer, you can use an editor template for Skill. You will need to add a folder named EditorTemplates to your Views\Controller folder. Now make a partial view in that folder named Skill.cshtml that looks something like this
#model Skill
#Html.TextBoxFor(s => s.SkillName)
#Html.TextBoxFor(s => s.Skills[i].Title)
// etc...
Now in your main view
using (Html.BeginForm("UpdateCart", "Orders"))
{
#Html.TextBoxFor(p=>p.Name)
#Html.TextBoxFor(p=>p.Title)
#Html.EditorFor(p => p.Skills)
}
Razor is smart enough that it will render each skill in Skills using the Skill.cshtml editor template.

Correct MVC3 Model type of multiselect box?

is the correct datatype for a multi-select box in mvc3 DataType.MultilineText? These are ultimately derived from a many-to-many type relationship.
Thanks
Example
A Channel can have multiple Ad Slots, and an Ad Slot can have multiple Channels.
My current model is:
[Display(Name = "Ad Slots")]
[DataType(DataType.MultilineText)]
public string[] AdSlots { get; set; }
Is that right for a multiselect?
ASP.NET MVC doesn't utilize "types", persay, for DOM elements. You would utilize the HtmlHelper.ListBox() extension method.
This extension method returns a multi-select listbox.
#Html.ListBox(
"YourFormFieldName",
new SelectList(new[] { "You can select this one", "and this one" })
)
EDIT: for a Model, you could use this:
public class YourViewModel
{
public MultiSelectList YourItems { get; set; }
}
And then on a POST you can see which items are selected.
I think you can use something like System.Web.Mvc.MultiSelectList which takes an IEnuermable collection.
Check this article for more info:
http://ittecture.wordpress.com/2009/04/30/tip-of-the-day-198-asp-net-mvc-listbox-controls/
Well with your edit, my answer might not be so helpful since you most likely don't want your Model referencing MVC, but you could maybe do #Html.ListBox("AdSlots", new MultiSelectList(model.AdSlots)) since its already enumerable.
This Multiline Type means textarea and not multiselect which has a markup with multiselect as an attribute.

Entity Framework error - nested model problem

I'm new to ASP.NET MVC and want to create a small order management tool. My database contains the tables Orders and Articles (and a few other ones), and I generated an EF Model from my database, so I can use the full power of the EF mappings (e.g. db.Orders.Articles)
My two main relations which I'm concerned about are Orders and Articles.
An order can have many articles
An article can only belong to one order.
I've created an OrdersController with an Create action to create an order:
//
// GET: /Orders/Create
public ActionResult Create()
{
Order order = new Order()
{
// filling some order columns, e.g. date
};
Article article = new Article()
{
// ... article columns
};
order.Articles.Add(article);
return View(order);
}
//
// POST: /Orders/Create
[HttpPost]
public ActionResult Create(Order order)
{
// i know i should care more about error handling, but now ommit it
db.Orders.AddObject(order);
db.SaveChanges();
return RedirectToAction("index");
}
So I'm directly binding an EF Object to a view (read somewhere not to do that and use a view model instead, but don't really know what that view model should look like)
My view contains the Order form as well as the article form (because i want to create a order and articles at the same time and not seperate). I used these greate EditorFor Methods to do that.
And now to my problem: If i hit the submit button, the app crashes as soon as it comes to the HttpPost Create Method (when mapping the order) with this error message:
Error Message: The EntityCollection
has already been initialized. The
InitializeRelatedCollection method
should only be called to initialize a
new EntityCollection during
deserialization of an object graph.
If i hit continue in VS2010, it will complete saving the order - so my question is how to solve this problem in a reliable way.
Thanks in advance and sorry for that long story :)
I solved my problem now by using a separate ViewModel like #Yakimych advised me. However I did not copy all the attributes from the EF models, instead I just refer to them. My ViewModel looks like this:
public class NewOrderViewModel {
public Order { get; set; }
public List<Article> { get; set; }
}

Problem organizing code in asp.net MVC 2

I'm new to MVC and I borrow a book from library yesterday on asp.net MVC 2.
I'm a bit confused about what kind of code should be included in Model, view and controller. I was working on user input validation from the book and if I understand correctly, it seems they declare variables in "Model", validating user input in "Controller" and display the web page in "View".
Model:
-Declaring variables
e.g:
class Contact:
public string Name { get; set; }
public string EmailAddress { get; set; }
Views:
-Contain HTML, HTML Helper code, displaying contents and use variables from "Model"
e.g:
<%: Html.TextBoxFor(model => model.Name) %>
<%: Html.ValidationMessageFor(model => model.Name) %>
Controller:
-"Playing"/"Manipulating" variables from Model + Call "View" to display web page at the end (return View()). (Validating user input for this example)
e.g:
if (String.IsNullOrEmpty(contact.Name))
ModelState.AddModelError("Name", "Please enter your name.");
I'm not sure but it seems to me that "Controller" is the "heavy coding" part to me. On the other hand, "View" is the good old HTML, markup that display the web site and "Model" is a place that store data (declaring variables for example.)
Please let me know whether I'm on the right direction.
Thanks :)
I'm not sure but it seems to me that "Controller" is the "heavy coding" part to me
You should avoid having fat controllers. In fact the controller might depend on a service layer which contains the business logic of you application. This service layer could itself depend on repositories performing the data access (simple CRUD operations) on the models. So the controller would simply invoke a business operation call on the service layer to fetch/update the model and then pass a view model to the view in order to display it.
I am also new to MVC and first thing i did when i started was to view most of the talks given by Scott Hanselman and Phill Haack. So you might try this one: [http://channel9.msdn.com/blogs/matthijs/aspnet-mvc-2-basics-introduction-by-scott-hanselman][1]
[1]: http://channel9.msdn.com/blogs/matthijs/aspnet-mvc-2-basics-introduction-by-scott-hanselman to get started. From what i got so for, Darin is right. Try to avoid fat controllers and work with a repository for your model. Also, I noticed that for simple validation (required, maximum string length and such) it is preferred to use DataAnnotion on the model... So your Contact model might look like this:
class Contact:
[Required]
public string Name { get; set; }
public string EmailAddress { get; set; }
This will make the Name property required on Edit/Create Views.

Resources