I would like to know if it is even possible to combine jQuery with a #Html.DropDownListFor in a strongly typed view, as I am beginning to suspect that either it isn't, or my approach to this problem is flawed.
Model:
public class NewUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public string ConfirmEmail { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
public SelectListItem DOBDay { get; set; }
public SelectListItem DOBMonth { get; set; }
public SelectListItem DOBYear { get; set; }
public string Gender { get; set; }
}
View:
#model test.Models.NewUser
#using (Ajax.BeginForm("RegisterUser", "Register", new AjaxOptions { OnSuccess = "" }))
{
<div>
#Html.TextBoxFor(m => Model.FirstName, new { #class = "big_i", #watermark = "First name" })
#Html.TextBoxFor(m => Model.LastName, new { #class = "big_i", #watermark = "Last name" })
</div>
<div>
#Html.TextBoxFor(m => Model.EmailAddress, new { #class = "big_i long_i", #watermark = "E-mail address" })
</div>
<div>
#Html.TextBoxFor(m => Model.ConfirmEmail, new { #class = "big_i long_i", #watermark = "Confirm e-mail address" })
</div>
<div>
#Html.PasswordFor(m => Model.Password, new { #class = "big_i long_i", #watermark = "Password" })
</div>
<div>
#Html.PasswordFor(m => Model.ConfirmPassword, new { #class = "big_i long_i", #watermark = "Confirm password" })
</div>
<div>
<fieldset>
<h2>
Date of birth</h2>
<div id="reg_date_control" class="date_control">
#Html.DropDownListFor(m => Model.DOBDay, Enumerable.Empty<SelectListItem>(), "Day: ", new { #class = "dc-days big_i" })
#Html.DropDownListFor(m => Model.DOBMonth, Enumerable.Empty<SelectListItem>(), "Month: ", new { #class = "dc-months big_i" })
#Html.DropDownListFor(m => Model.DOBYear, Enumerable.Empty<SelectListItem>(), "Year: ", new { #class = "dc-years big_i" })
</div>
</fieldset>
</div>
}
Controller action for form submit:
[HttpPost]
public ActionResult RegisterUser(Models.NewUser model)
{
string firstName = model.FirstName;
string lastName = model.LastName;
string email = model.EmailAddress;
string confirm_email = model.ConfirmEmail;
string password = model.Password;
string confirm_password = model.ConfirmPassword;
string dob_month = model.DOBMonth.Value; // an error is raised here
return View();
}
I am trying to initially bind the #Html.DropDownListFor with an empty list, which the jQuery will then populate. I won't paste the jQuery code here, it is basically populating each DOB drop down with the valid number of days in a selected month.
The lists populate fine. However, DOBDay, DOBMonth, and DOBYear are always null. I expect that using Enumerable.Empty() is my problem, but having said that, I have tried populating the dropdowns like so:
#model gs_mvc.Models.NewUser
#{
string[] months = new[]{"January", "February", "March", "April", "etc"};
var items = new List<SelectListItem>();
for (int i = 0; i < months.Length; i++) {
items.Add(new SelectListItem { Value = i.ToString(), Text = months[i] });
}
}
...
#Html.DropDownListFor(m => Model.DOBMonth, items, "Month: ", new { #class = "big_i" })
which also gives a null value.
At this point, I believe that my best bet would be to move the functionality of my jQuery script to C#, and do an AJAX call each time the dropdowns are changed. However, I wanted to check here first that I'm not missing something blindingly obvious that would allow me to do what I'm trying.
I think your problem is that the values on the model for month, day, and year should probably be int not SelectListItem. SelectListItem is used to build the options, since it has both the Text and Value properties, but what you want to and will receive back are just the values - not Text/Value pairs. Of course, you probably want to make them nullable so that you're sure that you're receiving values from the POST rather than just having them default to zero.
public class NewUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public string ConfirmEmail { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
public int? DOBDay { get; set; }
public int? DOBMonth { get; set; }
public int? DOBYear { get; set; }
public string Gender { get; set; }
}
Related
During the next time, I could create some posts because I'm learning C# and ASP.NET MVC. I'm coming from Pythonic world, so some things are not clear for me.
I would like to generate a List of strings, then I would like to display this list in my form as a DropDownList.
This is my model:
public class Joueur
{
public int ID { get; set; }
[Required, Display(Name = "Nom"), StringLength(30)]
public string Lastname { get; set; }
[Required, Display(Name = "Prénom"), StringLength(30)]
public string Firstname { get; set; }
[Required, StringLength(15)]
public string Poste { get; set; }
public string Image { get; set; }
}
This is my controller according to Create Method:
// GET: Joueurs/Create
public ActionResult Create()
{
List<Strings> posteList = new List<SelectListItem>{ "Gardien", "Défenseur", "Milieu", "Attaquant" };
ViewBag.PosteList = posteList;
return View();
}
And this is my view:
<div class="col-md-10">
#*ViewBag.PosteList is holding all the postes values*#
#Html.DropDownListFor(model => model.Poste, ViewBag.PosteList as SelectList, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Poste, "", new { #class = "text-danger" })
</div>
But I get this issue:
#Html.DropDownListFor(model => model.Poste, ViewBag.PosteList as SelectList, new { #class = "form-control" })
There is no ViewData element of type « IEnumerable » with the key « Poste ».
How I could do that ?
With Django, it's pretty easy, in my model I create a dictionary and I pass this dict in the property, but with C# ASP.NET? I don't find a way to do that.
I assume your view will display a form to represent the Joueur object that you want the user to fill out, and your ViewBag.PosteList will have the values that the user can select from for the Joueur.Poste property. In order to accomplish this, you should create a new/empty Joueur object in your Create controller method and pass it to the view like so:
public ActionResult Create()
{
var model = new Joueur();
List<Strings> posteList = new List<SelectListItem>{ "Gardien", "Défenseur", "Milieu", "Attaquant" };
ViewBag.PosteList = posteList;
return View(model);
}
Then the rest of your original code should work.
I found a solution, hopefully it's a good way:
In my model I created an Enum:
public class Joueur
{
public int ID { get; set; }
[Required, Display(Name = "Nom"), StringLength(30)]
public string Lastname { get; set; }
[Required, Display(Name = "Prénom"), StringLength(30)]
public string Firstname { get; set; }
[Required, StringLength(15)]
public Position Poste { get; set; }
public string Image { get; set; }
}
public enum Position
{
Gardien,
Défenseur,
Milieu,
Attaquant
}
And in my view I added:
<div class="form-group">
#Html.LabelFor(model => model.Poste, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.Poste, new SelectList(Enum.GetValues(typeof(FCSL.Models.Joueur.Position))), "Sélectionner le poste", new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Poste, "", new { #class = "text-danger" })
</div>
</div>
And I applied migration commands. It seems to work now.
#Html.DropDownList("Poste", new SelectList( ViewBag.PosteList, "id", "Poste"))
and in controller
public ActionResult Create()
{
List<Strings> posteList = new List<SelectListItem>{ "Gardien", "Défenseur", "Milieu", "Attaquant" };
ViewBag.PosteList = posteList;
return View(ViewBag.PosteList); // return viewbag
}
I am trying to post the form values back to the controller. But in the action, I get the ViewModel as null.
Here is ViewModel
public class CommunicationDetailsViewModel
{
public string OrganizationName { get; set; }
public List<Country> Country { get; set; }
public List<State> State { get; set; }
public List<City> City { get; set; }
[Display(Name = "Id")]
public int CountryId { get; set; }
[Display(Name = "Id")]
public int StateId { get; set; }
[Display(Name = "Id")]
public int CityId { get; set; }
[StringLength(32), Required(ErrorMessage ="Address is required")]
public string Address { get; set; }
[StringLength(32), Required(ErrorMessage = "Building name is required")]
public string BuildingName { get; set; }
}
Below is the controller action:
[HttpPost]
public ActionResult Save(CommunicationDetailsViewModel communicationDetailsViewModel)
{
return View();
}
Does it have to do anything with the Kendo UI for MVC? Because this is the very first time I am using Kendo UI. Below is the view:
#model WebAPI.ViewModels.CommunicationDetailsViewModel
#{
ViewBag.Title = "Supplier Information";
}
<h4>Supplier Details</h4>
#using (Html.BeginForm("Save", "SupplierInformation", FormMethod.Post ))
{
<div class="demo-section k-content">
<div class="form-group">
#Html.Label("Organization name")
#Html.Kendo().TextBoxFor(model => model.OrganizationName).Name("txtOrganization").HtmlAttributes(new { #class = "k-textbox required", placeholder = "Organization Name" })
</div>
<div class="form-group">
#Html.Label("Country")
#(Html.Kendo().DropDownList().Name("ddlCountry").DataTextField("CountryName").DataValueField("Id").BindTo(Model.Country))
</div>
<div class="form-group">
#Html.Label("State")
#(Html.Kendo().DropDownList().Name("ddlState").DataTextField("StateName").DataValueField("Id").BindTo(Model.State))
</div>
<div class="form-group">
#Html.Label("City")
#(Html.Kendo().DropDownList().Name("ddlCity").DataTextField("CityName").DataValueField("Id").BindTo(Model.City))
</div>
<div class="form-group">
#Html.Label("Address")
#Html.Kendo().TextBoxFor(model => model.Address).Name("txtAddress").HtmlAttributes(new { #class="k-textbox required", placeholder="Address", #maxlength = "32" })
</div>
<div class="form-group">
#Html.Label("Building name")
#Html.Kendo().TextBoxFor(model => Model.BuildingName).Name("txtBuildingName").HtmlAttributes(new { #class = "k-textbox required", placeholder = "Address", #maxlength = "32" })
</div>
</div>
#Html.Kendo().Button().Name("btnSave").Content("Save").HtmlAttributes(new { type = "submit", #class = "k-button k-primary" })
}
And interestingly, if I use FormCollection instead of my ViewModel, I am able to get the values in the action.
What am I missing here? Must be something stupid. Any help appreciated.
I think problem here is caused by you change name by Name function. Note that MVC binding properties by name attribute of input tag so don't change it
For example you use
#Html.Kendo().TextBoxFor(model => model.OrganizationName).Name("txtOrganization").HtmlAttributes(new { #class = "k-textbox required", placeholder = "Organization Name" })
You change name of input from OrganizationName to txtOrganization that may cause MVC cann't binding properties exactly. You should keep its original name or ignore change its name like this
#Html.Kendo().TextBoxFor(model => model.OrganizationName).Name("OrganizationName").HtmlAttributes(new { #class = "k-textbox required", placeholder = "Organization Name" })
I try to update one property in table from SelectedList
Here is my model
public partial class Interwier
{
[Key]
public int Interwier_id { get; set; }
[Display(Name = "ФИО")]
public string FIO { get; set; }
[Display(Name = "Email")]
public string Email { get; set; }
[Display(Name = "Телефон")]
public string Telephone { get; set; }
[Display(Name = "День рождения")]
public System.DateTime Birthday { get; set; }
[Display(Name = "Город")]
public string City { get; set; }
[Display(Name = "Зарплата")]
public string Salary { get; set; }
[Display(Name = "Английский язык")]
public string English { get; set; }
public Nullable<int> VacancyId { get; set; }
public string Status { get; set; }
public virtual Vacancy Vacancy { get; set; }
}
I need to update Status property.
Here is Edit action in controller
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Interwier interwierModel = db.InterwierModels.Find(id);
if (interwierModel == null)
{
return HttpNotFound();
}
return View(interwierModel);
}
// POST: Interwier/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,Email,Telephone,Birthday,City,Salary,English,Status")] Interwier interwierModel)
{
if (ModelState.IsValid)
{
db.Entry(interwierModel).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Incoming");
}
return View(interwierModel);
}
And here is how it looks on View
<div class="form-group" style="padding-left: 515px;">
<div class="col-md-10">
#Html.DropDownListFor(model => model.Status, new[]
{
new SelectListItem() {Text = "Подтвердить", Value = "Одобрено"},
new SelectListItem() {Text = "Отправить в архив", Value = "Архив"},
}, "Статус", new { #class = "form-control" })
</div>
</div>
When I click submit button I have this error
How I can handle this?
You need to include Interwier_id property as hidden field. Use HiddenFor extension method. You don't post the ID to server that's why EF cannot find the entity in DB. Assuming the code below is within the BeginForm block.
#Html.DropDownListFor(model => model.Interwier_id)
<div class="form-group" style="padding-left: 515px;">
<div class="col-md-10">
#Html.DropDownListFor(model => model.Status, new[]
{
new SelectListItem() {Text = "Подтвердить", Value = "Одобрено"},
new SelectListItem() {Text = "Отправить в архив", Value = "Архив"},
}, "Статус", new { #class = "form-control" })
</div>
</div>
And also update properties that you bind from Id to Interwier_id:
[Bind(Include = "Interwier_id,...")]
I am very new to MVC5 and JQuery and I trying to create a cascading drop down. When the user selects a Practice from the drop down I am trying to get the Opticians that work in that Practice to populate.
Optician Model:
public class Optician
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid OpticianId { get; set; }
[ForeignKey("User")]
public string UserId { get; set; }
public virtual ApplicationUser User { get; set; }
public IEnumerable<SelectListItem> UserList { get; set; }
[ForeignKey("Practice")]
public Guid PracticeId { get; set; }
public virtual Practice Practice { get; set; }
public IEnumerable<SelectListItem> PracticeList { get; set; }
public virtual ICollection<ApplicationUser> Users { get; set; }
public virtual ICollection<Practice> Practices { get; set; }
}
Practice Model:
public class Practice
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Name = "Practice")]
public Guid PracticeId { get; set; }
[Display(Name = "Practice Name")]
public string PracticeName { get; set; }
public virtual ICollection<Optician> Opticians { get; set; }
public virtual ICollection<Booking> Bookings { get; set; }
}
Application User Model:
public class ApplicationUser : IdentityUser
{
[Display(Name = "Title")]
public string Title { get; set; }
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
}
Controller :
public ActionResult TestDropDown()
{
var PracticeListItems = (from d in db.Practices
select d.PracticeName).ToList();
SelectList Practice = new SelectList(PracticeListItems);
ViewData["Practice"] = Practice;
return View();
}
public JsonResult Opticians(Guid? Id)
{
var OpticianList = (from d in db.Opticans
where d.PracticeId == Id
select d.User.FirstName).ToList();
return Json(OpticianList);
}
The View:
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script>
$(document).ready(function () {
$("#Optician").prop("disabled", true);
$("#Practice").change(function () {
if ($("#Practice").val() != "Select") {
var PracticeOptions = {};
PracticeOptions.url = "/Bookings1/Opticians";
PracticeOptions.type = "POST";
PracticeOptions.data = JSON.stringify({ Practice: $("#Practice").val() });
PracticeOptions.datatype = "json";
PracticeOptions.contentType = "application/json";
PracticeOptions.success = function (OpticianList) {
$("#Optician").empty();
for (var i = 0; i < OpticianList.length; i++) {
$("#Optician").append("<option>" + StatesList[i] + "</option>");
}
$("#Optician").prop("disabled", false);
};
PracticeOptions.error = function () { alert("Error in getting Practices"); };
$.ajax(PracticeOptions);
}
else {
$("#Optician").empty();
$("#Optician").prop("disabled", true);
}
});
});
#using (Html.BeginForm("TestDropDown", "Bookings1", FormMethod.Post))
{
#Html.AntiForgeryToken()
<h4>Select Practcie & Opticians</h4>
<hr />
#Html.ValidationSummary()
<div class="form-group">
#Html.Label("Select Practice :", new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownList("Practice", ViewData["Practices"] as SelectList, new { #class = "form-control" })
</div>
</div><br />
<div class="form-group">
#Html.Label("Select Optician :", new { #class = "col-md-2 control-label" })
<div class="col-md-10">
<select id="Optician"></select>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Submit" />
</div>
</div>
}
However, when I run the application the Practice Name populates but the Optician First Name does not. There are no errors and I am unsure of where I am going wrong. Any help would be greatly appreciated.
Seems like you have a few issues with your code.. Starting with your SelectList.
When you define your select list it helps if you tell it what your Value and Text properties are..
public ActionResult TestDropDown()
{
var practices = new SelectList(db.Practices, "PracticeId", "PracticeName");
ViewData["Practices"] = practices;
return View();
}
Then you should probably return more information in your Opticians json result
[HttpPost]
public JsonResult Opticians(Guid? Id)
{
var opticianList = db.Opticians.Where(a => a.PracticeId == Id).Select(a => a.User).ToList();
return Json(opticianList);
}
In your javascript once you get the names sorted out out you can reference the property FirstName of the result.
$(document).ready(function () {
$("#Optician").prop("disabled", true);
$("#Practice").change(function () {
$.ajax({
url = "#Url.Action("Opticians","Bookings1")",
type = "POST",
data = {Id : $(this).val() }
}).done(function(OpticianList){
$("#Optician").empty();
for (var i = 0; i < OpticianList.length; i++) {
$("#Optician").append("<option>" + OpticianList[i].FirstName + "</option>");
}
$("#Optician").prop("disabled", false);
});
});
});
I'm not sure why you were passing paramater Practice to an action that took a parameter Id but it should be fixed in the code above.
I have a View:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="input-group">
<div class="input-group-addon">
#Html.Label("Employee number", new { #class = "control-label" })
</div>
<div class="a">
#Html.TextBoxFor(model => model.EmployeeNo, new {#class="form-control" })
#Html.ValidationMessageFor(model => model.EmployeeNo)
</div>
</div>
/*
* other fields
*/
}
and Controller:
[HttpPost]
public ActionResult Edit([Bind(Include="Id,EmployeeNo,Name,Surname,ContactInfo,RoleId")] User user)
{
ValidateRequestHeader(Request);
if (ModelState.IsValid)
{
unitOfWork.userRepository.Update(user);
unitOfWork.Save();
return Json(new { ok = true, newurl = Url.Action("Index") });
}
//ModelState.AddModelError("", "Niepoprawne dane");
ViewBag.RoleId = new SelectList(unitOfWork.roleRepository.Get(), "Id", "RoleName", user.RoleId);
return PartialView(user);
}
and model:
public partial class User
{
public User()
{
this.DeviceUsages = new HashSet<DeviceUsage>();
}
public int Id { get; set; }
[Required(ErrorMessage="Brak numeru pracownika")]
public string EmployeeNo { get; set; }
[Required(ErrorMessage = "Brak imienia")]
public string Name { get; set; }
[Required(ErrorMessage = "Brak nazwiska")]
public string Surname { get; set; }
[Required(ErrorMessage = "Brak Adresu email")]
public string ContactInfo { get; set; }
public int RoleId { get; set; }
}
Data annotations are working. If I leave eg. Name empty ModelState is not Valid in controler. But validation messages are not shown. If I uncomment this line:
ModelState.AddModelError("", "Niepoprawne dane"); this will be the only Model error shown in the View.
Where is a mistake in my code?
It's because you are using #Html.ValidationSummary(true) means excludePropertyErrors = true