Just a quick question on my drop down list there are 2 empty values, and then male and female, I was just wondering why these empty values appear, also I have left Gender? so, default empty is selected. Please advise.
public class PatientRegistrationViewModel
{
[Required(ErrorMessage = "Please select your gender.")]
public Gender? GGender
{ get; set; }
public enum Gender
{
[Display(Name = "Male", Order = 0)]
Male = 0,
[Display(Name = "Female", Order = 1)]
Female = 1
}
}
View
<div class="row">
<div class="col-md-6">
<!--<i class="fa fa-child" aria-hidden="true"></i>-->
#Html.LabelFor(model => model.GGender, "Choose your gender:", new { #style = "", #class = "", id = "" })
<span style="color: red;">*</span>
#*#Html.DropDownListFor(model => model.Profession, new SelectList(Model.Professions, "Id", "Name"), new { placeholder = "", #style = "", #class = "form-control", id = "Profession" })*#
#Html.EnumDropDownListFor(model => model.GGender, "", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.GGender)
</div>
</div>
Reason for the problem
the first empty value will come from the second parameter of this method call
#Html.EnumDropDownListFor(model => model.GGender, "", new { #class = "form-control" })
here you are passing an empty string to the value which must appear when nothing has been selected (I assume you already know that)
This was easy, so where the second empty value come from?
It is coming from your property GGender which is of type Nullable<Gender> not Gender so actually this property has three possible values
Male
Female
Null (which rendered as second empty value in select html element)
Solution
If you want to not select anything by default from the select HTML element
you have to change your property to following
[Required(ErrorMessage = "Please select your gender.")]
public Gender? GGender { get; set; } = null;
and your call in the view to
#Html.EnumDropDownListFor(model => model.GGender.Value, "Please Select gender ...", new { #class = "form-control" })
Though the data is empty, but what you see is a text or label not value. and
public enum Gender method shows it to display as this (Male or Female).
To test - do not display even text then remove name from like
display name = "" this will not show text now.
You can test if they have value or not by html inspect.
Help example here!
Related
I have a DropDownListFor with ViewBag as SelectList and looking to add one more option into dropdown with text as "Not Applicable" and value null.
Code on the ViewData:
ViewData["RegionID"] = new SelectList(_context.Region, nameof(LocationMaster.Region.RegionId), nameof(LocationMaster.Region.Name));
Current code on DropDownListFor
#Html.DropDownListFor(m => m.RegionID, (SelectList) ViewBag.RegionID, "Select Region", new {#class = "form-control", #data_val = "true", #data_val_required= "Region is required"})
Can I like append or insert one more item into the ViewData?
Create a variable (regionOptions) to hold the list of regions.
With Insert(int index, T value) to add a default option as the first element of the regionOptions array.
var regionOptions = _context.Region.Select(x => new
{
RegionId = (int?)x.RegionId,
Name = x.Name
}).ToList();
regionOptions.Insert(0, new { RegionId = (int?)null, Name = "Not Applicable" });
ViewData["RegionID"] = new SelectList(regionOptions, nameof(LocationMaster.Region.RegionId), nameof(LocationMaster.Region.Name));
Remove the placeholder: "Select Region"
#Html.DropDownListFor(m => m.RegionID, (SelectList) ViewBag.RegionID, new {#class = "form-control", #data_val = "true", #data_val_required= "Region is required"})
Demo (MVC) # .NET Fiddle
Note that you should remove the data validation #data_val = "true", #data_val_required= "Region is required" if you allow the RegionID drop-down list as not mandatory.
Or as you add the placeholder: "Select Region", you don't have to manually add the default option into ViewData["RegionID"]. By default its value is blank.
I want to send the selected text field in dropdown to the controller.
When I use the code as follows, I can send the id number to the controllers, but the value I selected in the list pass null.
In addition , if there is a registered value in the model, I want this field to be selected in the dropdownlist when the page is opened.
Controller
public ActionResult Degerlendir(int id ,string CV_STATU)
{
using (MULAKATDBEntities1 ent = new MULAKATDBEntities1())
{
CvViewModel cv = new CvViewModel();
var entData = ent.CV.FirstOrDefault(a => a.ID_CV == id);
entData.CV_STATU = CV_STATU;
ent.SaveChanges();
}
}
In View
#using (Html.BeginForm("Degerlendir", "Home", FormMethod.Post))
{
<input type="hidden" name="id" value="#Model.Cv.ID_CV" />
#Html.DropDownListFor(model => model.Cv.CV_STATU,
new List<SelectListItem> {
new SelectListItem() { Text = "Secilmedi" },
new SelectListItem() { Text = "Kabul edildi" },
new SelectListItem() { Text = "Reddedildi" } },
new {#id="cv_statu", #class = "form-control" })
<input type="submit" id="btnSubmit" value="KAYDET" class="btn btn-add" />
}
Set #name="cv_statu" within the HTML helper htmlAttributes for binding to parameters on POST like this.
Also change the controller method parameter to lowercase cv_statu. Only parameter names passed through URL routes are not case sensitive.
I am assuming that what you shared on your code for your ActionResult is already the HttpPost Action verb. There should be a proper HttpGet as well.
To solve your issue, make sure the first argument that you set on your DropDownListFor should match on the parameter of your Degerlendir
#Html.DropDownListFor(model => model.CV_STATU,
new List<SelectListItem> {
new SelectListItem() { Text = "Secilmedi", Value = "Secilmedi" },
new SelectListItem() { Text = "Kabul edildi", Value = "Secilmedi" },
new SelectListItem() { Text = "Reddedildi", Value = "Reddedildi", Selected = true} }, "Please select an option",
new {#id="cv_statu", #class = "form-control" })
As you notice, I changed your:
#Html.DropDownListFor(model => model.Cv.CV_STATU
To:
#Html.DropDownListFor(model => model.CV_STATU
Because what you set here will set the name attribute on your HTML. This will be binded on your parameter on your ActionResult of Degerlendir particularly your parameter:
string CV_STATU
Lastly, I added Value on your SelectListItem, because that will be passed on your ActionResult whatever you select on your DropDownList. To set the default selected value, just add Selected = true.
Afternoon Folks,
I am new to c# and im trying to create an if statement to check the value of two fields and if both of these fields are blank, to then display a message to the user.
My two fields are DateofBirth with a datatype of DateTime and Age with a datatype of int. Im using studio 2013 and have a c# mvc project.
In my create.cshtml page i am using razor syntax for these two form fields.
#Html.EditorFor(model => model.client.DateOfBirth, new { htmlAttributes = new { #class = "form-control", #placeholder = "dd-mm-yyyy" } })
and
#Html.EditorFor(model => model.client.AgeNotKnown, new { htmlAttributes = new { #class = "form-control", #placeholder = "Age in Years" } })
the user needs to fill in either one or the other field when submitting the form.
In my controller and my HttpPost for the ActionResult Create. I have tried a couple of ways to get this working via an if statement but i get seem to get this to work.
I have tried using the string.IsNullOrEmpty method, but as these are DateTime and int datatypes this will not work. See sample below.
if (string.IsNullOrEmpty(clientViewRecord.client.AgeNotKnown));
{
MessageBox.Show("please an Age if DOB not known");
}
db.ClientRecords.Add(clientViewRecord.client);
db.SaveChanges();
return RedirectToAction("MainMenu", "Home");
I get three errors here:
Argument 1: cannot convert from 'int?' to 'string'
The name 'MessageBox' does not exist in the current context 3) The
best overloaded method match for 'string.IsNullOrEmpty(string)' has
some invalid arguments
The best overloaded method match for 'string.IsNullOrEmpty(string)' has
some invalid arguments
Another way i have tried to get this working is the following...
if (clientViewRecord.client.AgeNotKnown == 0 || clientViewRecord.client.DateOfBirth == 0);
{
MessageBox.Show("please enter an Age or if DOB");
}
db.ClientRecords.Add(clientViewRecord.client);
db.SaveChanges();
return RedirectToAction("MainMenu", "Home");
I get the same issue for the message box and the following for the DateofBirth filed.
Operator '==' cannot be applied to operands of type 'System.DateTime?' and 'int'
Im new to c# but think that im kinda on the right lines, i think just need a little help or any suggestions.
Regards
Betty
? means nullable whose default value will be null if i use int? its default value will be null if i use int its default value will be 0
about validation you can use ModelState for validation in MVC and add a custom validation
#Html.ValidationMessage("validation")
#Html.EditorFor(model => model.DateOfBirth, new { htmlAttributes = new { #class = "form-control", #placeholder = "dd-mm-yyyy" } })
#Html.EditorFor(model => model.AgeNotKnown, new { htmlAttributes = new { #class = "form-control", #placeholder = "Age in Years" } })
i used #Html.ValidationMessage("validation") which will show the validation message if i return any and in your action
if (cls.DateOfBirth == null && cls.AgeNotKnown == null)
{
ModelState.AddModelError("validation","Please select one");
return View();
}
in action it will check condition if both are null then it will return to the same view including the validation message of key validation which is defined in the view.
First of all MessageBox class is belong to windows forms. If you want to wanr the user you should use validations. I prefer jquery validation
To add control like this, just put a breakpoint to your code and look want data coming from your form. This way you can decide how do you want to control your data.
System.DateTime? and int?, this question marks tell you that these variables can be null. So you should consider that while comparing.
First of all create ViewModel for this kind of validation
public class ClientViewModel
{
[Required, DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
public DateTime Date { get; set; }
[Required]
public int Age { get; set; }
}
In View
#model Models.ClientViewModel #*reference to your model usally create in Models folder*#
#Html.ValidationSummary() #* add this for validation summary displays here.*#
#Html.EditorFor(model => model.Date, new { htmlAttributes = new { #class = "form-control", #placeholder = "dd-mm-yyyy" } })
#Html.ValidationMessageFor(m => m.Date)
#Html.EditorFor(model => model.Age, new { htmlAttributes = new { #class = "form-control", #placeholder = "Age in Years" } })
#Html.ValidationMessageFor(m => m.Age)
#* Add jqueryval bundles which is created in app_start/BundleConfig *#
#section Scripts{
#Scripts.Render("~/bundles/jqueryval")
}
In Controller
//Change the name of PostMethod
public ActionResult PostMethod(Models.ClientViewModel model )
{
if (ModelState.IsValid)
{
// do your stuff
}
return View();
}
I have a view that has two input fields that are bound to a DateTime and a DateTime? (nullable DateTime) model property.
<div class="form-group">
#Html.LabelFor(model => model.EffectiveDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.EffectiveDate, new { htmlAttributes = new { id = "txtEffectiveDate", Value = Model.EffectiveDate.ToString("MM/dd/yyyy"), #class = "form-control " } })
#Html.ValidationMessageFor(model => model.EffectiveDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CancelDate, htmlAttributes: new {#class = "control-label col-md-2"})
<div class="col-md-10">
#Html.EditorFor(model => model.CancelDate, new {htmlAttributes = new {id = "txtCancelDate", #class = "form-control " } })
#Html.ValidationMessageFor(model => model.CancelDate, "", new {#class = "text-danger"})
</div>
</div>
Here's the two properties of the Model:
public class Edit
{
[Display(Name = "Effective Date")]
[Required(ErrorMessage = "{0} is required")]
public DateTime EffectiveDate { get; set; }
[Display(Name = "Cancel Date")]
[NotEqualTo("EffectiveDate")]
[IsGreaterThan(otherProperty:"EffectiveDate", ErrorMessage = "{0} must be after {1}")]
[Required(ErrorMessage = "{0} is required")]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true, NullDisplayText = "")]
public DateTime? CancelDate { get; set; }
--etc
}
Both fields are required, so I originally did not see a need for a Nullable DateTime data type. However, I'm finding that if I were to use the DateTime data type, I am getting unexpected behavior.
For example, if the user types in 11/32/2016 for either the Effective or Cancel Date fields, a client side validation error is displayed "The field Effective Date must be a date" and "The field Cancel Date must be a date." However, if the user types in 11/31/2016 for both values, the property attribute-driven client side validation does not catch this and the invalid dates are posted to the server as 1/1/0001 for the regular not nullable EffectiveDate property's value and NULL for the nullable CancelDate property. I was disappointed in this apparent shortcoming in what I would have expected to be a basic common edit, but things get worse when we post to the controller method...
Since client side validation logic wasn't good enough to catch on the client that 11/31/2016 was not a valid date, it seems reasonable to me that since the EffectiveDate is a DateTime, it must be assign some value and 1/1/0001 seemed like a reasonable choice. Furthermore, since CancelDate was nullable, null is posted, as expected.
In my controller, I check if the ModelState is invalid.
[HttpPost]
[ActionName("Edit")]
public ActionResult Edit(ViewModels.Edit modifiedAssessment)
{
if (!base.ModelState.IsValid)
{
return this.View(modifiedAssessment);
}
The ModelState contains two errors which are displayed next to their associated input fields:
The value '11/31/2017,07/22/2016 12:30:08' is not valid for Effective Date.
The value '11/31/2017' is not valid for Cancel Date.
Another issue:
Why are two dates, 11/31/2017 and 7/22/2016 (today), part of the error message for EffectiveDate?
Another troubling part is troubling part is that the Dates that now appear in the EffectiveDate and CancelDate input fields are now 01/01/0001 and 11/31/2017, respectively. Note that 11/31/2017 is not a valid value for either a dateTime or a DateTime? data type, yet the nullable CancelDate property did not wipe out the originally typed value but the EffectiveDate DateTime value did.
Given this behavior, how can anyone use the DateTime datatype for model binding? I tried to add the following attribute to the EffectiveDate DateTime property
[DataType( DataType.Date)]
but this opens up a large can of worms when I consider all of the browsers that may be using the web app.
It seems like I must be missing something basic since surely binding us a DateTime should be very common. I'm brand new to MVC.
When I create a SelecList I wish to be able to add SelecListItem's manually and to do this I use this code:
List<SelectListItem> Provinces = new List<SelectListItem>();
Provinces.Add(new SelectListItem() { Text = "Northern Cape", Value = "NC" });
Provinces.Add(new SelectListItem() { Text = "Free State", Value = "FS" });
Provinces.Add(new SelectListItem() { Text = "Western Cape", Value = "WC" });
SelectList lstProvinces = new SelectList(Provinces);
Instead of this :
var lstProvinces = new SelectList(new[] { "Northern Cape", "Free State", "Western Cape" });
After I created the SelectList, I pass it to the DropDownListFor via the ViewBag :
Html.DropDownListFor(m => m.StartPointProvince, (SelectList)ViewBag.Provinces)
However when I create the SelectList using the first method, it doesn't work - It adds the 3 values to the dropdown list, but all the values display as:
*screenshot of output
However when I use the second method, it works fine.
I wish to use the first method because i want to be able to specify the Text AND value of each item.
The problem is that SelectList(IEnumerable) constructor doesn't accept SelectListItem's (at least not as SelectListItem to add to its Items collection). It simply accepts collection of some arbitrary objects that will be used to generate completely unrelated internal SelectListItems collection.
If you want, you can use SelectList(IEnumerable, string, string) constructor in such way:
List<SelectListItem> Provinces = new List<SelectListItem>();
Provinces.Add(new SelectListItem() { Text = "Northern Cape", Value = "NC" });
Provinces.Add(new SelectListItem() { Text = "Free State", Value = "FS" });
Provinces.Add(new SelectListItem() { Text = "Western Cape", Value = "WC" });
this.ViewBag.Provinces = new SelectList(Provinces, "Value", "Text");
It will work. But it is unnecessary, because you create complex SelectListItem items that won't be used by the SelectList - it will just treat them as any other data object.
In the same way you can just use some other simpler class in place of SelectListItem:
public class SelectListModel
{
public String Text { get; set; }
public String Value { get; set; }
}
...
Provinces.Add(new SelectListModel() { Text = "Northern Cape", Value = "NC" });
Use DropDownList and name it the same as the model's property name. Mine is "ItemType"
#Html.LabelFor(model => model.ItemType, new { #class = "control-label" })
#Html.DropDownList("ItemType", (IEnumerable<SelectListItem>)ViewBag.ItemTypes, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ItemType, null, new { #class = "text-danger" })
var types = new List<SelectListItem>();
types.Add(new SelectListItem() { Text = "Select...", Value = string.Empty });
types.Add(new SelectListItem() { Text = "OTC", Value = "0" });
types.Add(new SelectListItem() { Text = "Generic", Value = "1" });
types.Add(new SelectListItem() { Text = "Brand", Value = "2" });
types.Add(new SelectListItem() { Text = "Non-Merchandise", Value = "9" });
ViewBag.ItemTypes = types;
[Required(ErrorMessage = "Item Type is required")]
public Int32 ItemType { get; set; }
you can change your code from
SelectList lstProvinces = new SelectList(Provinces);
to
SelectList lstProvinces = new SelectList(Provinces, "Value", "Text");
and it will display provinces correctly.
You do not need using SelectList.
Instead, put List<SelectListItem> Provinces into ViewBag and return ViewBag.
Then on the View put:
#Html.DropDownList("Dropwonlist", (IEnumerable<SelectListItem>)ViewBag.YourData)
Considering the number of views on this topic, I thought it might help others in giving some further examples of which the option you chose depends on the desired contents of the select list.
I usually prefer to keep the assignment of select dropdown options in a seperate class which is more manageble when creating longer lists, it's also handy to use the same class of optons for more common applications across the app.
C# Class
public class CustomFormsSelectDropdownParams
{
public static IEnumerable<SelectListItem> Example1ItemWidth { get; private set; }
public static IEnumerable<SelectListItem> Example2ItemWidth { get; private set; }
public static List<SelectListItem> Example3ItemWidth { get; private set; }
static CustomFormsSelectDropdownParams()
{
// ---------
// Exmaple 1
// ---------
// This is OK if you only have a
// relatively small amount of options to write.
Example1ItemWidth = new SelectListItem[]
{
// First item different to the remaining range.
new SelectListItem ("100%", "100%"),
new SelectListItem ("5em", "5em"),
new SelectListItem ("6em", "6em"),
new SelectListItem ("7em", "7em"),
new SelectListItem ("8em", "8em"),
new SelectListItem ("9em", "9em"),
new SelectListItem ("10em", "10em")
};
// ---------
// Exmaple 2
// ---------
// This is more practical if you have a large amount of options.
// NOTE: using this example doesnt allow us to insert any options
// that are different from the rest, so limited use cases may apply.
Example2ItemWidth = Enumerable.Range(1, 200).Select(x => new SelectListItem
{
Value = x.ToString() + "em",
Text = x.ToString() + "em",
});
// ---------
// Exmaple 3
// ---------
// This is more practical if you have a large amount of options.
// This example also allows us to add an option that is a different
// to the remaining options in the loop.
// Our first item is bespoke so created seperately.
var firstDefaultItem = new SelectListItem("100%", "100%");
// Provides a range between 10 --> 200em
var remainingItems = Enumerable.Range(10, 191).Select(x => new SelectListItem
{
Value = x.ToString() + "em",
Text = x.ToString() + "em",
});
Example3ItemWidth = new List<SelectListItem>();
// Add out first bespoke item.
Example3ItemWidth!.Add(firstDefaultItem);
// Add the remaining items in a loop.
foreach (var item in remainingItems)
{
Example3ItemWidth.Add(new SelectListItem(item.Text, item.Value));
}
}
}
Sample HTML Code:
<div class="container-fluid">
<div class="row">
<div class="mb-3 col-3" >
<label class="form-label">Example 1</label>
<select class="form-select" asp-items="Classes.CustomForms.CustomFormsSelectDropdownParams.Example1ItemWidth"></select>
</div>
</div>
<div class="row">
<div class="mb-3 col-3" >
<label class="form-label">Example 2</label>
<select class="form-select" asp-items="Classes.CustomForms.CustomFormsSelectDropdownParams.Example2ItemWidth"></select>
</div>
</div>
<div class="row">
<div class="mb-3 col-3" >
<label class="form-label">Example 3</label>
<select class="form-select" asp-items="Classes.CustomForms.CustomFormsSelectDropdownParams.Example3ItemWidth"></select>
</div>
</div>
</div>
All three select dropdowns on the page:
Example 1:
Example 2:
Example 3:
Example 3 was the one that had niggled me for a while, I wasnt sure how to create an select options list as well as adding some other bespoke options at the same time. If i need to to add some more additional besoke options then I would simply add them in what ever order I need, either before the loop, after or in between multiple loops.