Validate Html.DropDownListFor, not send detault value when httpPost - c#

I'm having this dropDownListFor:
#Html.DropDownListFor(m => m.ChoosenThemeSetting, Model.ThemeSettings.Select(k => new SelectListItem { Text = k.ChoosenTheme, Value = k.ChoosenTheme, }), "-- Select here --", new { #class = "form-control", id = "colorIfZero" })
In the code I've set "-- Select here --" as the default value. If I don't select anything else than the detault value in my dropDown, the default value will be posted to my [httpPost]-method.
Is there some way to valite this. Like: if selected value is my default value, give me a validation message to choose somthing from my dropDown. Becaues my default "-- Select here --" I would not like to send to my [httpPost]

Problem solved thank's to this link: http://forums.asp.net/t/1580133.aspx?DropDownListFor+validation. Thank you ravikatha!
By setting the model-class that hold the property for ChoosenThemeSetting to (in the class)
[Required]
[DisplayName("")]
public string ChoosenThemeSetting { get; set; }
And then change my DropDown-code to this (note the string.empty-line)
#Html.DropDownListFor(m => m.ChoosenThemeSetting, Model.ThemeSettings.Select(k => new SelectListItem { Text = k.ChoosenTheme, Value = k.ChoosenTheme, }), string.Empty, new { #class = "form-control", id = "colorIfZero" })
And everything works fine!
I now get a validationmessage to chose some of the values from my DropDown

Related

How to set default value for ASP.NET MVC DropDownList from ViewBag

In the controller Index I have the following:
ViewBag.Assignees = (await GetAllUsers()).Select(a =>
new SelectListItem
{
Text = a.DisplayName,
Value = a.Username,
Selected = a.DisplayName == "John Smith"
}).OrderBy(x => x.Text).ToList();
In the View, I have the following:
#Html.DropDownListFor(model => model.Assignee,
ViewBag.Assignees as List<SelectListItem>,
"Select Assignee",
new { id = "ddlAssignee", #class = "form-control"})
The dropdownlist populates as expected, however, the default (selected = true) value, which does exist, does not get set. Can someone advise what is wrong in the above?
UPDATE:
By Changing the SelectListItem.Value to a.DisplayName (same as SelectedListItem.Text) I achieved it. Still not sure what prevents the dropdownlist from displaying the item with Selected = true
If the model.Assignee comes with value, and if it is an int it will be defaulted to 0, it will override the SelectListItem selected value.
I suggest to set up the model.Assignee.
Here two ways that i use.
WAY 1
#Html.DropDownListFor(model => model.Assignee,
ViewBag.Assignees as List<SelectListItem>,
"Value", // property to be set as Value of dropdown item
"Text", // property to be used as text of dropdown item
"1"), // value that should be set selected of dropdown
new { id = "ddlAssignee", #class = "form-control"})
WAY 2
<select name="SelectName" value="1" class="w-100">
#foreach (var item in ViewBag.Collection) {
<option value="#item.Id">#item.Name</option>
}
</select>
I hope it work for you
#Html.DropDownListFor how to set default value
In your view set:
#Html.DropDownListFor(model => model.Assignee,
ViewBag.Assignees as List<SelectListItem>,
"Select Assignee",
new { id = "ddlAssignee", #class = "form-control", #value = "Default value"})
When you have list already defined.
Use This
#Html.DropDownList("CoverageDropDown", new SelectList(Model.youList, "Code", "Description",item.seletecItem), "Select")

preselect dropdown list razor page

I have the below code that I use to populate my dropdown in my Razor Page
I want to preselect a description - the "Value" of that needs to be set is found in
s.UserEstablishmentId
How can I preselect this on the dropdown
#Html.DropDownList("drpEstablishments",
getEstablishments().Select(s => new SelectListItem()
{
Text = s.Description,
Value = s.EstablishId.ToString()
}),
new
{
#class = "dropdown form-control"
})
You're using linq to create a new SelectListItem for getEstablishments element. When creating each instance of a SelectListItem() you need to determine if Selected should be true or false. Simply replace YourConditionForSelectionHere with a method that returns a bool or syntax that returns a bool, shown below:
#Html.DropDownList("drpEstablishments",
getEstablishments().Select(s => new SelectListItem()
{
Selected = (YourConditionForSelectionHere),
Text = s.Description,
Value = s.EstablishId.ToString()
}),
new
{
#class = "dropdown form-control"
})
in the end something like this worked
Selected= (s.UserEstablishmentId==s.EstablishId)? true:false,

