Getting Values to Dropdown from Model - c#

I am trying to pull a list from my ViewModel to populate a drop-down. I can get the objects from the Model and pass them to the View, but the view just shows the name of the ViewModel as the value in the dropdown. Not sure how to get the actual values to the Dropdown or if am going in the wrong direction. No intellesence past the definition of the object "model.InitialFeesChart". Thanks in advance for looking.
Controller: Objects contain needed data
public ActionResult CreateFranchise()
{
var model = new FranchiseVM();
model.FranStates = new List<string> { "AZ", "NV", "CA" };
//Grap the Package Identificaton to determine Package selected by Franshise
model.InitialFeesChart = (from f in _db.InitalFeesCharts
select new InitalFeesChartVM {IFCPackage = f.IFCPackage}).ToList();
return View(model);
}
ViewModel:
namespace Compass.Models
{
public class FranchiseVM
{
[Key]
public int FranchiseID { get; set; }
public string FranPID { get; set; }
public string FranBusinessName { get; set; }
public string FranAddress { get; set; }
public string FranCity { get; set; }
public string FranState { get; set; }
public string FranPostalCode { get; set; }
public string FranPhonePrimary { get; set; }
public string FranPhonePrimaryCell { get; set; }
public string FranFAX { get; set; }
public string FranOwnerFirstName { get; set; }
public string FranOwnerLastName { get; set; }
public string FranAlternateFirstName { get; set; }
public string FranAlternateLastName { get; set; }
public string FranAlternatePhone { get; set; }
public string FranNotes { get; set; }
public string IFCPackageCurrent { get; set; }
public IList<string> FranStates { get; set; }
//public IList<InitalFeesChartVM> InitialFeesChart { get; set; }
//Added
public string IFCPackage { get; set; }
private readonly List<InitialFeesChart> _InitialFeesChart;
public IEnumerable<SelectListItem> IFCItems
{
get { return new SelectList(_InitialFeesChart, "InitialFeesID", "IFCPackage"); }
}
}
}
View:
<div class="form-group">
#Html.LabelFor(model => model.IFCPackageCurrent, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.IFCPackageCurrent, Model.IFCItems))
</div>
</div>
Final working code:
ViewModel
public IList<InitalFeesChartVM> InitialFeesChart { get; set; }
[Display(Name = "Franchise Package")]
public string IFCPackageCurrent { get; set; }
View:
<div class="form-group">
#Html.LabelFor(model => model.IFCPackageCurrent, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.IFCPackageCurrent, new SelectList(Model.InitialFeesChart, "InitialFeesID", "IFCPackage"))
</div>
</div>
Controller:
public ActionResult CreateFranchise()
{
var model = new FranchiseVM();
model.FranStates = new List<string> { "AZ", "NV", "CA" };
model.InitialFeesChart = (from f in _db.InitalFeesCharts select new InitalFeesChartVM { IFCPackage = f.IFCPackage, InitialFeesID = f.InitialFeesID }).ToList();
return View(model);

You need to specify what properties to use in the Select List. Specify the value field and the text field like this: SelectList(Items, "Id", "Title")
I've created a fiddle that uses your classes. You will have to change the string values in the part when the select list is created so that they match the properties you want to use from your InitalFeesChartVM http://dotnetfiddle.net/9052ZH

Related

Altering the output value of a SelectList in DropDownListFor in MVC View

I have this code inside my form:
<div class="form-group">
#Html.LabelFor(c => c.ClosingHourId)
#Html.DropDownListFor(c => c.ClosingHourId, new SelectList(Model.ClosingHours, "Id", "Time"), "Select time", new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.ClosingHourId)
</div>
The "Time" property is of type DateTime, so when I click the dropdown list on my page I see full dates and times, but the thing is I want to display only the hours, without the dates, so I want to use something like Time.ToString("H:mm") but I don't know where can I write this so it will work. Maybe the right approach would be to add something like [Display(Name = Time.ToString("H:mm"))] annotation in my ClosingHour Model? I'm not sure if it's possible.
My View Model:
public class CinemaFormViewModel
{
public int? Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
[Required]
public string Address { get; set; }
[Required]
[Display(Name = "Total Seats")]
public int TotalSeats { get; set; }
public IEnumerable<OpeningHour> OpeningHours { get; set; }
[Required]
[Display(Name = "Opens At")]
public byte? OpeningHourId { get; set; }
public IEnumerable<ClosingHour> ClosingHours { get; set; }
[Required]
[Display(Name = "Closes At")]
public byte? ClosingHourId { get; set; }
}
My ClosingHour Model:
public class ClosingHour
{
public byte Id { get; set; }
[Required]
public DateTime Time { get; set; }
}
The Action inside the controller which calls the view:
public ActionResult New()
{
var openingHours = _context.OpeningHours.ToList();
var closingHours= _context.ClosingHours.ToList();
var viewModel = new CinemaFormViewModel
{
OpeningHours = openingHours,
ClosingHours = closingHours
};
return View("CinemaForm", viewModel);
}
change you by adding string time property
public class ClosingHour
{
public byte Id { get; set; }
[Required]
public DateTime Time { get; set; }
[NotMapped]
public string ShortTime { get; set; }
}
action
public ActionResult New()
{
var closingHours= _context.ClosingHours.ToList();
var openingHours = _context.OpeningHours.ToList();
closingHours.ForEach(i=> i.ShortTime=i.Time.ToShortTimeString());
openingHours.ForEach(i=> i.ShortTime=i.Time.ToShortTimeString());
// or you can try
closingHours.ForEach(i=> {
i.ShortTime=i.Time.ToShortTimeString();
i.Time=null;
});
openingHours.ForEach(i=> {
i.ShortTime=i.Time.ToShortTimeString();
i.Time=null;
});
var viewModel = new CinemaFormViewModel
{
OpeningHours = openingHours,
ClosingHours = closingHours
};
return View("CinemaForm", viewModel);
}
view
....
#Html.DropDownListFor(c => c.ClosingHourId,
new SelectList(Model.ClosingHours, "Id", "ShortTime"), "Select time", new { #class = "form-control" })
.....

How can I bind CountryNames in DropDownListFor

I'm using mvc4. How can I Bind CuntryName and its values in DropdownList
Country?
public class Country
{
public int Cnt_Id { get; set; }
public string Cnt_Name { get; set; }
}
This is my private class
public class HybridEmployee
{
public IEnumerable<Country> GetCount { get; set; }
}
Controller
public ActionResult GetCountry()
{
var x = ObjRepo.GetCountry();
hybrid.GetCount = x;
return View(hybrid);
}
Index.cshtml
#model Mvc_Application.Models.HybridEmployee
#using Mvc_Application.Models
#using (Html.BeginForm("SaveEmp", "Home", FormMethod.Post))
{
#Html.DropDownListFor(x=>x.GetCount.FirstOrDefault().Cnt_Id),new SelectList(Model.GetCount,"","");
}
We can have two approaches as shown below:
Using a ViewBag containing the data for dropdown list.
Model file:
public class State
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public int CountryID { get; set; }
}
In .cs file:
ViewBag.Countries = countryService.All().Select(x => new SelectListItem() { Text = x.Name, Value = x.Id.ToString() }).ToList();
In .cshtml file:
#Html.DropDownListFor(x => x.CountryID, ViewBag.Countries as IEnumerable<SelectListItem>, "Select Country", new { #class = "form-control" })
Using a Model's property containing the data for dropdown list.
Model file:
public class State
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public int CountryID { get; set; }
public List<SelectListItem> Countries { get; set; }
}
In .cs file:
model.Countries = countryService.All().Select(x => new SelectListItem() { Text = x.Name, Value = x.Id.ToString() }).ToList();
In .cshtml file:
#Html.DropDownListFor(x => x.CountryID, Model.Countries, "Select Country", new { #class = "form-control" })
This expression totally doesn't makes sense:
#Html.DropDownListFor(x=>x.GetCount.FirstOrDefault().Cnt_Id),new SelectList(Model.GetCount,"","");
The first argument of DropDownListFor helper (Expression<Func<TModel, TProperty>> expression) doesn't use LINQ expression, it is model binding expression - you must use a property to hold selected value instead. The drop down list binding should be used like this:
Model
public class Country
{
public int Cnt_Id { get; set; }
public string Cnt_Name { get; set; }
public int SelectedCountry { get; set; } // additional property to get selected value
}
View
#Html.DropDownListFor(x => x.SelectedCountry, new SelectList(Model.GetCount, "Cnt_Id", "Cnt_Value"), null)

