MVC Add Record to Database - c#

Could somebody please help me add a record to a database?
I have created some base elements, but I'm struggling with the code for the AccountController. I would like for a user to enter the values for Stone and Pound via the form, and on posting add a record to the Weight table along with current Id of the logged in user and current date. Here is what I have so far.
AddWeightModel
public class AddWeightModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Stone")]
public Nullable<short> Stone { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Pound")]
public Nullable<short> Pound { get; set; }
}
WebApplication1Entities
public partial class WebApplication1Entities : DbContext
{
public WebApplication1Entities()
: base("name=WebApplication1Entities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Weight> Weights { get; set; }
}
Weight
public partial class Weight
{
public int Id { get; set; }
public string UserId { get; set; }
public Nullable<short> Stone { get; set; }
public Nullable<short> Pound { get; set; }
public Nullable<System.DateTime> Date { get; set; }
}
_UpdatePartial
#using Microsoft.AspNet.Identity
#model WebApplication1.Models.AddWeightModel
#using (Html.BeginForm("RecordCard", "Account", FormMethod.Post, new { #id = "contact-form", role = "form" }))
{
<fieldset>
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div class="form-div-5">
<label>
#Html.TextBoxFor(m => m.Stone, new { #placeholder = "Stone *", #type = "text" })
</label>
</div>
<div class="form-div-5">
<label>
#Html.TextBoxFor(m => m.Pound, new { #placeholder = "Pound *", #type = "text" })
</label>
</div>
<div class="button-wrapper">
<input type="submit" value="Submit" class="button" />
</div>
</fieldset>
}
AccountController
public ActionResult RecordCard()
{
var UserId = User.Identity.GetUserId();
var weightModel = from m in db.Weights where m.UserId == UserId select m;
return View(weightModel);
}
public ActionResult RecordCard(Weight Model)
{
if (ModelState.IsValid)
{
using (WebApplication1 db = new WebApplication1())
{
Weight weight = new Weight();
weight.UserId = User.Identity.GetUserId();
weight.Stone = Model.Stone;
weight.Pound = Model.Pound;
weight.Date = System.DateTime.Now;
db.Weights.Add(Model);
db.SaveChanges();
}
}
return View(Model);
}
Please note that _UpdatePartial is called from RecordCard like so:
#Html.Partial("_WeightPartial", new AddWeightModel())
And also RecordCard receives an IEnumerable list:
#model IEnumerable<Shedtember.Models.Weight>
I need a list of records from the Weight table depending on logged in user to generate a graph.
Just want to add the record and return to the RecordCard page.
Please help, I'm going insane!

I'll try to break this down.
Your compile error at:
db.Weights.Add(Model);
occurs because db.Weights.Add() expects a Weight. You are passing it your model of type AddWeightModel. You need to convert your model back to a Weight:
Weight weight = new Weight();
weight.UserId = //get your current user's ID
weight.Stone = Model.Stone;
weight.Pount = Model.Pound;
weight.Date = DateTime.UTCNow;
db.Weights.Add(weight);
Next, your method
public ActionResult RecordCard(AddWeightModel Model)
needs to be a POST, so decorate it:
[HttpPost]
public ActionResult RecordCard(AddWeightModel Model)
Now in your view you are (very correctly) adding a #Html.AntiForgeryToken(). It doesn't help you unless you validate it:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RecordCard(AddWeightModel Model)
Step back, and examine what types you are working with.

Related

ModelState.IsValid keeps coming back as false?

SO I have a view where a member enters the PIN associated with them to clock in
#model Models.Member
#{
Layout = "~/Views/Shared/_HomeLayout.cshtml";
}
<h1 style="margin-top: 0px;">Club Members Login Below!</h1> #*add this to the style for better ipad title -> "text-align: center;"*#
</br>
#using (Html.BeginForm("ClubHours", "Login", FormMethod.Post))
{
#Html.LabelFor(c => c.PIN)
#Html.TextBoxFor(c => c.PIN)<br />
#Html.ValidationMessageFor(c => c.PIN)<br />
<input type="submit" name="submit" value="ClockIn" />
<input type="submit" name="submit" value="ClockOut" />
}
which interacts with this action result:
[HttpPost]
public ActionResult ClubHours(string submit, Member member)//member clocking in
{
if (submit.Equals("ClockIn"))
{
if (!ModelState.IsValid) //validating events fields
{
return View("UserLogin");
}
else
{
var mem = _context.Members.SingleOrDefault(c => c.PIN == member.PIN);
var hours = new MemberClubHours();
hours.ClockIn = DateTime.Now;
mem.Hours.Add(hours);
_context.SaveChanges();
return View("ClockIn");
}
}
else if (submit.Equals("ClockOut"))
{
if (!ModelState.IsValid) //validating events fields
{
return View("UserLogin");
}
else
{
var mem = _context.Members.SingleOrDefault(c => c.PIN == member.PIN);
var hours = new MemberClubHours();
hours.ClockOut = DateTime.Now;
mem.Hours.Add(hours);
_context.SaveChanges();
return View("ClockOut");
}
}
else
{
return View("UserLogin","Login");
}
}
and lastly here is that Member class
public class Member
{
public int Id { get; set; }
[Required]
[MaxLength(4, ErrorMessage = "PIN must be 4 numbers long"), MinLength(4, ErrorMessage = "PIN must be 4 numbers long")]
public string PIN { get; set; }
[Required]
[Display(Name ="First Name")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Display(Name = "Date of Birth")]
public DateTime? Birthdate { get; set; }
public virtual ICollection<MemberClubHours> Hours { get; } = new HashSet<MemberClubHours>();
}
and the memberclubhours class
public class MemberClubHours
{
public int Id { get; set; }
public DateTime? ClockIn { get; set; }
public DateTime? ClockOut { get; set; }
[Required]
public Member Member { get; set; }
}
The code works correctly and will track the hours of a member, however I'm trying to implement validation, but even if I enter a PIN that is associated with a member in the system, it comes back as not valid? any help would be appreciated!
You're validating the model sent from the frontend. Not to the database, are you sure the model is populated according to your Data Annotations in the model?
Check out ModelState it's asp.net core 3.1 but still relevant
Member model is coming out as invalid because the member Model requires the Id, PIN, FirstName, LastName fields.
You can't validate this class with ModelState.IsValid because it will check all the properties-- and it looks like you're only passing the PIN property.
If you don't want to make a viewModel for it, you could just include those properties as hidden inputfields;
#using (Html.BeginForm("ClubHours", "Login", FormMethod.Post))
{
#Html.HiddenFor(c=>c.Id)
#Html.HiddenFor(c=>c.FirstName)
#Html.HiddenFor(c=>c.LastName)
#Html.LabelFor(c => c.PIN)
#Html.TextBoxFor(c => c.PIN)<br />
#Html.ValidationMessageFor(c => c.PIN)<br />
<input type="submit" name="submit" value="ClockIn" />
<input type="submit" name="submit" value="ClockOut" />
}

