I have created one mvc3 application.
There is one form where i'm taking values from user.
There is one field called Gender
i want to give a dropdown list for that with values Male and Female
but i dont understand where and how i specify there values please help.
I need an Ajax Helper method for this or any asynchronous script
the easiest way is to do this in Html :
<select id="selection" name="selection">
<option value="1">Male</option>
<option value="2">Female</option>
</select>
You can also do this with razor :
#Html.DropDownLiwt("GenderSelection", "Male")
after having done this inside the controler :
Dim genderSelection As List(Of String) = New List(Of String)
genderSelection.Add("Male")
genderSelection.Add("Female")
ViewData("GenderSelection") = New SelectList(genderSelection)
First create Entity class for your dropdown. It will return a list of value
public class KeyValueEntity
{
public string Description { get; set; }
public string Value { get; set; }
}
public class MyViewModel
{
public List<KeyValueEntity> Status { get; set; }
}
On your controller write the following code
[HttpGet]
public ActionResult Dropdown()
{
MyViewModel model = GetDefaultModel();
return View(model);
}
}
public MyViewModel GetDefaultModel()
{
var entity = new MyViewModel();
entity.Status = GetMyDropdownValues();
return entity;
}
private List<KeyValueEntity> GetMyDropdownValues()
{
return new List<KeyValueEntity>
{
new KeyValueEntity { Description = "Yes" , Value ="1" },
new KeyValueEntity { Description = "No" , Value ="0"}
};
}
Code for your cshtml page : Now you need to bind your view with your model for this on top of your view you define your model class
#model MyViewModel
Following is the code for dropdown binding
#Html.LabelForModel("Status:")
#Html.DropDownListFor(m => m.Status, new SelectList(Model.Status, "Value", "Description"), "-- Please Select --")
Related
I am in need of how the correct way to do this.
I can not use forms authentication
A user will "login" or confirm identity based on a value
I need to walk the user through a series of pages like so
Contact/MailAddress
Contact/Phone
Contact/Email
Contact/Summary
Questionaire/Question1
Questionaire/Question2
Questionaire/Question3
Questionaire/Summary
Final/Certify
Final/Review
I plan on using Session to hold the data but I'm having trouble figuring out how to pass the values to other views and how Redirect to other pages.
Any help will do...
Lets say you have some models like this
public class ContactModel
{
public string MailAddress { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
}
public class QuestionaireModel
{
public string Question1Answer { get; set; }
public string Question2Answer { get; set; }
public string Question3Answer { get; set; }
}
public class ContactQuestionaireModel
{
public ContactModel Contact { get; set; }
public QuestionaireModel Question { get; set; }
}
and you want to persist this model from view to view and action to action. In you controller you can create 2 actions. one for your first view and one for your second
Controller
public ActionResult ContactAddress()
{
var model = new ContactQuestionaireModel();
return View(model);
}
[HttpPost]
public ActionResult ContactAddress(ContactQuestionaireModel model)
{
var currentModel = TempData["currentModel"] as ContactQuestionaireModel;
currentModel.Contact.MailAddress = model.Contact.MailAddress;
TempData["currentModel"] = currentModel;
return RedirectToAction("ContactPhone");
}
public ActionResult ContactPhone()
{
var model = TempData["currentModel"] as ContactQuestionaireModel;
return View(model);
}
[HttpPost]
public ActionResult ContactPhone(ContactQuestionaireModel model)
{
var currentModel = TempData["currentModel"] as ContactQuestionaireModel;
currentModel.Contact.Phone = model.Contact.Phone;
TempData["currentModel"] = currentModel;
return RedirectToAction("ContactEmail");
}
in the first action ContactAddress you create a new blank model and pass that in to your view ContactAddress. In that view you can set TempData["currentModel"] equal to the model you are passing in. This will stay in TempData for 1 post back to the server. You dont need to do this on the first page since it's blank anyway but i'm doing it to save time.
View ContactAddress
#model WebApplication3.Models.ContactQuestionaireModel
#{
ViewBag.Title = "Contact Address";
TempData["currentModel"] = Model; //this will be available to me in the HttpPost action
}
#using (Html.BeginForm())
{
<div class="form-group">
#Html.LabelFor(m => m.Contact.MailAddress, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Contact.MailAddress, new { #class = "form-control" })
</div>
</div>
<button type="submit">Submit</button>
}
you'll notice in the controller code that the Post Action for ContactAddress is setting a var currentModel equal to what is in TempData["currentModel"] which was set in the ContactAddress view. Before you do a redirect to the next action ContactPhone set TempData["currentModel"] back to the model you are building and use it in the next action.
You do have the option of adding the Model as a parameter to each action and passing the currentModel object like
public ActionResult ContactPhone(ContactQuestionaireModel model)
return RedirectToAction("ContactPhone", currentModel);
its up to you really. this is not a foolproof way. page refreshes and back and forward buttons could clear out everything that was entered. Storing the information in Session or actually saving the data in a database might be more optimal.
I advise against doing what you are attempting to do by logging in with session but what you are looking for is:
TempData.yourModel = new SomeModel { Data = "yourData" };
//next page
var model = (SomeModel)TempData.yourModel;
and
RedirectToAction("yourController", "yourAction");
I know there are a lot of similar question here but none seem quite the same as mine.
In my View:
#model LocalInformedMotionServer.Models.FeedData
#Html.DropDownList("Premise", Model.LoadUp("key"), new { #style = "width: 218px;height:35px;" })
In my controller:
public class CloudController : Controller
{
public IEnumerable<wsCommon.Premise> Premises { get; set; }
public ActionResult Feed(string key)
{
var feedData = new FeedData();
Premises= feedData.LoadUp(key);
return View(feedData);
}
}
In my Model:
public class FeedData
{
public IEnumerable<wsCommon.Premise> LoadUp(string saltKey)
{
Premises premises = new InformedBiz.Premises();
return premises.GetPremises(saltKey);
}
}
It errors because the variable:
"key"
in this call:
Model.LoadUp("key")
is being read in as'null' in my controller method.
Of course as this is all new to me I could be doing this all wrong..
ADDITIONAL:
In my CloudController Class I have this:
public class CloudController : Controller
{
public ActionResult Feed(string saltKey)
{
var feedData = new FeedData();
feedData.LoadUp(saltKey);
return View(feedData);
}
public ActionResult Index()
{
return View();
}
public ActionResult LogIn()
{
return View();
}
}
I'm not sure what your Premise class looks like, but I usually use an IEnumberable of SelectListItem for drop downs in my views. So you could do something like this:
public IEnumerable<SelectListItem> LoadUp(string saltKey)
{
Premises premises = new InformedBiz.Premises();
return premises.GetPremises(saltKey).Select(
p => new SelectListItem { Text = p.Name, Value = z.PremiseId.ToString() }
);
}
You'll also need to create a Post ActionResult method that accepts the model in your view (FeedData) as well as wrap your DropDownList control in a Html.BeginForm, to post results to the controller. Hope this makes a bit of sense.
You have not posted the properties of your FeedData model but assuming it contains a property which is typeof Premise and you want to be able to select a Premise from a collection, then using a view model that represents what you want to display/edit is the recommended approach (refer View Model Design And Use In Razor Views and What is ViewModel in MVC?)
You view model might look like
public class FeedDataVM
{
.....
[Display(Name = "Premise")]
[Required(ErrorMessage = "Please select a Premise")]
public int? SelectedPremise { get; set; }
....
public SelectList PremiseList { get; set; }
}
and in your controller (not sure what saltKey is for?)
public ActionResult Feed(string saltKey)
{
FeedDataVM model = new FeedDataVM();
IEnumerable<Premise> premises = // get the collection of premise objects from your repository
// assuming you want to display the name property of premise, but post back the key property
model.PremiseList = new SelectList(premises, "key", "name");
return View(model);
}
View
#model FeedDataVM
#using(Html.BeginForm())
{
....
#Html.LabelFor(m => m.SelectedPremise)
#Html.DropDownListFor(m => m.SelectedPremise, Model.PremiseList, "-Please select")
#Html.ValidationMessageFor(m => m.SelectedPremise)
....
<input type="submit" value="Save" />
}
and the POST method
public ActionResult Feed(FeedDataVM model)
{
// model.SelectedPremise contains the value of the selected option as defined by the key property of Premise
}
Side note: Your FeedData model contains a method to retrieve a collection of Premise which appears to be calling another service. You should avoid this type of design which makes it difficult to debug and unit test. Your controller is responsible for initializing/getting you data models and view models and for populating/mapping their properties.
I'm trying to use the results of a LINQ query to create a dropdownlist in an MVC app. I'm using this answer as a reference. However, when I try to implement for my case I get the error: 'System.String' does not contain a property with the name 'SAMPLING_EVENT'
My code is as follows:
Controller
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
ViewBag.Title = "Sample Tracker Tool";
DateTime nineMonthsAgo = DateTime.Now.AddDays(-270);
var context = new EDMS_Entities();
var resultSet = (from samplingEvents in context.EDMS_SAMPLES
where samplingEvents.RECORD_CREATED_DATE >= nineMonthsAgo
orderby samplingEvents.SAMPLING_EVENT
select samplingEvents.SAMPLE_ID)
.Distinct();
var viewModel = new SamplingEventsVM();
viewModel.SamplingEvents = new SelectList(resultSet, "SAMPLING_EVENT", "SAMPLING_EVENT");
return View(viewModel);
}
}
ViewModel class
public class SamplingEventsVM
{
public int SelectedSamplingEvent { get; set; }
public SelectList SamplingEvents { get; set; }
}
View
#model SamplingEventsVM
<h2>#ViewBag.Title</h2>
<span>
#Html.DropDownListFor(model => model.SelectedSamplingEvent, Model.SamplingEvents, "Sampling Event")
</span>
What am I doing wrong?
You are selecting this select samplingEvents.SAMPLE_ID
So you get a List of int maybe, depends on your ID type
Then you try to make a select list with the property value "SAMPLING_EVENT"
Which doesn't exist on the int object you filled resultSet with.
Instead do this:
var resultSet = (from samplingEvents in context.EDMS_SAMPLES
where samplingEvents.RECORD_CREATED_DATE >= nineMonthsAgo
orderby samplingEvents.SAMPLING_EVENT
select samplingEvents)
.Distinct();
I tried searching and didn't find anything that fixed my problem. I have a DropDownList on a Razor view that will not show the the item that I have marked as Selected in the SelectList. Here is the controller code that populates the list:
var statuses = new SelectList(db.OrderStatuses, "ID", "Name", order.Status.ID.ToString());
ViewBag.Statuses = statuses;
return View(vm);
Here is the View code:
<div class="display-label">
Order Status</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.StatusID, (SelectList)ViewBag.Statuses)
#Html.ValidationMessageFor(model => model.StatusID)
</div>
I walk through it and even in the view it has the correct SelectedValue however the DDL always shows the first item in the list regardless of the selected value. Can anyone point out what I am doing wrong to get the DDL to default to the SelectValue?
The last argument of the SelectList constructor (in which you hope to be able to pass the selected value id) is ignored because the DropDownListFor helper uses the lambda expression you passed as first argument and uses the value of the specific property.
So here's the ugly way to do that:
Model:
public class MyModel
{
public int StatusID { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
// TODO: obviously this comes from your DB,
// but I hate showing code on SO that people are
// not able to compile and play with because it has
// gazzilion of external dependencies
var statuses = new SelectList(
new[]
{
new { ID = 1, Name = "status 1" },
new { ID = 2, Name = "status 2" },
new { ID = 3, Name = "status 3" },
new { ID = 4, Name = "status 4" },
},
"ID",
"Name"
);
ViewBag.Statuses = statuses;
var model = new MyModel();
model.StatusID = 3; // preselect the element with ID=3 in the list
return View(model);
}
}
View:
#model MyModel
...
#Html.DropDownListFor(model => model.StatusID, (SelectList)ViewBag.Statuses)
and here's the correct way, using real view model:
Model
public class MyModel
{
public int StatusID { get; set; }
public IEnumerable<SelectListItem> Statuses { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
// TODO: obviously this comes from your DB,
// but I hate showing code on SO that people are
// not able to compile and play with because it has
// gazzilion of external dependencies
var statuses = new SelectList(
new[]
{
new { ID = 1, Name = "status 1" },
new { ID = 2, Name = "status 2" },
new { ID = 3, Name = "status 3" },
new { ID = 4, Name = "status 4" },
},
"ID",
"Name"
);
var model = new MyModel();
model.Statuses = statuses;
model.StatusID = 3; // preselect the element with ID=3 in the list
return View(model);
}
}
View:
#model MyModel
...
#Html.DropDownListFor(model => model.StatusID, Model.Statuses)
Make Sure that your return Selection Value is a String and not and int when you declare it in your model.
Example:
public class MyModel
{
public string StatusID { get; set; }
}
Create a view model for each view. Doing it this way you will only include what is needed on the screen. As I don't know where you are using this code, let us assume that you have a Create view to add a new order.
Create a new view model for your Create view:
public class OrderCreateViewModel
{
// Include other properties if needed, these are just for demo purposes
// This is the unique identifier of your order status,
// i.e. foreign key in your order table
public int OrderStatusId { get; set; }
// This is a list of all your order statuses populated from your order status table
public IEnumerable<OrderStatus> OrderStatuses { get; set; }
}
Order status class:
public class OrderStatus
{
public int Id { get; set; }
public string Name { get; set; }
}
In your Create view you would have the following:
#model MyProject.ViewModels.OrderCreateViewModel
#using (Html.BeginForm())
{
<table>
<tr>
<td><b>Order Status:</b></td>
<td>
#Html.DropDownListFor(x => x.OrderStatusId,
new SelectList(Model.OrderStatuses, "Id", "Name", Model.OrderStatusId),
"-- Select --"
)
#Html.ValidationMessageFor(x => x.OrderStatusId)
</td>
</tr>
</table>
<!-- Add other HTML controls if required and your submit button -->
}
Your Create action methods:
public ActionResult Create()
{
OrderCreateViewModel viewModel = new OrderCreateViewModel
{
// Here you do database call to populate your dropdown
OrderStatuses = orderStatusService.GetAllOrderStatuses()
};
return View(viewModel);
}
[HttpPost]
public ActionResult Create(OrderCreateViewModel viewModel)
{
// Check that viewModel is not null
if (!ModelState.IsValid)
{
viewModel.OrderStatuses = orderStatusService.GetAllOrderStatuses();
return View(viewModel);
}
// Mapping
// Insert order into database
// Return the view where you need to be
}
This will persist your selections when you click the submit button and is redirected back to the create view for error handling.
I hope this helps.
For me, the issue was caused by big css padding numbers ( top & bottom padding inside the dropdown field). Basically, the item was being shown but not visible because it was way down. I FIXED it by making my padding numbers smaller.
I leave this in case it helps someone else. I had a very similar problem and none of the answers helped.
I had a property in my ViewData with the same name as the selector for the lambda expression, basically as if you would've had ViewData["StatusId"] set to something.
After I changed the name of the anonymous property in the ViewData the DropDownList helper worked as expected.
Weird though.
My solution was this...
Where the current selected item is the ProjectManagerID.
View:
#Html.DropDownList("ProjectManagerID", Model.DropDownListProjectManager, new { #class = "form-control" })
Model:
public class ClsDropDownCollection
{
public List<SelectListItem> DropDownListProjectManager { get; set; }
public Guid ProjectManagerID { get; set; }
}
Generate dropdown:
public List<SelectListItem> ProjectManagerDropdown()
{
List<SelectListItem> dropDown = new List<SelectListItem>();
SelectListItem listItem = new SelectListItem();
List<ClsProjectManager> tempList = bc.GetAllProductManagers();
foreach (ClsProjectManager item in tempList)
{
listItem = new SelectListItem();
listItem.Text = item.ProjectManagerName;
listItem.Value = item.ProjectManagerID.ToString();
dropDown.Add(listItem);
}
return dropDown;
}
Please find sample code below.
public class Temp
{
public int id { get; set; }
public string valueString { get; set; }
}
Controller
public ActionResult Index()
{
// Assuming here that you have written a method which will return the list of Temp objects.
List<Temp> temps = GetList();
var tempData = new SelectList(temps, "id", "valueString",3);
ViewBag.Statuses = tempData;
return View();
}
View
#Html.DropDownListFor(model => model.id, (SelectList)ViewBag.Statuses)
#Html.ValidationMessageFor(model => model.id)
I am trying to use the Html.ListBoxFor helper to show a list box and return the selected Id. Is there a problem with the dataValueField not being a string?
If the SelectList contained in the model uses integers as the dataValueField then I get a "Value cannot be null - Parameter name: Source" exception raised when the list is rendered in the view.
If the Id is changed to a string then everything works and the selected Id is passed back to the view.
Any ideas?
Here is the controller (based on a cut down new project)
namespace Mvc2.Controllers
{
public class ViewModel
{
public int TestId { get; set; } // if this is a string it works ok
public SelectList ListData {get; set;}
}
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new ViewModel();
model.TestId = 1; // code corrected after Lazarus' comment
var lst = new[] { new { Id = 1, Name = "cat" }, new { Id = 2, Name = "dog" } };
model.ListData = new SelectList(lst, "Id", "Name");
return View("TestView", model);
}
public ActionResult TestSubmit(ViewModel returnedModel)
{
int i = 99; // break here - returnedModel has correct TestId when declared as string
}
}
}
here is the View - crashes on the ListBoxFor line
<%using (Html.BeginForm("TestSubmit", "Home")) { %>
<%=Model.TestId %><br />
<%=Html.ListBoxFor(m => m.TestId, Model.ListData) %>
<br />
<input type="submit" value="Save" />
<%} %>
The expression you are passing for the selected values needs to be IEnumerable because ListBoxFor supports multiple selected items.
Answering my own question;
I am unconviced by the comments that this might be a bug which is waiting to be fixed because I get it in RC2 and in MVC 1 (I copied the code back to a project in that release).
Anyway I have implemented a work around for now which is to:-
(a) Add a dummy string version of the Id to the model (TestId)
public class ViewModel
{
public string TestId { get; set; } // dummy Id as a string
public List<DataToShow> Data { get; set; }
public SelectList ListData {get; set;}
}
(b) Display the list but retrieve the value as the dummy TestId - note that the list still dumps the data values as integers!
<%=Html.ListBoxFor(m => m.TestId, Model.ListData) %>
(c) Copy the dummy string value into its proper integer location in the action
public ActionResult TestSubmit(ViewModel returnedModel)
{
MyModel.DataId = Int32.Parse(returnedModel.TestId);
Hope this is of some Help.
This is a known issue with ASP.NET MVC 2. It should be fixed in the March release.