Table not incrementing after an insert in asp.net mvc

I'm working on an ASP.NET MVC project. I have created the various models and the viewmodels to use in my project. I have also seeded my database table with seed data but upon implementing the registration view, I tested the form but was getting 0 as the value inserted into the Id portion of the database table. I truncated the tables and did a fresh new insert I still had same error.
Below is the model for the user table
public class User
{
[Key]
public byte Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string RefIndicator { get; set; }
public Team TeamCategory { get; set; }
public byte TeamId { get; set; }
public bool IsRegistered { get; set; }
public DateTime DateRegistered { get; set; }
public DateTime? LastModified { get; set; }
public UserRoles UserRoles { get; set; }
public byte UserRolesId { get; set; }
}
and below is the viewModel I created for the Team Model property I needed to use in my view
public class RegisterFormViewModel
{
public User Users { get; set; }
public byte Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public IEnumerable<Team> Teams { get; set; }
public byte TeamId { get; set; }
public string RefIndicator { get; set; }
public bool IsRegistered { get; set; }
public DateTime DateRegistered { get; set; }
public byte UserRolesId { get; set; }
}
And here is the register action to the userController to initialize the values for the Register view
public ActionResult Register()
{
var AppUser = User.Identity.Name.Substring(5);
var AppUserEmail = AppUser + "#nlng.com";
int index = AppUser.IndexOf('.');
var FirstName = AppUser.Substring(0, index);
var LastName = AppUser.Substring(index + 1);
var IsRegistered = true;
var UserRolesId = 1;
var DateRegistered = HttpContext.Timestamp;
var teams = _context.Team.ToList();
var viewModel = new RegisterFormViewModel{
Email = AppUserEmail,
FirstName = FirstName,
LastName = LastName,
Teams = _context.Team.ToList(),
IsRegistered = IsRegistered,
UserRolesId = (byte)UserRolesId,
DateRegistered = DateRegistered
};
return View("Register", viewModel);
}
And finally here is the associated view for the registration page
#model eLeave.ViewModel.RegisterFormViewModel
#{
ViewBag.Title = "Register";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>User Registration</h2>
#using (Html.BeginForm("Save", "User"))
{
<div class="form-group">
#Html.LabelFor(r=>r.FirstName)
#Html.TextBoxFor(r => r.FirstName, new { #class = "form-control", #readonly = true })
</div>
<div class="form-group">
#Html.LabelFor(r => r.LastName)
#Html.TextBoxFor(r => r.LastName, new { #class = "form-control", #readonly = true })
</div>
<div class="form-group">
#Html.LabelFor(r => r.Email)
#Html.TextBoxFor(r => r.Email, new { #class = "form-control", #readonly = true })
</div>
<div class="form-group">
#Html.LabelFor(r => r.TeamId)
#Html.DropDownListFor(r => r.TeamId, new SelectList(Model.Teams, "Id", "TeamName"), "Select your Team", new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(r => r.RefIndicator)
#Html.TextBoxFor(r => r.RefIndicator, new { #class = "form-control" })
</div>
#Html.HiddenFor(m => m.IsRegistered)
#Html.HiddenFor(m => m.DateRegistered)
#Html.HiddenFor(m => m.UserRolesId)
#Html.HiddenFor(m => m.Id)
#Html.AntiForgeryToken()
<button class="btn btn-primary">Register</button>
}
Finally here's the save action of the userController
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Save(User user)
{
if (!ModelState.IsValid)
{
var viewModel = new RegisterFormViewModel
{
Users = user,
Teams = _context.Team.ToList()
};
return View("Register", viewModel);
}
if (user.Id == 0)
{
_context.User.Add(user);
}
else
{
var usersInDb = _context.User.Single(m => m.Id == user.Id);
usersInDb.FirstName = user.FirstName;
usersInDb.LastName = user.LastName;
usersInDb.TeamCategory = user.TeamCategory;
usersInDb.RefIndicator = user.RefIndicator;
usersInDb.UserRoles = user.UserRoles;
usersInDb.IsRegistered = user.IsRegistered;
usersInDb.Email = user.Email;
usersInDb.DateRegistered = user.DateRegistered;
}
_context.SaveChanges();
return RedirectToAction("Index", "User");
}
The Save Action basically does two things...It saves a new form and it's also used for updating data.
Would appreciate if the bugs in my code can be fished out.
Form what I understand, you need to make ID as auto incremented value.
public class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string RefIndicator { get; set; }
public Team TeamCategory { get; set; }
public byte TeamId { get; set; }
public bool IsRegistered { get; set; }
public DateTime DateRegistered { get; set; }
public DateTime? LastModified { get; set; }
public UserRoles UserRoles { get; set; }
public byte UserRolesId { get; set; }
}
I don't think it will work with byte, but you can use int for sure.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().Property(a => a.Id).HasKey(b => b.Id);
modelBuilder.Entity<User>().Property(a => a.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}

