This section creates job offers (it is a job portal), from which, you need to choose Area and Subarea. When I select an Area, I should see the Subareas of that Area. I leave an image to see the composition of the tables:
tables area & subarea
My job offer model is this:
namespace ProyectoBase4.Models
{
using System;
using System.Collections.Generic;
public partial class OfertaLaboral
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public OfertaLaboral()
{
this.OfertaPostulante = new HashSet<OfertaPostulante>();
}
public int Of_ID { get; set; }
public Nullable<int> OfEmp_ID { get; set; }
public string Of_Titulo { get; set; }
public string Of_Puesto { get; set; }
public Nullable<int> Of_Area { get; set; }
public Nullable<int> Of_Subarea { get; set; }
public string Of_Descrp { get; set; }
public string Of_Lugar { get; set; }
public Nullable<int> Of_Vacante { get; set; }
public Nullable<System.DateTime> Of_FechaIn { get; set; }
public Nullable<System.DateTime> Of_FechaFin { get; set; }
public Nullable<int> Of_Salario { get; set; }
public Nullable<int> Of_Jornada { get; set; }
public Nullable<int> Of_Mov { get; set; }
public Nullable<int> Of_Edu { get; set; }
public Nullable<int> Of_TContrato { get; set; }
public Nullable<int> Of_Estado { get; set; }
public virtual Area Area { get; set; }
public virtual Educacion Educacion { get; set; }
public virtual Estado Estado { get; set; }
public virtual Jornada_Compl Jornada_Compl { get; set; }
public virtual Movilidad Movilidad { get; set; }
public virtual Subarea Subarea { get; set; }
public virtual TipoContrato TipoContrato { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<OfertaPostulante> OfertaPostulante { get; set; }
}
}
How can I do that by choosing a field in Area, I display the corresponding Subtareas? This is the view:
<div class="">
<div class="form-group col-md-8">
#Html.LabelFor(model => model.Of_Titulo, htmlAttributes: new { style = "" })
<div class="">
#Html.EditorFor(model => model.Of_Titulo, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Of_Titulo, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group col-md-3">
#Html.LabelFor(model => model.Of_Area, htmlAttributes: new { #class = "", style = "margin-left:10px;" })
<div class="">
#Html.DropDownList("Of_Area", null, htmlAttributes: new { #class = "form-control form-control-75", style = "margin-left:10px;" })
#Html.ValidationMessageFor(model => model.Of_Area, "", new { #class = "text-danger" })
</div>
</div>
</div>
<br /><br /><br /><br />
<div>
<div class="form-group col-md-4">
#Html.LabelFor(model => model.Of_Vacante, htmlAttributes: new { #class = "" })
<div class="">
#Html.EditorFor(model => model.Of_Vacante, new { htmlAttributes = new { #class = "form-control form-control-50" } })
#Html.ValidationMessageFor(model => model.Of_Vacante, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group col-md-4">
#Html.LabelFor(model => model.Of_Salario, htmlAttributes: new { #class = "" })
<div class="">
#Html.EditorFor(model => model.Of_Salario, new { htmlAttributes = new { #class = "form-control form-control-50" } })
</div>
</div>
<div class="form-group col-md-3">
#Html.LabelFor(model => model.Of_Subarea, htmlAttributes: new { #class = "", style = "margin-left:40px;" })
<div class="">
#Html.DropDownList("Of_Subarea", null, htmlAttributes: new { #class = "form-control form-control-75", style = "margin-left:40px;" })
#Html.ValidationMessageFor(model => model.Of_Subarea, "", new { #class = "text-danger" })
</div>
</div>
As I mentioned before, I need that when I choose an option, then when I select the sub-option, only the options of that area appear to me.
Example:
view
Thanks
First, add an attribute to the subarea options with the area.
An example can be found here: SelectListItem with data-attributes
Second, handle the change() event of the area drop-down in jQuery. Use that event handler to hide() all options not in that area, and show() those that are.
$("#Of_Area").change(function(){
$("#Of_Subarea>option").hide();
$("#Of_Subarea>option[area=" + $("#Of_Area>option:selected").attr("value") + "]").show();
});
Related
I previously reveived some help here but some problems with the "Edit" arouse now. Currently stuck at HttpGet, HttpPost is yet to come.
In short, whenever I click on an existing item to edit, instead of the expected values, it returns an empty form, as seen here. (You might think that the reason for this is because I use the same exact view for Create and Edit but unfortunately this isn't, even when I used to separate ones, had the same result.)
Town.cs
using System.Collections.Generic;
namespace City.Models
{
public class Town
{
public Town()
{
Streets = new List<Street>();
}
public int TownId { get; set; }
public string TownName { get; set; }
public virtual ICollection<Street> Streets { get; set; }
}
}
Street.cs
using System.Collections.Generic;
namespace City.Models
{
public class Street
{
public Street()
{
Houses = new List<House>();
}
public int StreetId { get; set; }
public string StreetName { get; set; }
public virtual ICollection<House> Houses { get; set; }
}
}
House.cs
using System.Collections.Generic;
namespace City.Models
{
public class House
{
public House()
{
Floors = new List<Floor>();
}
public int HouseId { get; set; }
public string HouseName { get; set; }
public ICollection<Floor> Floors { get; set; }
}
}
Floor.cs
using System.Collections.Generic;
namespace City.Models
{
public class Floor
{
public Floor()
{
FireExtinguishers = new List<FireExtinguisher>();
}
public int FloorId { get; set; }
public int FloorNumber { get; set; }
public virtual ICollection<FireExtinguisher> FireExtinguishers { get; set; }
}
}
FireExtinguisher.cs
using System.ComponentModel;
namespace City.Models
{
public class FireExtinguisher
{
public int FireExtinguisherId { get; set; }
[DisplayName("Fire Extinguisher")]
public string FireExtinguisherName { get; set; }
public int FloorId { get; set; }
public int HouseId { get; set; }
public int StreetId { get; set; }
public int TownId { get; set; }
public Floor Floor { get; set; }
public House House { get; set; }
public Street Street { get; set; }
public Town Town { get; set; }
}
}
MyViewModel.cs
using System.Collections.Generic;
namespace City.Models
{
public class MyViewModel
{
public IEnumerable<Town> TownId { get; set; }
public IEnumerable<Street> StreetId { get; set; }
public IEnumerable<House> HouseId { get; set; }
public IEnumerable<Floor> FloorId { get; set; }
public FireExtinguisher FireExtinguisher { get; set; }
public string FireExtinguisherName { get; set; }
}
}
Create/Edit view
#model City.Models.MyViewModel
<h2>Add new or edit existing FE</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="col-md-12">
<div class="form-group">
#Html.LabelFor(model => model.TownId, "Town", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.TownId, new SelectList(Model.TownId, "TownId", "TownName"), "Choose Town", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.TownId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.StreetId, "Street", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.StreetId, new SelectList(Model.StreetId, "StreetId", "StreetName"), "Choose Street", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.StreetId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.HouseId, "House", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.HouseId, new SelectList(Model.HouseId, "HouseId", "HouseName"), "Choose House", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.HouseId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FloorId, "Floor", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.FloorId, new SelectList(Model.FloorId, "FloorId", "FloorNumber"), "Choose Floor", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.FloorId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FireExtinguisherName, "Fire Extinguisher", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.FireExtinguisherName, new { #class = "form-control", Value = "" })
#Html.ValidationMessageFor(model => model.FireExtinguisherName, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div>
<div>
<input type="submit" value="Do it" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Homecontroller.cs
using System;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using City.Models;
namespace City.Controllers
{
public class HomeController : Controller
{
private ApplicationDbContext db;
private MyViewModel viewModel;
public HomeController()
{
db = new ApplicationDbContext();
var town = db.Towns.ToList();
var street = db.Streets.ToList();
var house = db.Houses.ToList();
var floor = db.Floors.ToList();
viewModel = new MyViewModel()
{
TownId = town,
StreetId = street,
HouseId = house,
FloorId = floor
};
}
public ActionResult Index()
{
return View(db.FireExtinguishers.ToList());
}
[HttpGet]
public ActionResult Create()
{
return View(viewModel);
}
[HttpPost]
public ActionResult Create(FireExtinguisher fe)
{
if (ModelState.IsValid)
{
db.FireExtinguishers.Add(fe);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
[HttpGet]
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var fe = db.FireExtinguishers.Find(id);
var town = db.Towns.ToList();
var street = db.Streets.ToList();
var house = db.Houses.ToList();
var floor = db.Floors.ToList();
viewModel = new MyViewModel()
{
FireExtinguisher = fe,
TownId = town,
StreetId = street,
HouseId = house,
FloorId = floor
};
return View("Create", viewModel);
}
[HttpPost]
public ActionResult Edit()
{
throw new NotImplementedException();
}
}
}
Any help would be appreciated, thank you
Personally I like to use View- and Post-Models for that as a clear statement, what is send to the View (ViewModel) and what is send back via Post. As a naming convention the name of the model class Takes the controller name and the action name.
I start with the PostModel, which would be in your case
public class HomeEditPostModel
{
[Required]
[MaxLength(50)]
public string Name { get; set; }
[Required]
public int TownId { get; set; }
[Required]
public int StreetId { get; set; }
[Required]
public int HouseId { get; set; }
[Required]
public int FloorId { get; set; }
}
Now for the view we need some collections for the dropdown fields, where we can select from
public class SelectionItem<TKey>
{
public TKey Key { get; set; }
public string DisplayName { get; set; }
}
public class HomeEditViewModel : HomeEditPostModel
{
public IEnumerable<SelectionItem<int>> Town { get; set; }
public IEnumerable<SelectionItem<int>> Street { get; set; }
public IEnumerable<SelectionItem<int>> House { get; set; }
public IEnumerable<SelectionItem<int>> Floor { get; set; }
}
Now the view
#model WebApplication6.Models.HomeEditViewModel
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>HomeEditSubmitModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TownId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.TownId, new SelectList(Model.Town, "Key", "DisplayName"), "Choose Town", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.TownId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.StreetId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.StreetId, new SelectList(Model.Street, "Key", "DisplayName"), "Choose Street", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.StreetId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.HouseId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.HouseId, new SelectList(Model.House, "Key", "DisplayName"), "Choose House", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.HouseId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FloorId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.FloorId, new SelectList(Model.Floor, "Key", "DisplayName"), "Choose Floor", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.FloorId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
and finally the controller (only relevant parts)
public class HomeController : Controller
{
[HttpGet]
public ActionResult Edit(int id)
{
// just some fake data for demonstration
var model = new HomeEditViewModel
{
Name = "Name",
Floor = Enumerable.Range(1, 10).Select(e => new SelectionItem<int> { Key = e, DisplayName = $"Floor {e}" }),
Street = Enumerable.Range(1, 10).Select(e => new SelectionItem<int> { Key = e, DisplayName = $"Street {e}" }),
House = Enumerable.Range(1, 10).Select(e => new SelectionItem<int> { Key = e, DisplayName = $"House {e}" }),
Town = Enumerable.Range(1, 10).Select(e => new SelectionItem<int> { Key = e, DisplayName = $"Town {e}" }),
FloorId = 3,
StreetId = 4,
HouseId = 5,
TownId = 6,
};
return View(model);
}
[HttpPost]
public ActionResult Edit(int id, HomeEditPostModel model)
{
// needs to save the data here
return RedirectToAction(nameof(Index));
}
}
I'm calling three Models (Unit, Site, Work_Type) in my view model called UnitAdminViewModel. I need to set one field as required from the Unit Model. Since I'm using Database First approach, I cannot modify the Unit Model directly since this gets autogenerated. How can I successfully add:
[Required(ErrorMessage = "Group is required")]
public string GroupName { get; set; }
to my view model UnitAdminViewModel?
public class UnitAdminViewModel
{
public Unit Unit { get; set; }
public List<Site> Site { get; set; }
public IEnumerable<Work_Type> Work_Type { get; set; }
}
In the Unit Model, I want to set the field GroupName as [Required]
public partial class Unit
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Unit()
{
this.Staffs = new HashSet<Staff>();
}
public int UnitID { get; set; }
public string UnitCode { get; set; }
public string UnitName { get; set; }
public string GroupName { get; set; }
public byte IncentiveUnit { get; set; }
public bool CallCenter { get; set; }
public bool CDWUnit { get; set; }
public string CDWSite { get; set; }
public Nullable<int> SiteID { get; set; }
public Nullable<int> DivisionID { get; set; }
public bool WFCUnit { get; set; }
public bool QAMonitored { get; set; }
public bool NICEMonitored { get; set; }
public string ListPrefix { get; set; }
public string TSHSource { get; set; }
public string StatsSource { get; set; }
public string DialerSource { get; set; }
public Nullable<int> CostCenterID { get; set; }
public int WaterfallView { get; set; }
public bool Locked { get; set; }
public string Platform { get; set; }
public Nullable<int> Supplier { get; set; }
public string Work_Type { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Staff> Staffs { get; set; }
}
Update
I tried going off #Izzy example. I feel like i'm closer, but the [Required] still doesn't seem to trigger a validation error when I submit a form without populating that field. #Izzy, is there something I might be missing?
View Model
public class UnitAdminViewModel
{
public Unit Unit { get; set; }
public List<Site> Site { get; set; }
public IEnumerable<Work_Type> Work_Type { get; set; }
}
UnitMetaData class
[MetadataType(typeof(UnitMetaData))]
public partial class Unit
{
}
public class UnitMetaData {
[Required(ErrorMessage = "Group is required")]
public string GroupName { get; set; }
[Required(ErrorMessage = "UnitName is required")]
public string UnitName { get; set; }
public string CDWSite { get; set; }
public string Platform { get; set; }
public Nullable<int> Supplier { get; set; }
public string Work_Type { get; set; }
}
VIEW
#model WebReportingToolDAL.Models.ViewModels.UnitAdminViewModel
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Unit</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Unit.UnitName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Unit.UnitName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Unit.UnitName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Unit.GroupName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Unit.GroupName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Unit.GroupName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Unit.CDWSite, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Unit.CDWSite, new SelectList(Model.Site, "SiteName", "SiteName"), new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Unit.Platform, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Unit.Platform, new List<SelectListItem> { new SelectListItem { Text = "PSCC", Value = "PSCC" }, new SelectListItem { Text = "RC", Value = "RC" } }, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Unit.Supplier, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Unit.Supplier, new List<SelectListItem> { new SelectListItem { Text = "0", Value = "0" }, new SelectListItem { Text = "1", Value = "1" } }, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Unit.Work_Type, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Unit.Work_Type,new SelectList(Model.Work_Type, "Name", "Name"),new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "UnitID,UnitCode,UnitName,GroupName,IncentiveUnit,CallCenter,CDWUnit,CDWSite,SiteID,DivisionID,WFCUnit,QAMonitored,NICEMonitored,ListPrefix,TSHSource,StatsSource,DialerSource,CostCenterID,WaterfallView,Locked,Platform,Supplier,Work_Type")] Unit unit)
{
if (ModelState.IsValid)
{
unit.UnitCode = "XX";
unit.IncentiveUnit = 1;
unit.CallCenter = true;
unit.CDWUnit = true;
unit.DivisionID = 2;
unit.WFCUnit = false;
unit.QAMonitored = false;
unit.NICEMonitored = true;
unit.ListPrefix = null;
unit.TSHSource = null;
unit.StatsSource = null;
unit.DialerSource = null;
unit.CostCenterID = 3;
unit.WaterfallView = 1;
unit.Locked = false;
var siteId = (from s in db.Sites
where s.SiteName.ToLower().Equals(unit.CDWSite.ToLower())
select s.SiteID).First();
unit.SiteID = siteId;
db.Units.Add(unit);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(unit);
}
When using Database first approach you'll realise that the class is marked as partial So what you can do is make use of MetadataType attribute to achieve what you're after.
So go ahead and create a file and name it e.g. UnitMetaData. Your code should look something like:
public class UnitMetaData
{
[Required(ErrorMessage = "Group is required")]
public string GroupName { get; set; }
//more properties
}
Your Unit class is partial so you can create it another file and use MetadataType as:
[MetadataType(typeof(UnitMetaData))]
public partial class Unit
{
}
More about MetadataType here
partial definition:
It is possible to split the definition of a class or a struct, an interface or a method over two or more source files. Each source file contains a section of the type or method definition, and all parts are combined when the application is compiled.
source
Please Note: Ensure the namespace is same as the generated Unit class, otherwise it will not work
You can use a real view model, for one. Simply wrapping a bunch of entities in a class is missing the point of what view models are for. Your view models should only contain the properties that should be displayed/edited and it should hold the business logic for your view, such as the fact that GroupName is required (when it apparently isn't at the database level).
That means creating something like:
public class UnitViewModel
{
// other properties you want to edit
[Required]
public string GroupName { get; set; }
}
Then, you use this rather than Unit in your view, and map the posted properties from UnitViewModel onto your Unit instance.
I'm having trouble retrieving the correct value to my DropDownList Control within the Edit Action.
Customer Model:
public class Customer
{
public int CustId { get; set; }
public string CustDisplayName { get; set; }
public string CustFirstName { get; set; }
public string CustLastName { get; set; }
public string CustCompanyName { get; set; }
public string CustAddress { get; set; }
public string CustPhoneNumber { get; set; }
public string CustMobileNumber { get; set; }
public string CustEmailAddress { get; set; }
public int StId { get; set; }
public State State { get; set; }
}
State Model:
public class State
{
public int StId { get; set; }
public string StAbbr { get; set; }
public List<Customer> Customers { get; set; }
}
Manufacturer Model:
public class Manufacturer
{
public int MfrId { get; set; }
public string MfrCompanyName { get; set; }
public string MfrWebsiteDomainName { get; set; }
}
CustomerFormViewModel
public class CustomerFormViewModel
{
public int CustId { get; set; }
[Required(ErrorMessage = "Display Name is required!")]
[Display(Name = "Display Name")]
[StringLength(100)]
public string CustDisplayName { get; set; }
[Display(Name = "First Name")]
[StringLength(50)]
public string CustFirstName { get; set; }
[Display(Name = "Last Name")]
[StringLength(50)]
public string CustLastName { get; set; }
[Display(Name = "Company Name")]
[StringLength(50)]
public string CustCompanyName { get; set; }
[Display(Name = "Phone Number")]
[DataType(DataType.PhoneNumber)]
[StringLength(12)]
[RegularExpression(#"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}", ErrorMessage = "Invalid Phone Number format!")]
public string CustPhoneNumber { get; set; }
[Display(Name = "Mobile Number")]
[DataType(DataType.PhoneNumber)]
[StringLength(12)]
[RegularExpression(#"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}", ErrorMessage = "Invalid Number!")]
public string CustMobileNumber { get; set; }
[Display(Name = "Email Address")]
[DataType(DataType.EmailAddress)]
[StringLength(320)]
public string CustEmailAddress { get; set; }
[Required(ErrorMessage = "Address is required!")]
[Display(Name = "Address")]
[StringLength(100)]
public string CustAddress { get; set; }
[Required(ErrorMessage = "State is required!")]
[Display(Name = "State")]
public int StId { get; set; }
public IEnumerable<State> States { get; set; }
}
CustomerController:
public class CustomerController : Controller
{
private WebAppDbContext _context;
public CustomerController(WebAppDbContext context)
{
_context = context;
}
// GET: /<Customer>/
public IActionResult Index()
{
return View(_context.Customers.ToList());
}
public ActionResult Create()
{
var states = _context.States.ToList();
var viewModel = new CustomerFormViewModel
{
States = states
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CustomerFormViewModel vm)
{
if (ModelState.IsValid)
{
var customer = new Customer();
{
customer.CustDisplayName = vm.CustDisplayName;
customer.CustFirstName = vm.CustFirstName;
customer.CustLastName = vm.CustLastName;
customer.CustCompanyName = vm.CustCompanyName;
customer.CustAddress = vm.CustAddress;
customer.CustPhoneNumber = vm.CustPhoneNumber;
customer.CustMobileNumber = vm.CustMobileNumber;
customer.CustEmailAddress = vm.CustEmailAddress;
customer.StId = vm.StId;
}
_context.Customers.Add(customer);
_context.SaveChanges();
return RedirectToAction("Index");
}
else
{
vm.States = _context.States.ToList();
return View(vm);
}
}
public ActionResult Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var customervm = new CustomerFormViewModel();
{
Customer customer = _context.Customers.SingleOrDefault(c => c.CustId == id);
if (customer == null)
{
return NotFound();
}
customervm.CustId = customer.CustId;
customervm.CustDisplayName = customer.CustDisplayName;
customervm.CustFirstName = customer.CustFirstName;
customervm.CustLastName = customer.CustLastName;
customervm.CustCompanyName = customer.CustCompanyName;
customervm.CustAddress = customer.CustAddress;
customervm.CustPhoneNumber = customer.CustPhoneNumber;
customervm.CustMobileNumber = customer.CustMobileNumber;
customervm.CustEmailAddress = customer.CustEmailAddress;
customervm.StId = customer.StId;
}
return View(customervm);
}
}
Create View:
<div class="form-group">
#Html.LabelFor(c => c.CustDisplayName)
#Html.TextBoxFor(c => c.CustDisplayName, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.CustDisplayName)
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustFirstName)
#Html.TextBoxFor(c => c.CustFirstName, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustLastName)
#Html.TextBoxFor(c => c.CustLastName, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustCompanyName)
#Html.TextBoxFor(c => c.CustCompanyName, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustAddress)
#Html.TextBoxFor(c => c.CustAddress, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.CustAddress)
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustPhoneNumber)
#Html.TextBoxFor(c => c.CustPhoneNumber, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.CustPhoneNumber)
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustMobileNumber)
#Html.TextBoxFor(c => c.CustMobileNumber, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.CustMobileNumber)
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustEmailAddress)
#Html.TextBoxFor(c => c.CustEmailAddress, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.CustEmailAddress)
</div>
<div class="form-group">
#Html.LabelFor(s => s.StId)
#Html.DropDownListFor(s => s.StId, new SelectList(Model.States, "StId", "StAbbr"), "", new { #class = "form-control" })
#Html.ValidationMessageFor(s => s.StId)
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
Edit View:
<div class="form-group">
#Html.LabelFor(c => c.CustDisplayName)
#Html.TextBoxFor(c => c.CustDisplayName, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.CustDisplayName)
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustFirstName)
#Html.TextBoxFor(c => c.CustFirstName, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustLastName)
#Html.TextBoxFor(c => c.CustLastName, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustCompanyName)
#Html.TextBoxFor(c => c.CustCompanyName, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustAddress)
#Html.TextBoxFor(c => c.CustAddress, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.CustAddress)
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustPhoneNumber)
#Html.TextBoxFor(c => c.CustPhoneNumber, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.CustPhoneNumber)
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustMobileNumber)
#Html.TextBoxFor(c => c.CustMobileNumber, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.CustMobileNumber)
</div>
<div class="form-group">
#Html.LabelFor(c => c.CustEmailAddress)
#Html.TextBoxFor(c => c.CustEmailAddress, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.CustEmailAddress)
</div>
<div class="form-group">
#Html.LabelFor(s => s.StId)
#Html.DropDownListFor(s => s.StId, new SelectList(Model.States, "StId", "StAbbr"), "", new { #class = "form-control" })
#Html.ValidationMessageFor(s => s.StId)
</div>
#Html.HiddenFor(c => c.CustId)
<div class="form-group">
<button type="submit" class="btn btn-primary">Update</button>
</div>
It is same as your create action, Load the collection property for all states (States) and also set the property for the selected item (StId) on your view model object.
So add this code to your Edit GET action method.
var customervm = new CustomerFormViewModel();
{
// Your existing code to map the entity property values goes here
}
//Load all the states
var states = _context.States.ToList();
customervm.States = states;
//Set the selected state
customervm.StId = customer.StId;
return View();
How to save data from Select box in Entity Framework Database relation Many to Many
There are two classes one weapon and other User..
public class Weapon { } public class User { }
public class User
{
public int ID { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
public class Wepon
{ public int ID { get; set; }
public string Wepon_Name { get; set; }
public int Power { get; set; }
}
Which should have relation Many to Many Using FormCollection and Model
User Class
And Weapon Class
public class User
{
public int ID { get; set; }
public string Name { get; set; }
public string Type { get; set; }
**public List<Wepon> WeposInList { get; set; }**
}
public class Wepon
{
public int ID { get; set; }
public string Wepon_Name { get; set; }
public int Power { get; set; }
public List<User> UsersHaveWeponsList { get; set; }// User the List for M to M
}
DBContext
public class DbContexFor : DbContext
{
public DbContexFor()
: base("name=ConnectionStringName")
{
}
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<Wepon> Wepons { get; set; }
}
}
**
The Controller Code
**
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Name,Type")] User user, FormCollection formData)
{
if (ModelState.IsValid)
{
var ss = formData["ShipFromCountries"].ToString();
user.WeposInList = db.Wepons.Where(c => c.Wepon_Name == ss).ToList();
db.Users.Add(user);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(user);
}
And the Html Code
#model enumVarAction.Models.User
#{
var list = ViewBag.MyList;
ViewBag.Title = "Create";
}
Create Html Page
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>User</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Type, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Type, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Type, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.WeposInList, htmlAttributes: new { #class = "control-label col-md-2" })
<select id="ShipFromCountries" multiple="multiple" name="ShipFromCountries">
<div class="col-md-10">
#foreach (var VARIABLE in list)
{
<option value="#VARIABLE.Wepon_Name">#VARIABLE.Wepon_Name</option>
}
</div>
</select>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
**
Debug at Controller
**
**
Data is Database
**
I have a little blog application with posts and tags. This is my model for Post:
namespace HelloWorld.Models
{
public class Post
{
[Required]
[DataType(DataType.Text)]
public string Title { get; set; }
[Required]
[DataType(DataType.MultilineText)]
public string Description { get; set; }
[Required]
[DataType(DataType.DateTime)]
public DateTime PostDate { get; set; }
public List<Tag> Tags { get; set; }
[Required]
public int PostId { get; set; }
}
public class CreatePostView
{
[Required]
[DataType(DataType.Text)]
public string Title { get; set; }
[Required]
[DataType(DataType.MultilineText)]
public string Description { get; set; }
[Display(Name = "Tags")]
[Required(ErrorMessage = "Please select a tag")]
public string SelectedTag { get; set; }
public SelectList TagList { get; set; }
[Required]
public int PostId { get; set; }
}
}
And model of Tag consist of string TagName, int TagId, List Posts.
When I create a new Post I use CreatePostView and my view is:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="create-post-form">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<strong>Title</strong>
<div class="col-md-10">
#Html.EditorFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Title, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<strong>Description</strong>
<div class="col-md-10">
#Html.EditorFor(model => model.Description, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Description, "", new { #class = "text-danger" })
</div>
</div>
#Html.DropDownListFor(m => m.SelectedTag, Model.TagList, "Add tag")
#Html.ValidationMessageFor(m => m.SelectedTag)
<div class="post-create-button">
<input type="submit" value="Create">
</div>
<div class="back-to-list-button">
#Html.ActionLink("Back", "Index")
</div>
</div>
}
And now I want to display my tag that I selected. I put value of selected tag in ViewBag, but it does not display. Maybe it's silly, but I do not know how to fix it. My Create action of PostsController:
// POST: Posts/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreatePostView post)
{
Post currPost = new Post {
Title = post.Title,
Description = post.Description,
PostDate = DateTime.Now,
Tags = null };
ViewBag.Tag = post.SelectedTag.ToString();
ViewBag.Trash = "texttexttexttexttext"; // It's strange, but it not displayed.
if (ModelState.IsValid)
{
//var tags = db.Tags.Where(s => s.TagName.Equals(post.SelectedTag)).ToList();
//currPost.Tags = tags;
db.Posts.Add(currPost);
db.SaveChanges();
return RedirectToAction("Index", "Posts");
}
return View(currPost);
}
My view with all Posts (use model Post)
#foreach (var item in Model)
{
<article class="post">
<h3>#Html.DisplayFor(modelItem => item.Title)</h3>
<p>#Html.DisplayFor(modelItem => item.Description)</p>
<!--None of them is not shown-->
<p><strong>Tag: #ViewBag.Tag</strong></p>
<p><strong>Trash: #ViewBag.Trash</strong></p>
</article>
}
ViewBag is used when returning a view, not when redirecting to another action. Basically it doesn't persist across separate requests. Try using TempData instead:
TempData["Tag"] = post.SelectedTag.ToString();
and in the view:
<p><strong>Tag: #TempData["Tag"]</strong></p>