I have the following set for drop down in asp.net mvc
#Html.DropDownListFor(model => model.DataId, ((IEnumerable<ProgrammeModel>)ViewBag.Data).Select(option => new SelectListItem
{
Text = (option == null ? "None" : option.Name),
Value = option.DataId.ToString(),
Selected = (Model != null) && (option.DataId== Model.DataId)
}), "Choose...", new { Class = "input", id = "DataId"
})
And in model:
[Required(ErrorMessage="The Data field is required.")]
public int DataId { get; set; }
But when the validation happens on form submit I am getting the error message for this field as
The Int32 field is required.
where I was expecting the result as
The Data field is required
#Html.DropDownListFor(model => model.DataId,
new SelectList(ViewBag.Data as System.Collections.IEnumerable,
"DataId", "Name"), "Choose")
I had the same problem, It seems that in the controller you have ViewBag.DataId and it is causing confusion to the validation.
Please try removing it and let me know if it is ok now.
Thanks,
Dimitar
Related
I feel like I'm taking crazy pills. I have a dropdownlist for a view that reads from our database all of the wine producers we have. I want to set the selectedValue to a particular ID driven by the referring page. I can see it picks up the selectedValue in debug, I see the selected value populated (906 for this example), but it doesn't set the dropdownlist to the correct value when the page is rendered, it always defaults to 1 for the default value. I've tried creating the selectList in razor as opposed to my controller, but nothing works. Any help on this would be appreciated, I'm guessing it is something small.
Controller:
if (User.IsInRole("admin"))
{
if (ID != 0)
{
ViewBag.ProducerSelect = new SelectList(db.Producers.OrderBy(p => p.Name), "ProducerID", "Name", ID);
}
else
{
ViewBag.ProducerSelect = new SelectList(db.Producers.OrderBy(p => p.Name), "ProducerID", "Name");
}
}
View:
if (User.IsInRole("producereditor"))
{
<h3>#ViewBag.ProducerName</h3>
}
else
{
<div class="editor-label">
#Html.LabelFor(m => m.Wine.ProducerID, "Producer")
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.Wine.ProducerID, ViewBag.ProducerSelect as SelectList)
</div>
}
Tried the below but no success:
ViewBag.ProducerSelect = new SelectList(from p in db.Producers
orderby p.Name
select new { p.ProducerID, p.Name }
, "ProducerID", "Name", ID);
If you want to preselect an item, You set that value to your ProducerId property.
var yourViewModelObj=new YourViewModel;
yourViewModelObj.Wine.ProducerId=906; //or whatever value you want
return View(yourViewModelObj);
Suggestion : For better code readablity/Maintenance, Try to avoid ViewBag / ViewData and use a ViewModel to pass the data.
I would add a Property to my ViewModel to hold the Collection of Producers
public class WineViewModel
{
//Other Existing properties also
public IEnumerable<SelectListItem> Producers{ get; set; }
public string SelectedProducer { get; set; }
}
Then in yout GetAction method, you can set the value like this, If you want to set one select option as the default selected one.
public ActionResult CreateWine()
{
var vm=new WineViewModel();
//The below code is hardcoded for demo. you mat replace with DB data.
vm.Producers= new[]
{
new SelectListItem { Value = "1", Text = "Prodcer A" },
new SelectListItem { Value = "2", Text = "Prodcer B" },
new SelectListItem { Value = "3", Text = "Prodcer C" }
};
//Now let's set the default one's value
vm.SelectedProducer = "2";
return View(vm);
}
And in your Strongly typed View,
#Html.DropDownListFor(x => x.SelectedProducer,
new SelectList(Model.Producers, "Value", "Text"), "Select Producer")
The HTML Markup generated by above code will have the HTML select with the option with value 2 as selected one.
I figured this out. I had ViewModel.wine.ProducerID elsewhere on the page in a hidden field, and that defaults to 1, so I just assigned that to passed in value, and it worked great. I knew it was something like that. Thanks!
User a ViewModel ex WineViewModel
public class WineViewModel
{
public Wine Wine { get; set; }
public SelectList PProducerList { get; set; }
public WineViewModel() { }
public WineViewModel(Wine wine)
{
this.Wine = wine;
}
}
Try the following in your controller
var model = new WineViewModel( selectwine);
model.ProjectTypeList = new SelectList( from p in db.Producers
orderby p.Name
select new { p.ID, p.Name }, "ID", "Name")
notice how I am exclusively declaring which is the ID and which is the Value in my SelectList
Then in your view do
#Html.DropDownListFor(model => model.Wine.ProducerID, Model.ProjectTypeList)
I have a table that has bit values (true/false)
Table Definition:
CharacterID int
isActive bit
UserId uniqueidentifier
I have 2 problems:
How to display the existing selected option in the edit view in a Dropdown
I need to save the value (yes/No) as true and false in the database.
Here is what I have attempted so far:
<div class="editor-label">
#Html.LabelFor(model => model.IsActive)
</div>
<div class="editor-field">
#Html.DropDownList("", new SelectListItem[] { new SelectListItem() { Text = "Yes", Value = "true", Selected = Model.IsActive }, new SelectListItem() { Text = "No", Value = "false", Selected = !Model.IsActive }})
</div>
Assuming that model.IsActive is declared as bool:
Wouldn't using a CheckBox be a bit more intuitive to the user and require less clicks?
In that case you could just use:
#Html.EditorFor(model => model.IsActive)
If you really want dropdowns, then this SO might provide a working implementation: https://stackoverflow.com/a/4036922/1373170
Applied to your context, I believe it would be:
#Html.DropDownListFor(model => model.IsActive, new SelectList(new SelectListItem[] { new SelectListItem() { Text = "Yes", Value = "True" }, new SelectListItem() { Text = "No", Value = "False"}}, model.IsActive.ToString())
Now, for saving it to the database I'd have to know if you are using EF, L2S, etc.
But I imagine you already have an action in your controller set up for saving. In that case it is probably already receiving an instance of your model as parameter. Using DropDownListFor instead of DropDownList, your model should be bound automatically by MVC's default ModelBinder, and you should be able to map that to your database entity and store it.
There are couple things you need to setup for drop-down and viewmodel property to make this work.
1) Your view model:
public class MyModel
{
public MyModel()
{
BoolSelectList = new List<SelectListItem>();
}
public int CharacterID { get; set; }
public bool isActive { get; set; }
public Guid UserId { get; set; }
public IList<SelectListItem> BoolSelectList { get; set; }
}
2) In controller you need to assign value to bool Value and List
public MyModel viewmodel = new MyModel();
// Set other properties of viewmodel
// ....
// Set Drop-down List values
viewModel.BoolSelectList = new SelectList(new SelectListItem[] { new SelectListItem() { Text = "Yes", Value = "True" }, new SelectListItem() { Text = "No", Value = "False"}};
3) In your view :
#Html.LabelFor(model => model.isActive, "Is Active ")
#Html.DropDownListFor(model => model.isActive, Model.BoolSelectList, model.IsActive.ToString())
On your Post action, the value of IsActive should be True/False depending on your selection.
Hey friends I am using drop down list in my mvc 3 project. Here the user choose one of the options and save it. And when he/she revisit the page than i have to make the initially saved value as selected value. Actually i am doing this with custom html helper as per need. But i am getting problem on it. I am doing this as:
else if (question_type == 7)
{
EAI.DAL.EaiEntities entities = new DAL.EaiEntities();
QuestionnaireRepository repository = new QuestionnaireRepository(entities);
SelectList typesList = repository.PopDdlList(qid);
output.Append(helper.Label(questiontext));
if (answer == "")
{
output.Append(helper.DropDownList("ddl" + question_id, typesList, "-- select type----));
}
else
{
output.Append(helper.DropDownList("ddl" + question_id, typesList, answer));
}
return helper.Raw(output.ToString());
}
Actually above code renders the selected value from database but it actually replacing the "-- select type ---" . So, After saving once if i visit the same page and save the page than i can get empty value in Formcollection.
So, please suggest the appropriate way of doing this
I usually add a few properties in my model:
int SelectedCategory { get; set; }
IEnumerable<SelectListItem> Categories { get; private set; }
and then load the data in my model constructor:
ProductService productService = new ProductService();
this.Categories =
productService.GetCategories()
.Select(c => new SelectListItem() { Text = c.Name, Id = c.Id.ToString() });
this.Categories.InsertAt(0, new SelectListItem() { Text = "--- Please Select ---", value = "" });
then in my Razor markup do something like:
#Html.DropDownListFor(m => m.SelectedCategory, Model.Categories)
This should auto wire up in the standard MVC way. Hope this helps.
I am attempting to display a form that allows a user to input a new assignment for a person. I'm using a DateTime.cshtml EditorTemplate to handle DateTime values for the assignment. The non-nullable DateTime works fine. The nullable DateTime causes an "InvalidOperationException: Nullable object must have a value."
I have a simple viewmodel that looks like this:
AssignmentViewModel.cs:
public Person Person { get; set; }
public Assignment NewAssignment { get; set; }
Assignment.cs contains:
public DateTime AssignmentStartDate { get; set; }
public DateTime? AssignmentEndDate { get; set; }
My AssignmentController Create() method looks like:
public ViewResult Create(int personId)
{
Person person = personRepository.GetPersonById(personId);
var newAssignment = new AssignmentViewModel { Person = person, NewAssignment = new Assignment() };
return View(newAssignment);
}
My Create.cshtml view looks like this:
#model AssignmentViewModel
#using (Html.BeginForm("Create", "Assignment"))
{
#Html.Hidden("NewAssignment.PersonId", Model.Person.PersonId)
#Html.LabelFor(x => x.NewAssignment.AssignmentStartDate):
#Html.EditorFor(x => x.NewAssignment.AssignmentStartDate.Date, new { cssClass = "datePicker" })
<br />
#Html.LabelFor(x => x.NewAssignment.AssignmentEndDate):
#Html.EditorFor(x => x.NewAssignment.AssignmentEndDate.Value.Date, new { cssClass = "datePicker" })
<br />
<input type="submit" value="Send />
}
My DateTime.cshtml EditorTemplate looks like:
#model DateTime?
#{
String modelValue = "";
if (Model.HasValue)
{
if (Model.Value != DateTime.MinValue)
{
modelValue = Model.Value.ToShortDateString();
}
}
}
#Html.TextBox("", modelValue, new { #class = "datePicker" })
When I attempt to load the Create view, I get the exception mentioned above on the line "#Html.EditorFor(x => x.NewAssignment.AssignmentEndDate.Value)".
You may be wondering why I'm passing in AssignmentEndDate.Value.Date instead of just passing in AssignmentEndDate; the reason is because I'm trying to get to the point where I'm splitting DateTime into Date and a TimeOfDay field and recombine them with a DateTimeModelBinder. I am using a similar technique to the one shown here and here.
I -can- bypass the error, by changing my controller Create() method to instantiate the ViewModel with AssignmentEndDate set to DateTime.MinValue, but this seems completely wrong for a nullable DateTime:
var newAssignment = new AssignmentViewModel
{
Person = person,
NewAssignment = new Assignment { AssignmentEndDate = DateTime.MinValue }
};
Something strange happens after I "bypass" the error by supplying a value for the nullable DateTime; the un-required nullable DateTime property (AssignmentEndDate.Date) fails client side validation. Trying to submit the form highlights the field in red.
How can I handle this correctly?
The problem is that you're trying to retrieve the AssignmentEndDate.Value.Date, but AssignmentEndDate is null, which results in this error.
Since your editor template accepts a DateTime?, you should just pass along the AssignmentEndDate. In other words, remove the .Value.Date from the view:
#Html.EditorFor(x => x.NewAssignment.AssignmentEndDate, new { cssClass = "datePicker" })
Since your editor template is using ToShortDateString(), there's no need to "truncate" the time from the date at all.
Update
Regarding your desire to have separate "Date" and "Time" editors:
You can do this 2 ways.
1 - Your current DateTime? editor renders a field for the Model.Value.Date, so you could simply extend this to also render a field for the Model.Value.TimeOfDay. Example:
#{
DateTime? modelDate = (Model == null) ? (DateTime?)null : Model.Value.Date;
TimeSpan? modelTime = (Model == null) ? (TimeSpan?)null : Model.Value.TimeOfDay;
}
#Html.TextBox(..., modelDate, new{#class="datePicker"})
#Html.TextBox(..., modelTime, new{#class="timePicker"})
2 - You could split the above functionality into 2 separate editors, "DateOnly" and "TimeOnly". Then, update your view to call both editors:
#Html.EditorFor(x => x.NewAssignment.AssignmentEndDate, "DateOnly")
#Html.EditorFor(x => x.NewAssignment.AssignmentEndDate, "TimeOnly")
The choice is up to you, and whether you want to keep the Date and Time parts separate or together, but this is how I'd go about solving this problem.
create a DateTime.cshtml in your Shared/DisplayTemplate folder
#model Nullable<DateTime>
#(Model != null ? string.Format(ViewData.ModelMetadata.DisplayFormatString ?? "{0:d}", Model) : string.Empty)
this supports metadata from datannotations to be used if found.
UPDATE: GetValueOrDefault treats it as a DateTime and therefore the required Field validators are getting attached, because the original expression is for a datetime not a nullable datetime.
Therefore the solution below doesn't work.
Like the asker, I also used the DateTimeModelBinder from here:
Here's the Link
This is how I solved a similar situation:
#Html.EditorFor(x => x.NewAssignment.AssignmentEndDate.GetValueOrDefault().Date)
And this is what my DateTime EditorTemplate looks like:
#model DateTime
#Html.TextBox("", Model != default(DateTime) ? Model.ToShortDateString() : String.Empty, new { #class = "datepicker", #maxlength = "10" })
code is:
#using (Html.BeginForm("Register", "User", FormMethod.Post, new { id = "RegisterForm" }))
{
#Html.DropDownList("StateId", new SelectList(Model.States, "StateId", "StateName"),
"--Select an option--", new { #tabindex = "11" })
}
i need required field validation for dropdown
Have you tried using Data Annotations in your model to mark the property as required?
[Required(ErrorMessage = "You must select a State")]
Are you exposing the StateId as a part of the Model? If so that's where you should set the Required Attribute, like so:
[Required(ErrorMessage = "You must select a State")]
public int StateId { get; set; }