I am trying to store the details from form to database using entity framework, i am using enum to store dropdown content.while submitting i am facing issue.
issue: System.InvalidOperationException: 'The entity type socialwebtable is not part of the model for the current context.'
[HttpPost]
public ActionResult register(socialwebtable c1)
{
socialwebsiteEntities db = new socialwebsiteEntities();
//data1 is a table name
socialwebtable data23 = new socialwebtable();
data23.name = c1.name;
data23.bloodgroup = c1.bloodgroup;
data23.city = c1.city;
data23.phonenumber = c1.phonenumber;
db.socialwebtables.Add(data23);
// db.socialwebtables.InsertOnSubmit(data23);
db.SaveChanges();
return View();
}
View:
<div class="form-group">
#Html.LabelFor(model => model.bloodgroup, htmlAttributes: new {
#class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EnumDropDownListFor(
x => x.bloodgroup,
"Select My Type",
new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.bloodgroup, "", new {
#class = "text-danger" })
</div>
</div>
Model:
public enum enum1
{
[Display(Name = "O+")]
O,
[Display(Name = "A+")]
B,
[Display(Name = "B+")]
A,
[Display(Name = "AB+")]
AB,
[Display(Name = "O-")]
O1,
[Display(Name = "A-")]
B1,
[Display(Name = "B-")]
A1,
[Display(Name = "AB-")]
AB1,
}
public partial class socialwebtable
{
public int id { get; set; }
public string name { get; set; }
public enum1 bloodgroup { get; set; }
public string city { get; set; }
public decimal phonenumber { get; set; }
}
}
This error occurs if the table(s) are not created at startup. Please place below code in your custom DBContext class to address the issue.
protected void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Estate>().ToTable("socialwebtable");
}
Hope this helps you..
Related
I have the following table:
And the model for it:
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
public int Duration { get; set; }
public enum Ratings
{
G = 1,
PG = 2,
PG13 = 3,
R = 4
}
public virtual Ratings MaturityRating { get; set; }
public ICollection<Screening> Screenings { get; set; }
}
In my Screening model I want to reference one of the movies so I can add a Screening:
public class Screening
{
public int Id { get; set; }
public DateTime Date { get; set; }
public int Room { get; set; }
public int Seats { get; set; }
[ForeignKey("Movie")]
public virtual int MovieId { get; set; }
public virtual Movie Movie { get; set; }
}
The problem is, the scaffolded form displays the movies in the drop-down with their ids, and it should be with their titles:
How can I change that?
Create a List in the controller to populate the dropdown. It the ViewBag Object name matches the Model property name it will be used for the dropdown items.
View
#*DropDownList*#
<div class="form-group">
#Html.LabelFor(model => model.Movie, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Movie, null, "Please Select", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Movie, "", new { #class = "text-danger" })
</div>
</div>
Controller Action, include
ViewBag.Movie = db.Movies.GetAll().Select(x=> new SelectListItem() { Name = x.Name, Value x.Id});
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 use Scaffolding to create the first version of controllers in my MVC 5 projects, but I'm not able to create the relashionship between 2 entities and get the expected results.
public partial class Call
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Display(Name = "Criado em")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd-M-yyyy HH:mm}")]
public DateTime DateCreated { get; set; }
[Display(Name = "Alterado em")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd-M-yyyy HH:mm}")]
public DateTime DateModified { get; set; }
public int UserCreated_Id { get; set; }
[ForeignKey("UserCreated_Id")]
public ApplicationUser UserCreated { get; set; }
public int UserModified_Id { get; set; }
[ForeignKey("UserModified_Id")]
public ApplicationUser UserModified { get; set; }
[Required(ErrorMessage = "Campo obrigatório")]
[MaxLength(256, ErrorMessage = "Não pode ter mais que 256 caracteres")]
[Display(Name = "Assunto")]
public string Subject { get; set; }
[Display(Name = "Descrição")]
public string Description { get; set; }
[Display(Name = "Data e Hora de início")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd-M-yyyy HH:mm}")]
public DateTime DateToCall { get; set; }
public int CallType_Id { get; set; }
[ForeignKey("CallType_Id")]
public CallType CallType { get; set; }
}
And Call Type
[Table("CallTypes")]
public partial class CallType
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Display(Name = "Nome")]
public string Name { get; set; }
}
But the Call Create and Edit Views are not creating the Dropdownlist with the Call Types, why?
EDIT:
For the UserCreated I get the dropdownlist correctly:
View:
<div class="form-group">
#Html.LabelFor(model => model.UserCreated_Id, "UserCreated_Id", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("UserCreated_Id", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.UserCreated_Id, "", new { #class = "text-danger" })
</div>
</div>
Controller:
public virtual ActionResult Create()
{
ViewBag.UserCreated_Id = new SelectList(db.ApplicationUsers, "Id", "Email");
return View();
}
But for the CallType I don't get any code.
EDIT2:
I found a solution for the problem, I would like to know if it's the way:
[Table("CallTypes")]
public partial class CallType
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Display(Name = "Nome")]
public string Name { get; set; }
public virtual ICollection<Call> Calls { get; set; } // <--- Add the relation with the Call Entity
}
Now I get the code correctly:
// GET: Call/Create
public virtual ActionResult Create()
{
ViewBag.CallType_Id = new SelectList(db.CallTypes, "Id", "Name");
ViewBag.UserCreated_Id = new SelectList(db.ApplicationUsers, "Id", "Email");
ViewBag.UserModified_Id = new SelectList(db.ApplicationUsers, "Id", "Email");
return View();
}
And the View:
<div class="form-group">
#Html.LabelFor(model => model.CallType_Id, "CallType_Id", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("CallType_Id", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.CallType_Id, "", new { #class = "text-danger" })
</div>
</div>
I want to have a dropdown in my view, but that dropdown should have categories loaded from database.
I am using Entity Framework Code First Approach in MVC 5.
Here is my Model:
public class CreateProductModel
{
[Required]
public string Name { get; set; }
[Required]
public int CategoryID { get; set; }
public SelectList Categories { get; set; }
[MaxLength]
public double Price { get; set; }
public string Description { get; set; }
}
Controller:
public ActionResult Index()
{
var model = new ProductModel();
model.CreateProductModel.Categories = new SelectList(_db.Categories, "CategoryID", "Name", 1);
return View(model);
}
View:
<div class="form-group">
#Html.LabelFor(model => model.CreateProductModel.CategoryID, new { #class = "col-lg-2 control-label" })
<div class="col-lg-10">
#Html.DropDownListFor(model => model.CreateProductModel.CategoryID, new SelectList(Model.CreateProductModel.Categories, "CategoryID", "Name", 1), "Please Select Category");
</div>
</div>
I am getting this error:
Initialize CreateProductModel property:
var model = new ProductModel();
model.CreateProductModel = new CreateProductModel();
model.CreateProductModel.Categories = new SelectList(_db.Categories, "CategoryID", "Name", 1);
My entities:
public class Meal
{
[HiddenInput(DisplayValue = false)]
public int Id { get; set; }
[Required(ErrorMessage = "Proszę podać nazwę posiłku")]
public string Name { get; set; }
[Required(ErrorMessage = "Proszę podać ilość białka")]
[Range(0.00, double.MaxValue, ErrorMessage = "Proszę podać dodatnią ilość.")]
public double Protein { get; set; }
[Required(ErrorMessage = "Proszę podać ilość węglowodanów")]
[Range(0.00, double.MaxValue, ErrorMessage = "Proszę podać dodatnią ilość.")]
public double Carbohydrates { get; set; }
[Required(ErrorMessage = "Proszę podać ilość tłuszczy")]
[Range(0.00, double.MaxValue, ErrorMessage = "Proszę podać dodatnią ilość.")]
public double Fat { get; set; }
[Required(ErrorMessage = "Proszę podać ilość kalorii")]
[Range(0.00, double.MaxValue, ErrorMessage = "Proszę podać dodatnią ilość.")]
public double Calories { get; set; }
}
public class EatenMeal
{
public int Id { get; set; }
public virtual Meal Meal { get; set; }
public virtual MealType MealType { get; set; }
public double Serving { get; set; }
public string Username { get; set; }
public DateTime Date { get; set; }
}
public class MealType
{
public int Id { get; set; }
public string Name { get; set; }
}
In MealController's view MealList which displays meals from datebase. And there is a button "Add" which refers to action AddEatenMeal in EatenMealController.
public ActionResult AddEatenMeal(int id)
{
var meal = mealRepository.GetMeal(id);
EatenMeal eatenMeal = new EatenMeal() { Meal = meal, Username = User.Identity.Name };
return View(eatenMeal);
}
[HttpPost]
public ActionResult AddEatenMeal(EatenMeal eatenMeal)
{
if(ModelState.IsValid)
{
eatenMealRepository.AddEatenMeal(eatenMeal);
RedirectToAction("Index", "Home");
}
return RedirectToAction("Index", "Home");
}
I am creating there object EatenMeal and partially initializing this object. Then I am passing this object to View to further initializing.
#model Domain.Entities.EatenMeal
#{
ViewBag.Title = "Dodawanie posiłku do dziennika";
}
#using (Html.BeginForm("AddEatenMeal","EatenMeal", FormMethod.Post, new {#class = "form"}))
{
#Html.HiddenFor(x => x.Meal.Name)
#Html.HiddenFor(x => x.Username)
#Html.HiddenFor(x => x.Meal.Calories)
#Html.HiddenFor(x => x.Meal.Carbohydrates)
#Html.HiddenFor(x => x.Meal.Fat)
#Html.HiddenFor(x => x..Meal.Protein)
#Html.HiddenFor(x => x.Meal.Id)
#Html.HiddenFor(x=>x.Username)
<div class="form-group">
#Html.Label("Nazwa posiłku")
#Html.Label(Model.Meal.Name, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.Label("Porcja (g)")
#Html.TextBoxFor(x => x.Serving, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.Label("Typ posiłku")
#Html.DropDownListFor(x=>x.MealType)????
</div>
<div class="form-group">
#Html.Label("Data spożycia")
#Html.TextBoxFor(x => x.Date, new { #class = "form-control", #id="date-eaten", #Value=DateTime.Today.ToShortDateString()})
</div>
<input type="submit" class="btn btn-info" value="Dodaj" />
}
Now I have a question. Is it correct to hiding fields? I don't know how I can save data from first controller to second in other way.
And is a second question. How I can make DropDownListFor for property MealTye in EatenMeal?
Rather than sending and receiving a whole lot of unused data across the wire and opening yourself to over posting attack, create a view model that represents what you want to display and edit. See What is a view model in MVC?
View model
public class EatenMealVM
{
public int MealID { get; set; }
[Display(Name="Nazwa posiłku")]
public string MealName { get; set; }
[Display(Name = "Typ posiłku")]
[Required(ErrorMessage = "Please select a meal")]
public int? MealTypeID { get; set; }
[Display(Name = "Porcja (g)")]
public double Serving { get; set; } // is this really double?
[Display(Name = "Data spożycia")]
[DataType(DataType.Date)]
public DateTime Date { get; set; }
public SelectList MealTypeList { get; set; }
}
Controller
public ActionResult AddEatenMeal(int id)
{
var meal = mealRepository.GetMeal(id);
var mealTypes = // get the list of meal types from the database
EatenMealVM model = new EatenMealVM()
{
MealID = meal.Id,
MealName = meal.Name,
MealTypeList = new SelectList(mealTypes, "ID", "Name")
};
return View(model);
}
View
#model EatenMealVM
....
#using (Html.BeginForm())
{
#Html.HiddenFor(m => m.MealID)
#Html.DisplayNameFor(m => m.MealName)
#Html.DisplayFor(m => m.MealName)
#Html.LabelFor(m => m.MealTypeID)
#Html.DropDownListFor(m => m.MealTypeID, Model.MealTypeList, "--Please select--")
#Html.ValidationMessageFor(m => m.MealTypeID)
#Html.LabelFor(m => m.Serving)
#Html.TextBoxFor(m => m.Serving, new { #class = "form-control")
#Html.ValidationMessageFor(m => m.Serving)
#Html.LabelFor(m => m.Date)
#Html.TextBoxFor(m => m.Date)
#Html.ValidationMessageFor(m => m.Date, new { #class = "form-control" })
<input type="submit" class="btn btn-info" value="Dodaj" />
}
Post method
[HttpPost]
public ActionResult AddEatenMeal(EatenMealVM model)
{
if (!ModelState.IsValid)
{
var mealTypes = // get the list of meal types from the database
model.MealTypeList = new SelectList(mealTypes, "ID", "Name");
return View(model);
}
// Initialize new EatenMeal class
// Map properties from view model (including setting user name)
// Save and redirect
}
Note also the use of [Display] attribute and #Html.LabelFor(). Currently you not creating 'real' labels (they are not associated with the corresponding control)