Saving selected multiSelectList items back to the model

I am working on a site where I have a MultiSelectList of categories. Each item can belong to multiple categories, and obviously each category can have many items. I have it selecting the correct items in the dropdownlist in my view. But once I save, I can't figure out how to save the selected items back into the model.
Here is my model:
public class WebItem
{
public string ImId { get; set; }
public string itemRef { get; set; }
public string name { get; set; }
public string Image { get; set; }
public string NUTS { get; set; }
public string description { get; set; }
public string ingredients { get; set; }
public string allergens { get; set; }
public string price { get; set; }
public string saleprice { get; set; }
public string quantity { get; set; }
private const string DEFAULT_USERNAME = "amyb";
private string _username = DEFAULT_USERNAME;
public string username {
get { return _username; }
set { _username = value; }
}
[Display(Name = "Active?")]
public bool active { get; set; }
[Display(Name = "Order online?")]
public bool orderonline { get; set; }
[Display(Name = "Food?")]
public bool isfood { get; set; }
[Display(Name = "Frozen?")]
public bool isfrozen { get; set; }
[Display(Name = "Overstock?")]
public bool isoverstock { get; set; }
public string activedate { get; set; }
//public int[] catIDs { get; set; }
public List<Category> Categories { get; set; }
public IEnumerable<SelectListItem> categories { get; set; }
private List<int> selectedCategories;
public List<int> SelectedCategories
{
get
{
if (selectedCategories == null)
{
selectedCategories = Categories.Select(m => int.Parse(m.catID)).ToList();
}
return selectedCategories;
}
set { selectedCategories = value; }
}
}
public class Category
{
public Category()
{
}
public Category(string catID, string name, string longname)
{
this.catID = catID;
this.name = name;
this.longname = longname;
}
public string catID { get; set; }
public string name { get; set; }
public string longname { get; set; }
}
Relevant controller code:
public ActionResult UpdateItem(string ImId)
{
WebItem item = new WebItem();
List<Category> categories = HomeModel.getAllCategories();
//var selectCategories = categories.Select(c => new
//{
// CategoryID = c.catID,
// CategoryName = c.longname
//}).ToList();
//item.categories = new MultiSelectList(selectCategories, "CategoryID", "CategoryName");
item.categories = categories.Select(c => new SelectListItem
{
Text = c.name,
Value = c.catID
});
if (ImId != null && !ImId.Equals(""))
{
string query = "SELECT 'Image', 'NUTS', ...";
MySqlConnection con;
//WebItem item = new WebItem();
try
{
con = new MySqlConnection();
con.ConnectionString = appConfig._...;
con.Open();
item = con.Query<WebItem>(query, new { imid = ImId }).FirstOrDefault();
string activedate = item.activedate;
if (activedate.Contains(' '))
{
string[] activedates = activedate.Split(' ');
item.activedate = activedates[0];
}
//List<Category> categories = HomeModel.getAllCategories();
//var selectCategories = categories.Select(c => new
//{
// CategoryID = c.catID,
// CategoryName = c.longname
//}).ToList();
query = "SELECT ...";
try
{
item.SelectedCategories = con.Query<int>(query, new { pid = ImId }).ToList();
}
catch (MySqlException ex)
{
}
//item.categories = new MultiSelectList(selectCategories, "CategoryID", "CategoryName", item.catIDs);
}
catch (MySqlException ex)
{
// show error somehow
//return View(ex.Message);
}
}
return View(item);
}
[HttpPost]
public ActionResult UpdateItem(WebItem item)
{
string result = HomeModel.insertUpdateItem(item);
TempData["Message"] = item.name + " has been inserted/updated.";
return RedirectToAction("WebItems");
}
And the relevant part of my view:
<div class="form-group">
#Html.LabelFor(model => model.categories, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#*#Html.DropDownList("category", (MultiSelectList)Model.categories, new { multiple = "multiple", htmlAttributes = new { #class = "form-control" } })*#
#Html.ListBoxFor(m => m.SelectedCategories, Model.categories)
#Html.ValidationMessageFor(model => model.categories, "", new { #class = "text-danger" })
</div>
</div>
I don't currently have any code dealing with the categories in my [HttpPost] section of my action. But I'm sure I need something there. And I'm not sure if my model or view are right either.
You may add a new property of array type to your vie wmodel to store the selected options from the multi select box.When the form is posted, MVC Model binding will properly bind the selected values to an object of this view model as long as we have that in our HttpPost action method as a parameter.
public class CreateWebItem
{
public string Name{ get; set; }
public List<SelectListItem> Categories { set; get; }
public int[] SelectedCategories { set; get; }
//Add other properties NEEDED FOR THE VIEW
}
And in your GET action
public ActionResult Create()
{
var vm = new CreateWebItem();
//Hard coded for demo. you may replace with values from db
v.Categories = new List<SelectListItem>
{
new SelectListItem { Value="1", Text="Dinner" },
new SelectListItem { Value="2", Text="Lunch" },
new SelectListItem { Value="3", Text="Snacks" },
new SelectListItem { Value="4", Text="Drinks" }
};
return View(vm);
}
And in your razor view which is strongly typed to the CreateWebItem view model.
#model CreateWebItem
#using (Html.BeginForm())
{
<label>FirstName </label>#Html.TextBoxFor(d => d.Name)
<label>Categories</label>
#Html.ListBoxFor(s=>s.SelectedCategories,Model.Categories)
<input type="submit" value="Add" />
}
And when the form is posted, you can use the SelectedCategories property to get an array of Id's (of the selected options)
[HttpPost]
public ActionResult Index(CreateWebItem model)
{
//read model.SelectedCategories array
// to do : Save to somewhere and do a redirect (PRG pattern)
}