Unable to add the value from dropdownlist to database

I created a form to store information about the customers and his membership type. For that I am using the drop down list to hold values for membership types. But on submitting the form, the value(Id) for membership type isnt added to database
//Model Membership Types
public int Id { get; set; }
public string Name { get; set; }
//ViewModel NewCustomerviewModel
public IEnumerable<MembershipTypes> MembershipTypes { get; set; }
public Customers Customers{ get; set; }
//Controler CustomerController
public IActionResult Index()
{
var customers = _context.Customers.Include(c => c.MembershipTypes).ToList();
return View(customers);
}
[HttpPost]// Create is the aciton for Submit Button
public IActionResult Create(Customers customers)
{
_context.Customers.Add(customers);
_context.SaveChanges();
return RedirectToAction("Index", "Customers");
}
//View Model
#model Wes.ViewModels.NewCustomerviewModel;
#Html.DropDownListFor(m => m.Customers.MembershipTypes, new SelectList(Model.MembershipTypes, "Id", "Name"),"Select Membership Type", new { #class = "form-control" })
When the Form is Submitted, it should add all the values to the database including the value of Drop Down List Membership Types
You could try doing it this way:
//model
public int Id { get; set; }
public string Name { get; set; }
public enum MembershipTypes
{
Type1,
Type2,
Type3
}
public MembershipTypes _membershipTypes {get; set; }
//controller
[HttpPost]
public IActionResult Create([Bind("Id","Name","_membershipTypes")] Customers customers)
{
if (ModelState.IsValid)
{
_context.Add(customers);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
Return View(customers);
}
//view
<div class="row">
<div class="col-md-6">
<form asp-action="Create">
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
#Html.DropDownList("_membershipTypes",
new SelectList(Enum.GetValues(typeof(MembershipTypes))),
"Select membership type",
new { #class = "form-control" })
</div>
<input type="submit" value="Submit!" />
</form>
</div>
</div>
You need to show more about the relationships(one-to-one,one-to-many) of your models.
The parameters of your post action need to correspond with the model of your view,use NewCustomerviewModel instead of Customers.
The dropdownlist shows the type of name and pass id as value to action, so your asp-for of dropdown list needs to be set for an id or id list.
Refer to my demo which pass id list of MembershipTypes to action using multiple select.
1.My ViewModel NewCustomerviewModel,
public class MembershipTypes
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
public class NewCustomerviewModel
{
public int[] SelectMembershipTypesId { get; set; }
public Customers Customers { get; set; }
}
public class Customers
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<MembershipTypes> MembershipTypes { get; set; }
}
2.Create GET action
public IActionResult Create()
{
var model = new NewCustomerviewModel()
{
Customers = new Customers()
{
MembershipTypes = _context.MembershipTypes.ToList()
},
};
return View(model);
}
3.Create POST action
[HttpPost]
public async Task<IActionResult> Create(NewCustomerviewModel viewmodel)
{
if (ModelState.IsValid)
{
viewmodel.Customers.MembershipTypes= _context.MembershipTypes
.Where(m =>viewmodel.SelectMembershipTypesId.Contains(m.Id))
.ToList();
_context.Add(viewmodel.Customers);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(viewmodel);
}
4. Create View
#Html.DropDownListFor(m => m.SelectMembershipTypesId,
new SelectList(Model.Customers.MembershipTypes, "Id", "Name"), "Select Membership Type",
new { #class = "form-control", #multiple = "multiple" })

Null Reference Exception when i use navigation property in model class

I try to add new entity in database in controller action.
This is my model class
public class Product
{
public int ProductID { get; set; }
[Required(ErrorMessage = "Please enter product name")]
public string Name { get; set; }
[Required(ErrorMessage = "Please enter product model")]
public string Model { get; set; }
[Required(ErrorMessage = "Please enter product serial")]
public string Serial { get; set; }
[Required(ErrorMessage = "Please choose dealer")]
public int DealerID { get; set; }
[Required]
public Guid ClientID { get; set; }
[Required(ErrorMessage = "Please choose employee")]
public Guid EmployeeID { get; set; }
public virtual Dealer Dealer { get; set; }
public virtual Client Client { get; set; }
public virtual Employee Employee { get; set; }
[DisplayName("Commercial use")]
public bool UseType { get; set; }
}
This is actions for creating new product in database
public ViewResult Create()
{
PopulateDropDownLists();
var model = new Product();
return View(model);
}
[HttpPost]
public ActionResult Create(Product model)
{
try
{
if (ModelState.IsValid)
{
_repo.GetRepository<Product>().Add(model);
_repo.Save();
TempData["message"] = "Product was successfully created";
return RedirectToAction("List");
}
}
catch (DataException)
{
TempData["error"] =
"Unable to save changes. Try again, and if the problem persists, see your system administrator.";
return View("Error");
}
PopulateDropDownLists();
return View("Create");
}
CreateView has appropriate model type (Product type in this case). Code below
#using System.Web.Mvc.Html
#model STIHL.WebUI.Models.Product
#using (Html.BeginForm())
{
#Html.EditorFor(m => m.Name)
#Html.EditorFor(m => m.Model)
#Html.EditorFor(m => m.Serial)
<div class="form-group">
#Html.LabelFor(m => m.DealerID, "Dealer")
#Html.DropDownListFor(m => m.DealerID, new SelectList((IEnumerable)TempData["Dealers"],"DealerID", "DealerNumber"), string.Empty, new {#class = "form-control"})
#Html.ValidationMessageFor(m => m.DealerID, null, new {#class = "help-block"})
</div>
<div class="form-group">
#Html.LabelFor(m => m.EmployeeID, "Employee",new {#class = "control-label"})
#Html.DropDownListFor(m => m.EmployeeID, new SelectList((IEnumerable)TempData["Employees"],"EmployeeID", "FullName"),string.Empty, new {#class="form-control"})
#Html.ValidationMessageFor(m => m.EmployeeID, null, new {#class = "help-block"})
</div>
<div class ="ok-cancel-group">
<input class="btn btn-primary" type="submit" value="Create" />
#Html.ActionLink("Cancel", "List","Product",new {#class = "btn btn-primary"})
</div>
}
i always get null reference instead model in [HttpPost] action, but if i use ViewModel instead Model everything is ok (ViewModel code below)
public class ProductViewModel
{
public Product Product { get; set; }
}
I think it cause model class has virtual properties, but anyway i don't understand why it's ok when i use ViewModel.
Can anyone answer me?
Thx in advance.
The virtual properties won't change the outcome. The issue is that the view is written to bind to the view model, therefore accepting the model isn't going to work. If you want to use the model; then bind the view to the model.

Model binding with a sub model

I have a model as follows:
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
public virtual Department Department { get; set; }
}
Here is the controller action:
[AllowAnonymous]
public ActionResult Register(int departmentId)
{
using (var db = new DataContext())
{
var department = db.Departments.Find(departmentId);
var registerModel = new RegisterModel {Department = department};
return View(registerModel);
}
}
I have departments list page. such as Foo, then I want to ass user to Foo.
1 . Foo - add user
then I have a register View.
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
#Html.HiddenFor(x => x.Department.Id)
<fieldset>
<legend>Registration Form</legend>
<ol>
<li>
#Html.LabelFor(m => m.UserName)
#Html.TextBoxFor(m => m.UserName)
</li>
<li>
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password)
</li>
</ol>
<input type="submit" value="Register" />
</fieldset>
}
Now my question is how can i bind the Department to Model? with department Id? or department object?
I have access to Department, which i populate from database, then I need to pass it to View. but how do i pass it? so upon register submit, I can have access to it or id of it?
You should add a DepartmentId and DepartmentsList to your RegisterModel:
public class RegisterModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
public int DepartmentId { get; set; }
// You don't really need this.
//public virtual Department Department { get; set; }
// Create this list in your controller before sending it to the view.
public IEnumerable<SelectListItem> DepartmentsList { get; set; }
}
Populate the DepartmentsList in your Register action:
public ActionResult Register()
{
using (var db = new DataContext())
{
var departments = db.Departments.Select(department => new SelectListItem
{
Value = department.Id,
Text = department.Name
}).ToList();
var registerModel = new RegisterModel { DepartmentsList = departments };
return View(registerModel);
}
}
Then you create a drop down list in your view:
<li>
#Html.LabelFor(m => m.Department)
#Html.DropDownListFor(m => m.DepartmentId, Model.DepartmentsList)
</li>
Then in your HttpPost action you accept a RegisterModel:
[HttpPost]
public ActionResult Register(RegisterModel registerModel)
{
using (var db = new DataContext())
{
// Note: this is just an example..
var user = new User
{
UserName = registerModel.UserName,
Password = registerModel.Password,
DepartmentId = registerModel.DepartmentId
}
db.Users.Add(user);
db.SaveChanges();
}
}

