I'm just starting with MVC3 and I have the following situation.
My app's initial sign up page among other controls contains a drop down menu. When the user has completed the form then the form details are saved in a session and they move on to the next step. They may also move back to the original step to re-edit, in which case I need to show the drop down menu with the appropriate value preselected.
My code is as follows:
Controller:
public ActionResult Index()
{
var model = new CompanyDetailsModel();
BindDropDownLists(model);
//IF WE HAVE A SESSION THEN PREFILL THE VALUES
if(MySession.Current.IFA!=null)
model = EditIFAProfileService.returnCompanyDetailSession(MySession.Current.IFA);
return View("CreateCompanyDetails", model);
}
I am getting the expected values from the model, so for example the
value model.Salutation is equal to an integer.
So, armed with that value I would expect to be able to set the preselected value of my dropdownlist as follows:
#Html.DropDownListFor(model => model.SalutationValue, Model.SalutationItems,
"Please Select", new { #tabindex = "1" })
If I do set the model value of SalutationValue to an int then I get an error stating that
ViewData item that has the key is of type 'System.Int32' but must be of type 'IEnumerable'.
Any help would be much appreciated.
Thank you.
Don't use any ViewData if you are working with strongly typed views and view models as it would conflict. Simply set the SalutationValue property to some given value. Here's an example:
public ActionResult Index()
{
var model = new CompanyDetailsModel();
model.SalutationItems = ...
if (MySession.Current.IFA != null)
{
model.SalutationValue = MySession.Current.IFA;
}
return View("CreateCompanyDetails", model);
}
Related
I am working in mvc3 razor.
i want checkbox input in razor view for all catagories stored in database.
how could i bind it? please help
Suppose your model is having a field to hold all the checkbox text like.
public class MyClass
{
public string SelectedOptions {get;set;}
public List<String> CheckList {get;set;}
}
Write a controller Action method like
public ActionResult ShowCheckBoxList()
{
MyClass Options= new MyClass();
Options.CheckList = new List<String>();
// Here populate the CheckList with what ever value you have to
// either if you are getting it from database or hardcoding
return View(Options);
}
you have to create a view by right clicking the above method and choose Add View. Make sure you keep the name same as the method name also you the strongly typed view by choosing the MyClass Model from the dropDown, scaffolding template is optional use it as per your scenario.
Now in your View you can use this populated check box text as
#foreach(var optionText in Model.CheckList)
{
#Html.CheckBox(#Model.SelectedOptions, false, new {Name = "SelectedOptions", Value = #optionText})
#Html.Label(#optionText , new { style = "display:inline;" })
}
Keep this in a form and make sure you also specify a Action to be called on post of the form.
Make your action name same as the previous action (it is [GET] meaning before post), Now we create same method for [POST]
[HTTPPOST]
public ActionResult ShowCheckBoxList(MyClass data) // here you will get all the values from UI in data variable
{
//data.SelectedOptions will have all the selected values from checkbox
}
I need to create a random number of dropdownlists in my view, based on the selected value of another dropdownlist. This is all done but my problem comes when I need to make the httppost because i never know how much data i need to save in my db.
In my model I have a list
public List<RoomToBooking> RoomsToBooking { get; set; }
that will get filled with x number of RoomToBooking when the Create view is rendered after the user makes a selction of dropdownlist 1:
var dogs = from d in db.Dogs
where d.Customer_ID == id
select d;
foreach (Dog item in dogs)
{
roomToBooking = new RoomToBooking();
roomToBooking.Customer_ID = id;
roomToBooking.Dog = item;
roomsToBookingList.Add(roomToBooking);
}
So I would like to create the same number of dropdownlist in my Create view
#Html.DropDownListFor(model => model.Booking.RoomToBooking, new SelectList(ViewBag.DeliveryTypes), new { #class = "selectbox" })
#Html.ValidationMessageFor(model => model.Booking.RoomToBooking)
So I in the end can be able to save it to my db
[HttpPost]
public ActionResult Create(EditBookingPensionViewModel model)
{
foreach (RoomToBooking item in objViewModel.RoomsToBooking)
{
//Save to db
}
}
I assume that I should use jquery to create the dropdownlists, but how do i create the dropdownlists so the selected values can be found in my viewmodel??
You may take a look at the following article. I slight adaption might be necessary for your scenario because you don't have add and remove buttons but instead you use the selected value of a dropdownlist to determine the number of dynamic rows to be added. But the concept is the exactly the same.
I have a ddl which is populated with hours of day 01-23. This is on a form which is used to book an item of equipment. The hour is populated to a db field. The issue is this, when the booking form is opened to alter the time the ddl shows the hour that was booked, when changed though and the form is submitted the value passed on post is the initial value from db not the new selected hour.
this is the basic pieces of code. any idea why the newly selected ddl value is not passed to the model??
View
<%= Html.DropDownList("ddl_Hour", Model.ddlHour,
new { #class = "DropDown", style = "width: 40px” })%>
Model
private string _ddlHourSelectedValue = "0";
public SelectList ddlHour
{
get
{
return (new System.Web.Mvc.SelectList(_ddlHour, "intValue", "Text", Convert.ToInt32(_ddlHourSelectedValue)));
}
}
public string ddlHourSelectedValue
{
get
{
return _ddlHourSelectedValue;
}
set
{
_ddlHourSelectedValue = value;
}
}
param[6] = new SqlParameter("#Timeslot", ddlHourSelectedValue);
The field in your view is called "ddl_Hour" However is there a variable in your Model with the same name? Otherwise the MVC framework will not automatically populate the value in the model.
Two ways you could go about this.
1
In your controller methods that accepts a post, you can add the parameter: FormCollection fc to the method. This key value pair collection will allow you to fetch results from fields in the post data like so:
string selectedValue = fc["ddl_Hour"];
2
Or you can modify your model to include a variable with the same name as the drop down list so that it is automatically populated for you.
public string ddl_Hour { get; set; }
You should then be able to access the result of the drop down list selection on post from that variable.
I am new to MVC frame work. And i am making one page where we can see details of department by clicking on details link button.
While User click link button it fetch the all the records of the particular department in List Collection and redirect to Details View.Data has been fetched in List but while going to Details view it Generates following error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List1[DocPageSys.Models.Interfaces.DepartmentInfo]', but this dictionary requires a model item of type 'DocPageSys.Models.Interfaces.DepartmentInfo`'.
I understood the error but confusion to solve it.And stuck with this problem...
Since your Details view is strongly typed to DepartmentInfo:
#model DocPageSys.Models.Interfaces.DepartmentInfo
you need to pass a single instance of it from the controller action instead of a list:
public ActionResult Details(int id)
{
DepartmentInfo depInfo = db.Departments.FirstOrDefault(x => x.Id == id);
return View(depInfo);
}
So make sure that when you are calling the return View() method from your controller action you are passing a single DepartmentInfo instance that you have fetched from your data store.
To make it run fine initially you could simply hardcode some value in it:
public ActionResult Details(int id)
{
var depInfo = new DepartmentInfo
{
Id = 1,
Name = "Sales",
Manager = "John Smith"
}
return View(depInfo);
}
Oh, and you will notice that I didn't use any ViewData/ViewBag. You don't need it. Due to their weakly typed nature it makes things look really ugly. I would recommend you to always use view models.
Passing a list instead of a single item
This error tells you, that you're passing a list to your view but should be passing a single entity object instance.
If you did fetch a single item but is in a list you can easily just do:
return View(result[0]);
or a more robust code:
if (result != null && result.Count == 1)
{
return View(result[0]);
}
return RedirectToAction("Error", "Home");
This error will typically occur when there is a mismatch between the data that the controller action passes to the view and the type of data the view is expecting.
In this instance it looks as if you're passing a list of DepartmentInfo items when your view is expecting a single item.
I'm running into an issue trying to use #Html.DropDownListFor().
I have a model with a navigation property on it:
public class Thing {
...
public virtual Vendor Vendor { get; set; }
}
In the controller I'm grabbing the vendor list to throw into the ViewBag:
public ActionResult Create() {
ViewBag.Vendors = Vendor.GetVendors(SessionHelper.CurrentUser.Unit_Id);
return View();
}
The html item in the view looks like this:
#Html.DropDownListFor(model => model.Vendor, new SelectList(ViewBag.Vendors, "Id", "Name"), "---- Select vendor ----")
#Html.ValidationMessageFor(model => model.Vendor)
The dropdown list is being rendered, and everything seems fine until I submit the form. The HttpPost Create method is returning false on the ModelState.IsValid and throwing a Model Error: The parameter conversion from type 'System.String' to type '...Models.Vendor' failed because no type converter can convert between these types.
If I let the page post through, I end up with a server error:
Exception Details: System.ArgumentNullException: Value cannot be null.
Parameter name: items
After searching high and low I haven't been able to find a reason that the #Html.DropDownListFor() isn't properly auto-binding a Vendor object to the navigation property.
Any help would be greatly appreciated.
EDIT:
I ended up having to explicitly set the ForeignKey attributes so that I could directly access "Vendor_Id" then I changed the DropDownListFor to point to "Vendor_Id" instead of the navigation property. That seems to work.
I have found that the best way to do this is as follows. Change the controller to create the SelectListItems.
public ActionResult Create() {
ViewBag.Vendors = Vendor.GetVendors(SessionHelper.CurrentUser.Unit_Id)
.Select(option => new SelectListItem
{
Text = (option == null ? "None" : option.Name),
Value = option.Id.ToString()
});
return View();
}
Then modify the view as follows:
#Html.DropDownListFor(model => model.Vendor, (IEnumerable<SelectListItem>)ViewBag.Vendors, "---- Select vendor ----")
#Html.ValidationMessageFor(model => model.Vendor)
You have to cast the ViewBag.Vendors as (IEnumerable).
This keeps the views nice and neat. You could also move the code that gets the SelectListItems to your repo and put it in a method called something like GetVendorsList().
public IEnumerable<SelectListItem> GetVendorsList(int unitId){
return Vendor.GetVendors(unitId)
.Select(option => new SelectListItem
{
Text = (option == null ? "None" : option.Name),
Value = option.Id.ToString()
});
}
This would separate concerns nicely and keep your controller tidy.
Good luck
I have replied similar question in following stackoverflow question. The answer is good for this question too.
Validation for Navigation Properties in MVC (4) and EF (4)
This approach doesn't publish the SelectList in controller. I don't think publishing SelectList in controller is good idea, because this means we are taking care of view part in controller, which is clearly not the separation of concerns.