Set Required = false in virtual property, Entity Framework

I have an ASP.NET MVC app and I am using Entity framework.
I have a model named Propiedad and this have some virtual properties without Required attibute, in the view I have a dropdown for the virtual properties and when I do not select an option this tell me that I have to select an option.
I need that Grupo property does not need to select another option, that I can select the optionLabel without show me validator error message.
This is the model:
public class Propiedad
{
[Key]
public int Id { get; set; }
public virtual Entidad Entidad { get; set; }
public virtual PestanasPorEntidad Pestana { get; set; }
public virtual GrupoDePropiedades Grupo { get; set; }
public string Codigo { get; set; }
public string Nombre { get; set; }
public string TipoDeDatos { get; set; }
public bool Requerido { get; set; }
[Required]
public int Orden { get; set; }
public string Columna { get; set; }
}
This is part of the view (Create):
<div class="form-group">
#Html.LabelFor(model => model.Grupo, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.Grupo.Id, (SelectList)(ViewBag.PestanaList), "Ninguno", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Grupo)
</div>
</div>
This is part of the controller
private void SetGrupoListViewBag()
{
ViewBag.GrupoList = new SelectList(unitOfWork.GrupoDePropiedadesRepository.Get(), "id", "nombre");
}
// GET: /GlobalAdmin/Propiedades/Create
public ActionResult Create()
{
var propiedad = new Propiedad();
SetTipoDeDatosListViewBag();
SetEntidadListViewBag();
SetPestanaListViewBag();
SetColumnaListViewBag();
SetGrupoListViewBag();
var entidadId = Request["entidadId"] != null ? Convert.ToInt32(Request["entidadId"]) : -1;
if (entidadId != -1)
{
propiedad.Entidad = unitOfWork.EntidadRepository.GetById(entidadId);
return View(propiedad);
}
else
{
return View();
}
}

Categories

Resources