MultiLineText DataType Value not populating in TextAreaFor

I am attempting to implement an Update on a current text area value.
The datatype is set for multiline in my model
[DataType(DataType.MultilineText)]
public string Text { get; set; }
When the page loads for the textarea, it does not populate.
#Html.TextAreaFor(a => a.Text, new { #Value = Model.Text })
But for a textbox it does populate
#Html.TextBoxFor(a => a.Text, new { #Value = Model.Text })
Is there something I'm missing? this seems pretty straight forward.
#Html.TextAreaFor(a => a.Text, new { id = "SomeID", placeholder = "Text", Value = Model.Text})
#Html.TextAreaFor(m => m.UserName) should be enough - ASP MVC takes care of populate current value from model to textarea.
Using { #Value = Model.Text } doesn't apply to textarea as it does not uses value attribute: How to add default value for html <textarea>?

Setting the default value of an enum dropdown in Razor

I'm trying to create an Item edit screen where the user can set a property of the Item, the ItemType. Ideally, when the user returns to the screen, the dropdown would display the ItemType already associated with the Item.
As it is, regardless of what the item.ItemType is, the dropdown will not reflect that in the dropdown. Is there a way around this?
For reference, my code at the moment is:
<div class="form-group">
#Html.LabelFor(model => model.ItemType, new { #class = "control-label col-xs-4" })
<div class="col-xs-8">
#Html.DropDownListFor(model => model.ItemType, (SelectList)ViewBag.ItemType, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ItemType, String.Empty, new { #class = "text-danger" })
</div>
</div>
The ViewBag is set with the following:
var ItemType = Enum.GetValues(typeof(ItemType));
ViewBag.ItemType = new SelectList(ItemType);
If you're using ASP.NET MVC 5, try just using the EnumHelper.GetSelectList method. Then you don't need ViewBag.ItemType.
#Html.DropDownListFor(model => model.ItemType, EnumHelper.GetSelectList(typeof(ItemType)), new { #class = "form-control" })
If not, you might need to specify the data value and data text fields of the select list.
var itemTypes = (from ItemType i in Enum.GetValues(typeof(ItemType))
select new SelectListItem { Text = i.ToString(), Value = i.ToString() }).ToList();
ViewBag.ItemType = itemTypes;
Then since it's an IEnumerable<SelectListItem> you'll need to change your cast.
#Html.DropDownListFor(model => model.ItemType, (IEnumerable<SelectListItem>)ViewBag.ItemType, new { #class = "form-control" })
Eventually I found a fix - manual creation of the list.
<select class="form-control valid" data-val="true"
data-val-required="The Item Type field is required." id="ItemType" name="ItemType"
aria-required="true" aria-invalid="false" aria-describedby="ItemType-error">
#foreach(var item in (IEnumerable<SelectListItem>)ViewBag.ItemType)
{
<option value="#item.Value" #(item.Selected ? "selected" : "")>#item.Text</option>
}
</select>
Try to keep as much of the logic outside of the View and in the Controller.
I saw in your self answer that it looks like you have an enum selected from wihin your controller.
I have a DropDownList in one of my apps that contains a list of Enums. It also has a default value selected, but also has specific enums available to the user. The default selection can be set from within the controller.
This example is based on what my needs were, so you'll need to adapt to your case.
In the controller:
public ActionResult Index()
{
ViewBag.NominationStatuses = GetStatusSelectListForProcessView(status)
}
private SelectList GetStatusSelectListForProcessView(string status)
{
var statuses = new List<NominationStatus>(); //NominationStatus is Enum
statuses.Add(NominationStatus.NotQualified);
statuses.Add(NominationStatus.Sanitized);
statuses.Add(NominationStatus.Eligible);
statuses.Add(NominationStatus.Awarded);
var statusesSelectList = statuses
.Select(s => new SelectListItem
{
Value = s.ToString(),
Text = s.ToString()
});
return new SelectList(statusesSelectList, "Value", "Text", status);
}
In the view:
#Html.DropDownList("Status", (SelectList)ViewBag.NominationStatuses)
This approach will automatically set the default item to the enum that was selected in the controller.

ASP.NET MVC4 Model's Child Collection Drop Down List not binding properly

I'm having the same issue as this here I believe, but the workaround is not working for me.
My issue is that I have a child collection of models inside my main view's ViewModel. They contain data to be displayed in two fields, a dropdownlist and a password field. Each dropdownlist selection must be unique. Everything is saving and being sent to the view properly, however the dropdownlist are not binding to the selected values when the view is called but the password field is. They all default to the first selection, even though the property they are suppose to bind to is unique and only one can be the first value. Any help or insight is appreciated. Thanks.
Here is the part in my view where the issue is occurring. I have commented out my efforts and tried the above link's workaround to no avail:
#functions {
private IEnumerable<SelectListItem> Mark(IEnumerable<SelectListItem> items, object Id)
{
foreach (var item in items)
if (string.CompareOrdinal(item.Value, Convert.ToString(Id)) == 0)
item.Selected = true;
return items;
}
}
#for (int j = 0; j < Model.PasswordResetQuestionUserAnswers.Count(); j++)
{
#Html.Hidden("PasswordResetQuestionUserAnswers.Index", j)
#Html.HiddenFor(p => Model.PasswordResetQuestionUserAnswers[j].Id)
#Html.HiddenFor(p => Model.PasswordResetQuestionUserAnswers[j].UserId)
<div class="form-group">
<label class="col-md-2 control-label">Password Reset Question #(j+1)</label>
<div class="col-md-6">
#*#Html.DropDownList("PasswordResetQuestionUserAnswers[" + j + "].PasswordResetQuestionId", Model.PasswordResetQuestionList, new { #class = "form-control passwordQuestion" })*#
#*#Html.DropDownListFor(x => Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, Model.PasswordResetQuestionList, new { #class = "form-control passwordQuestion" })*#
#Html.DropDownListFor(x => Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, Mark(Model.PasswordResetQuestionList, Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId))
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">Password Reset Answer #(j+1)</label>
<div class="col-md-6">
#Html.Password("PasswordResetQuestionUserAnswers[" + j + "].Answer", Model.PasswordResetQuestionUserAnswers[j].Answer, new { #class = "form-control passwordQuestionUserAnswer" })
#*#Html.PasswordFor(x => Model.PasswordResetQuestionUserAnswers[j].Answer, new { #class = "form-control passwordQuestionUserAnswer" })*#
</div>
</div>
}
I just had this same problem. This syntax works for me:
#Html.DropDownListFor(x => x.ChildCollection[i].ChildID, new SelectList(ViewBag.ChildCollectionSelect as SelectList, "Value", "Text", Model.ChildCollection[i].ChildID))
Define the SelectList as new, then specifically set the selected value from the model.
This is an adaption to the example of above, for what worked for me in a similar scenario, where itm represents the child object in the collection. I'm not exactly sure what all is going on in that example -- too many "Questions", "Users", and "Answers", but say if you wanted a dropdown of users and it to be filled with the particular one that had been assigned to that child item:
foreach (var itm in Model.PasswordResetQuestionUserAnswers)
{
#Html.DropDownListFor(modelItem => itm.UserId,
new SelectList( (IEnumerable<SelectListItem>)ViewData["users"], "Value", "Text", itm.UserId),
htmlAttributes: new { #class = "form-control" }
)
}
Where you'd fill ViewData["users"] like this in the Controller method that renders the view:
var usersList = GetUsersList();
ViewData["users"] = usersList;
and have these supporting functions:
private static SelectListItem[] _UsersList;
/// <summary>
/// Returns a static category list that is cached
/// </summary>
/// <returns></returns>
public SelectListItem[] GetUsersList()
{
if (_UsersList == null)
{
var users = repository.GetAllUsers().Select(a => new SelectListItem()
{
Text = a.USER_NAME,
Value = a.USER_ID.ToString()
}).ToList();
users.Insert(0, new SelectListItem() { Value = "0", Text = "-- Please select your user --" });
_UsersList = users.ToArray();
}
// Have to create new instances via projection
// to avoid ModelBinding updates to affect this
// globally
return _UsersList
.Select(d => new SelectListItem()
{
Value = d.Value,
Text = d.Text
})
.ToArray();
}
Repository.cs
My Repository function GetAllUsers() for the function, above:
Model1 db = new Model1(); // Entity Framework context
// Users
public IList<USERS> GetAllUsers()
{
return db.USERS.OrderBy(e => e.USER_ID).ToList();
}
Users.cs
public partial class USERS
{
[Key]
public int USER_ID { get; set; }
[Required]
[StringLength(30)]
public string USER_NAME { get; set; }
}
Edit
After re-reading the question, it seems it was about posting password reset questions.
foreach (var itm in Model.PasswordResetQuestionUserAnswers)
{
#Html.DropDownListFor(modelItem => itm.PasswordResetQuestionId,
new SelectList( (IEnumerable<SelectListItem>)ViewData["pwordResetQuestions"], "Value", "Text", itm.PasswordResetQuestionId),
htmlAttributes: new { #class = "form-control" }
)
}
And you'd have to have a ViewData["pwordResetQuestions"] filled like this in the controller method that renders that view:
var questionsList = GetQuestionsList();
ViewData["questions"] = questionsList;
and these supporting functions/objects:
private SelectListItem[] _QuestionsList;
public SelectListItem[] GetQuestionsList()
{
if (_QuestionsList == null)
{
var questions = PasswordResetQuestionUserAnswers.Select(a => new SelectListItem()
{
Text = a.Answer, //? I didn't see a "PasswordResetQuestionText" call in your example, so...
Value = a.PasswordResetQuestionId.ToString()
}).ToList();
questions.Insert(1, new SelectListItem() { Value = "1", Text = "Mother's Maiden Name" });
questions.Insert(2, new SelectListItem() { Value = "2", Text = "Elementary school attended" });
_QuestionsList = questions.ToArray();
}
// Have to create new instances via projection
// to avoid ModelBinding updates to affect this
// globally
return _QuestionsList
.Select(d => new SelectListItem()
{
Value = d.Value,
Text = d.Text
})
.ToArray();
}
I hard-coded some questions in there - I kinda doubt you'd have a table for them, usually companies only have less than 10. But you could always do that database call like I did for the Users table if they were using a database table - which is why I left that example there.
I was having the same issue and fighting with it. The examples above got me over the hump, but I was able to simplify using the code the way you have it, with one modification:
Original Code
#Html.DropDownListFor(x => Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, Model.PasswordResetQuestionList, new { #class = "form-control passwordQuestion" })
Update Code: (Wrap it with a new SelectList)
#Html.DropDownListFor(x => Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, new SelectList(Model.PasswordResetQuestionList, "Value", "Text", Model.PasswordResetQuestionUserAnswers[j].PasswordResetQuestionId, new { #class = "form-control passwordQuestion" })
This eliminates the need for the ViewBag or ViewData.

Categories

Resources