Get string from DropDownList

I have XML file which contains my data and I want from dropdownlist save choose string to this xml.
In my view I have this:
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>MatchXML</legend>
...
<div class="editor-label">
#Html.LabelFor(model => model.Team)
</div>
<div class="editor-field">
#Html.DropDownList("Team", (SelectList)ViewBag.Team, String.Empty)
#Html.ValidationMessageFor(model => model.Team)
</div>
...
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
In controller:
public ActionResult Pridat()
{
ViewBag.Team = new SelectList(repo.GetTeams(), "Name", "Name");
return View();
}
[HttpPost]
public ActionResult Pridat(MatchXML match, string Team)
{
if (ModelState.IsValid)
{
try
{
ViewBag.Team = new SelectList(repo.GetTeams(), "Name", "Name");
match.Team = repo.GetTeamByName(Team);
repo.AddMatch(match);
return RedirectToAction("Index");
}
catch (Exception ex)
{
//error msg for failed insert in XML file
ModelState.AddModelError("", "Error creating record. " + ex.Message);
}
}
return View(match);
}
Models looks:
public class MatchXML
{
public int MatchXMLID { get; set; }
public string Opponent { get; set; }
public DateTime MatchDate { get; set; }
public string Result { get; set; }
public Team Team { get; set; }
public int Round { get; set; }
}
public class Team
{
public int TeamID { get; set; }
public string Name { get; set; }
public virtual User Coach { get; set; }
public virtual ICollection<Player> Players { get; set; }
}
I was trying do some modification to do this but it is not working. I can do it with TeamID and saving ID but I want in xml save string (name of team). Thanks for help
Edit:
I updated show code of controller and view method.
You are binding the dropdown to the Team complex property (first argument of the DropDownList helper). This doesn't make sense. You can bind only to scalar values. I would also recommend you using the strongly typed version of the helper:
#Html.DropDownListFor(x => x.Team.TeamID, (SelectList)ViewBag.Team, String.Empty)
This way you will populate the TeamID property in the POST action with the selected value from the dropdown.
Also replace:
#Html.ValidationMessageFor(model => model.Team)
with:
#Html.ValidationMessageFor(model => model.Team.TeamID)

Categories

Resources