Case is an MVC 5 application
I have a class Team (sports team), that looks like this:
public class Team
{
public int Id { get; set; }
public string TeamName { get; set; }
public string Badge { get; set; }
public TeamColor? TeamColor { get; set; }
public League? League { get; set; }
public bool HasAlias { get; set; }
public bool IsAlias { get; set; }
public int? AliasId { get; set; }
public virtual Team AliasTeam { get; set; }
public virtual ICollection<Team> Aliases { get; set; }
}
An AliasTeam is a Team with just a TeamName an AliasId.
How do I go about adding a textbox for filing out the AliasTeamName if the user has clicked the HasAlias checkbox on the original team, and how do I loop through the textboxes in the controller in order to add them as Teams with an AliasId of the original team?
Controller action looks like this right now, where I can add a Team
public ActionResult CreateTeam(CreateTeamViewModel model)
{
if (ModelState.IsValid)
{
var team = new Team
{
TeamName = model.TeamName,
TeamColor = model.TeamColor,
League = model.League
};
db.Teams.Add(team);
db.SaveChanges();
return RedirectToAction("AddTeamImage", new {teamid = team.Id});
}
return View(model);
}
EDIT:
Solved it by adding following js:
$(document).ready(function() {
$("#HasAlias").change(function () {
if (this.checked) {
$(".textboxes").append('<div><input class="form-control text-box single-line" placeholder="enter aliasname" type="text" name="teams"/> <span class=" glyphicon glyphicon-plus-sign"></span> <span class=" glyphicon glyphicon-minus-sign"></span></div>');
} else {
$(".textboxes").empty();
}
});
$('.textboxes').on("click", ".add_field", function(e) {
e.preventDefault();
$(".textboxes").append('<div><input class="form-control text-box single-line" placeholder="enter aliasname" type="text" name="teams"/> <span class=" glyphicon glyphicon-plus-sign"></span> <span class=" glyphicon glyphicon-minus-sign"></span></div>');
});
$('.textboxes').on("click", ".remove_field", function (e) {
e.preventDefault(); $(this).parent('div').remove();
});
});
And then looping through array of teams in Action:
public ActionResult CreateTeam(CreateTeamViewModel model, string[] teams)
{
if (ModelState.IsValid)
{
var team = new Team
{
TeamName = model.TeamName,
TeamColor = model.TeamColor,
League = model.League,
HasAlias = model.HasAlias
};
db.Teams.Add(team);
db.SaveChanges();
foreach (var s in teams)
{
var t = new Team
{
TeamName = s,
AliasId = team.Id,
IsAlias = true
};
db.Teams.Add(t);
db.SaveChanges();
}
return RedirectToAction("Index");
}
return View(model);
}
I may have misunderstood the whole ViewModel paradigm then. I thought you where meant to create ViewModels, with only the information needed to create a result.
Related
My Question Model
public class Question
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
public string D { get; set; }
public int SubjectId { get; set; }
public virtual Subject Subject { get; set; }
public int AnswerId { get; set; }
public virtual Answer Answer { get; set; }
}
and this is my view.cshtml
#foreach (var item in Model)
{
<div>
#Html.DisplayFor(modelItem => item.Title)
<input type="radio" value="#Html.DisplayFor(modelItem => item.A)" id="A" name="#Html.DisplayFor(modelItem=> item.Id)" class="rb" />
#Html.DisplayFor(modelItem => item.A)
<input type="radio" value="#Html.DisplayFor(modelItem => item.B)" id="B" name="#Html.DisplayFor(modelItem=> item.Id)" class="rb" />
#Html.DisplayFor(modelItem => item.B)
<input type="radio" value="#Html.DisplayFor(modelItem => item.C)" id="C" name="#Html.DisplayFor(modelItem=> item.Id)" class="rb" />
#Html.DisplayFor(modelItem => item.C)
<input type="radio" value="#Html.DisplayFor(modelItem => item.D)" id="D" name="#Html.DisplayFor(modelItem=> item.Id)" class="rb" />
#Html.DisplayFor(modelItem => item.D)
</div>
}
So how can I can compare the user answer with my correct answer and then give a score and save it to the database?
and this is my table that should store the score:
public class StraintTest
{
public int Id { get; set; }
public string Name { get; set; }
public string LastName { get; set; }
public string FatherName { get; set; }
public int Cost { get; set; }
public string Contact { get; set; }
public int Grammar { get; set; }
public int Vocabulary { get; set; }
public int Reading { get; set; }
public int Listening { get; set; }
public int Writing { get; set; }
public int Speaking { get; set; }
public string Exam_Date { get; set; }
public int Score { get; set; }
public int ProgramId { get; set; }
public virtual Program Program { get; set; }
}
this is the StriantTest Service :
public int AddStraintTest(StraintTestViewModel test)
{
var newStriant = new StraintTest()
{
Name = test.Name,
LastName = test.LastName,
FatherName = test.FatherName,
Contact = test.Contact,
Cost = test.Cost,
Exam_Date = test.Exam_Date,
Grammar = test.Grammar,
Listening = test.Listening,
Speaking = test.Speaking,
Writing = test.Writing,
Reading = test.Reading,
ProgramId = test.ProgramId.HasValue ? test.ProgramId.Value:1,
Score = test.Score
};
_context.Add(newStriant);
_context.SaveChanges();
return newStriant.Id;
}
this is StrainTest Controller:
[HttpPost]
public IActionResult Create(StraintTestViewModel straintTest)
{
if (ModelState.IsValid)
{
int id = _istraintTest.AddStraintTest(straintTest);
if (id > 0)
{
return RedirectToAction(nameof(Create));
}
}
ViewBag.Program = new SelectList(_iprogram.GetProgram(), "Id", "Name");
return View();
}
this is my View, when the start exam button clicked, it should take the Id of this field and show the questions and after submitting the question the score field should update and show the score that the student got from exam.
and this is my setting score operation:
public IActionResult TakeExam(int straintTestId)
{
var data = _iquestion.ShowQuestion();
return View(data);
}
[HttpPost]
public IActionResult TakeExam(IEnumerable<Question> Questions, int straintTestId)
{
ExamCheck examCheck;
int score = 0;
if(Questions != null)
{
foreach(Question Q in Questions)
{
examCheck = new ExamCheck();
examCheck.StriantTestId = straintTestId;
examCheck.QuestionID = Q.Id;
examCheck.CorrectAnswer = Q.AnswerId;
if(Q.SelectAnswer != null)
{
examCheck.StudentAnswer = (int)Q.SelectAnswer;
}
else
{
examCheck.StudentAnswer = 0;
}
_context.ExamChecks.Add(examCheck);
_context.SaveChanges();
if(Q.SelectAnswer == Q.AnswerId)
{
score += 1;
}
}
}
StraintTest straintTest = new StraintTest();
straintTest.Id = straintTestId;
straintTest.Score = score;
_context.StraintTests.Add(straintTest);
_context.SaveChanges();
return View(straintTest);
}
when I click it shows the questions but it doesn't set score...!
it would really please if someone help me obviously !!!
I wrote simple test code for you. You can check this and implement yourself.
This is my question class :
public class Question
{
public string Tittle { get; set; }
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
public string D { get; set; }
public bool OptA { get; set; }
public bool OptB { get; set; }
public bool OptC { get; set; }
public bool OptD { get; set; }
}
and this is controller Get Action. I created random questions dont mind that.
public IActionResult test() {
List<Question> list = new List<Question>() {
new Question { Tittle = "Asadasadasa", A = "asasas", B = "basasasasas", C = "casadsdfadsad", D = "dasadsdsd" },
new Question { Tittle = "Asadasadasa", A = "asasas", B = "basasasasas", C = "casadsdfadsad", D = "dasadsdsd" },
new Question { Tittle = "Asadasadasa", A = "asasas", B = "basasasasas", C = "casadsdfadsad", D = "dasadsdsd" },
new Question { Tittle = "Asadasadasa", A = "asasas", B = "basasasasas", C = "casadsdfadsad", D = "dasadsdsd" },
new Question { Tittle = "Asadasadasa", A = "asasas", B = "basasasasas", C = "casadsdfadsad", D = "dasadsdsd" },
new Question { Tittle = "Asadasadasa", A = "asasas", B = "basasasasas", C = "casadsdfadsad", D = "dasadsdsd" },
};
return View(list);
}
after that this is my view page. I used checkbox for input this allow multi slect but you can use option group for that.I forget to add options text but dont mind that either :).
#model List<EpsilonMFALanguage.Help.Question>
<div class="col-md-12">
<div class="panel">
<div class="panel-body">
<form action="#Url.Action("test","Home")" method="post" class="form-horizontal">
#for (int i=0;i<Model.Count;i++)
{
<div class="form-group">
<input type="hidden" asp-for="#Model[i].Tittle" />
<label id="lbl_#i" class="col-md-12" asp-for="#i">#Model[i].Tittle</label>
<div class="col-md-6">
<input type="checkbox" id="#i" asp-for="#Model[i].OptA" />
</div>
<div class="col-md-6">
<input type="checkbox" id="#i" asp-for="#Model[i].OptB" />
</div>
<div class="col-md-6">
<input type="checkbox" id="#i" asp-for="#Model[i].OptC" />
</div>
<div class="col-md-6">
<input type="checkbox" id="#i" asp-for="#Model[i].OptD" />
</div>
</div>
}
<button type="submit">Submit</button>
</form>
</div>
</div>
</div>
this way when user solve the test and click submit it goes to my test Post action.
[HttpPost]
public IActionResult test(List<Question> list) {
return Json("");
}
when I debug the post action this is the result. You can see wihch option was selected.
This is my first ask. I have 2 models for 1 view. I built the code but i have a problem. data comes null from view to controller.
Models:
Mom model:
public class BildirimOlusturViewModel
{
public BildirimOlusturModel bildirimOlusturModel { get; set; }
public TagBoxViewModel tagBoxViewModel { get; set; }
}
Child models:
public class BildirimOlusturModel
{
[Required(ErrorMessage = "Lütfen bildirim tipi seçiniz")]
public string BildirimTipi { get; set; }
[Required(ErrorMessage = "Lütfen alıcı tipi seçiniz")]
public string AliciTipi { get; set; }
[Required(ErrorMessage = "Lütfen alıcı seçiniz")]
public string Alicilar { get; set; }
[Required(ErrorMessage = "Lütfen bir başlık giriniz")]
public string Baslik { get; set; }
[Required(ErrorMessage = "Mesaj boş olamaz")]
public string Mesaj { get; set; }
}
public class TagBoxViewModel
{
public List<string> Items { get; set; }
}
View:
#model xyz.Web.Notifications.Models.BildirimOlusturViewModel
<form method="post" asp-controller="Bildirim" asp-action="BildirimOlustur">
...
#(Html.DevExtreme().SelectBoxFor(s => s.bildirimOlusturModel.AliciTipi)
.Placeholder("Alıcı Tipi...")
.DataSource(new List<SelectListItem> {
new SelectListItem
{
Text = "Personel",
Value = "personel".ToString()
},
new SelectListItem
{
Text = "Müşteri",
Value = "musteri".ToString()
}})
.ValueExpr("Value").DisplayExpr("Text")
.OnValueChanged("alicitipi_changed")
.ID("slcAliciTipi")
)
</div>
<div class="col-md-8">
#(Html.DevExtreme().TagBoxFor(x => x.bildirimOlusturModel.Alicilar)
.Items(Model.tagBoxViewModel.Items)
.SearchEnabled(true)
.Placeholder("Alıcı...")
.ID("TagBoxAlici")
)
#(Html.DevExtreme().TextBoxFor(x => x.bildirimOlusturModel.Baslik)
.Placeholder("Başlık...")
)
<input type="text" id="Mesaj" asp-for="bildirimOlusturModel.Mesaj" name="bildirimOlusturModel.Mesaj" id="bildirimOlusturModel.Mesaj"/>
#(Html.DevExtreme().Button()
.Text("Submit")
.Type(ButtonType.Default)
.StylingMode(ButtonStylingMode.Contained)
.Width(120)
.UseSubmitBehavior(true)
)
</form>
Controller:
[HttpPost]
public IActionResult BildirimOlustur(BildirimOlusturModel model)
{
string sAlicilar = model.Alicilar;
string sAliciTipi = model.AliciTipi;
string sBaslik = model.Baslik;
string sBildirimTipi = model.BildirimTipi;
string sMesaj = model.Mesaj;
}
Submit button sends me inside the post method but not sends the model. My variables coming null. Thank you for help.
Try adding a [FromBody] attribute before your argument.
public IActionResult BildirimOlustur([Frombody] BildirimOlusturModel model)
I solved the problem. controller was waiting for the wrong parameter.
[HttpPost]
public IActionResult BildirimOlustur(BildirimOlusturViewModel model)
{
BildirimOlusturModel mdl = new BildirimOlusturModel();
mdl = model.bildirimOlusturModel;
string sAlicilar = mdl.Alicilar;
}
I am trying to create radio button groups that correspond to a "registration". Each registration can have multiple "payment options" I need to be able to select an option for each registration then pass those values to the controller. I have looked at the solutions and the comments from yesterday and this is my updated code but its still not working.
<div id="regsAndFees">
<ol>
#foreach (var reg in Model.PendingRegistrations.Cart)
{
<li>
<label>#reg.Description - </label> <span><label>#reg.Fee.ToString("C")</label></span>
<ul style="list-style:none;">
#foreach (var fee in reg.AdditionalFees)
{
<li>
<label>#fee.AdditionalFee.ToString("C")</label>
<span>#fee.Description</span>
</li>
}
</ul>
#for (int i = 0; i < Model.PaymentOptions.RegistrationPaymentTypes.Count; i++)
{
#Html.RadioButtonFor(m => m.PaymentOptions.RegistrationPaymentTypes[i], #Model.PendingRegistrations.PaymentOptions.RegistrationPaymentTypes)
#Html.LabelFor(m => m.PaymentOptions.RegistrationPaymentTypes[i], #Model.PendingRegistrations.PaymentOptions.RegistrationPaymentTypes)
<br />
}
</li>
}
</ol>
</div
Models
public class ViewModelPendingRegistrations
{
public ViewModelPendingRegistrations()
{
PendingRegistrations = new List<ViewModelPendingRegistration>();
Errors = new List<string>();
this.TempCart = new List<SalesTax.TempCart>();
this.Cart = new List<Registrations.Cart>();
this.PaymentOptions = new ViewModelPaymentOptions();
}
public ViewModelPaymentOptions PaymentOptions { get; set; }
public List<Domain.ViewModel.Registrations.Cart> Cart { get; set; }
public List<ViewModelPendingRegistration> PendingRegistrations { get; set; }
public bool IsBusinessAdmin { get; set; }
public bool HasBusinessRegistrations { get; set; }
public bool HasIndividualRegistrations { get; set; }
public List<string> Errors { get; set; }
here is Model.PendingRegistrations.Cart
public class Cart
{
public Cart()
{
this.AdditionalFees = new List<ViewModelAdditionalFee>();
this.PaymentOptions = new ViewModelPaymentOptions();
}
public List<ViewModelRegistrationRequirement> Requirements { get; set; }
public ViewModelPaymentOptions PaymentOptions { get; set; }
public int SelectedPaymentOption { get; set; }
public string EntityName { get; set; }
}
this is my controller method
public ActionResult PaymentOptions(Domain.ViewModel.PaymentModel model)
{
var pendingRegistrations = new BusinessLayer.Registration().GetPendingRegistrations(false, false, AppUser.UserId, true);
var paymentdetails = new BusinessLayer.PaymentType().GetAllActive();
var regs = pendingRegistrations.Cart;
model.PendingRegistrations.Cart = regs;
var payments = new BusinessLayer.RegistrationTypePaymentType().GetAll();
foreach (var pendingReg in regs)
{
model.PaymentOptions.RegistrationPaymentTypes = payments.Where(x => x.RegistrationTypeID == pendingReg.RegistrationTypeID).ToList();
foreach (var pmt in pendingReg.PaymentOptions.RegistrationPaymentTypes)
{
var pmtnames = paymentdetails.Where(x => x.PaymentTypeID == pmt.PaymentTypeID).FirstOrDefault();
pmt.PaymentName = pmtnames.Name;
}
}
return View(model);
}
and lastly this is what the view looks like with this code
I'm having trouble finding a tutorial / video that shows how to implement Cascading DropDownList from a Database using EntityFramework. I'm using ASP.NET MVC Core, EntityFramework Core with C#.
As of now, I'm able to retrieve the data from my database to my 3 DropDownList fine.
What I would like to be able to accomplish is to have the user select a State first which would then display all Cities related to that State. Then after user has selected a City it would display the Zip Code(s) related to the City.
Any help would be greatly appreciated.
Models
public class Customer
{
public int CustomerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int StateId { get; set; }
public int CityId { get; set; }
public int ZipId { get; set; }
public State State { get; set; }
public City City { get; set; }
public Zip Zip { get; set; }
}
public class State
{
public int StateId { get; set; }
public string Abbr { get; set; }
public List<Customer> Customers { get; set; }
}
public class City
{
public int CityId { get; set; }
public string Name { get; set; }
public int StateId { get; set; }
public State State { get; set; }
public List<Customer> Customers { get; set; }
}
public class Zip
{
public int ZipId { get; set; }
public string PostalCode { get; set; }
public int CityId { get; set; }
public City City { get; set; }
public List<Customer> Customers { get; set; }
}
ViewModels
public class CustomerFormVM
{
public int CustomerId { get; set; }
[Display(Name = "First Name")]
[StringLength(50)]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
[StringLength(50)]
public string LastName { get; set; }
[Required(ErrorMessage = "Select State")]
[Display(Name = "State")]
public int StateId { get; set; }
//public IEnumerable<State> States { get; set; }
public IEnumerable<SelectListItem> States { get; set; }
[Required(ErrorMessage = "Select City")]
[Display(Name = "City")]
public int CityId { get; set; }
//public IEnumerable<City> Citys { get; set; }
public IEnumerable<SelectListItem> Citys { get; set; }
[Required(ErrorMessage = "Select Zip")]
[Display(Name = "Zip")]
public int ZipId { get; set; }
//public IEnumerable<Zip> Zips { get; set; }
public IEnumerable<SelectListItem> Zips { get; set; }
}
CustomerController
public class CustomerController : Controller
{
private MultiDbContext db;
public CustomerController(MultiDbContext context)
{
db = context;
}
// GET: /<controller>/
public IActionResult Index()
{
return View(db.Customers.ToList());
}
public IActionResult getCititesFromDatabaseByStateId(int id)
{
return View(db.Citys.Where(c => c.StateId == id).ToList());
}
public IActionResult getCities(int id)
{
var cities = new List<City>();
cities = getCititesFromDatabaseByStateId(id); //call repository
return Json(cities);
}
public ActionResult Create()
{
var states = db.States.ToList();
var citys = db.Citys.ToList();
var zips = db.Zips.ToList();
var viewModel = new CustomerFormVM
{
States = states,
Citys = citys,
Zips = zips
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CustomerFormVM vm)
{
if (ModelState.IsValid)
{
var customer = new Customer();
{
customer.FirstName = vm.FirstName;
customer.LastName = vm.LastName;
customer.StateId = vm.StateId;
customer.CityId = vm.CityId;
customer.ZipId = vm.ZipId;
}
db.Customers.Add(customer);
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
vm.States = db.States.ToList();
vm.Citys = db.Citys.ToList();
vm.Zips = db.Zips.ToList();
return View(vm);
}
}
public ActionResult Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var customervm = new CustomerFormVM();
{
Customer customer = db.Customers.SingleOrDefault(c => c.CustomerId == id);
if (customer == null)
{
return NotFound();
}
customervm.CustomerId = customer.CustomerId;
customervm.FirstName = customer.FirstName;
customervm.LastName = customer.LastName;
// Retrieve list of States
var states = db.States.ToList();
customervm.States = states;
// Retrieve list of Citys
var citys = db.Citys.ToList();
customervm.Citys = citys;
// Retrieve list of Citys
var zips = db.Zips.ToList();
customervm.Zips = zips;
// Set the selected state
customervm.StateId = customer.StateId;
// Set the selected city
customervm.CityId = customer.CityId;
// Set the selected zip
customervm.ZipId = customer.ZipId;
}
return View(customervm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CustomerFormVM vmEdit)
{
if (ModelState.IsValid)
{
Customer customer = db.Customers.SingleOrDefault(c => c.CustomerId == vmEdit.CustomerId);
if (customer == null)
{
return NotFound();
}
customer.FirstName = vmEdit.FirstName;
customer.LastName = vmEdit.LastName;
customer.StateId = vmEdit.StateId;
customer.CityId = vmEdit.CityId;
customer.ZipId = vmEdit.ZipId;
db.Entry(customer).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vmEdit);
}
}
Create View
<div class="form-group">
#Html.LabelFor(c => c.FirstName)
#Html.TextBoxFor(c => c.FirstName, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(c => c.LastName)
#Html.TextBoxFor(c => c.LastName, new { #class = "form-control" })
</div>
<div class="form-group">
#*#Html.LabelFor(s => s.StateId)
#Html.DropDownListFor(s => s.StateId, new SelectList(Model.States, "StateId", "Abbr"), "", new { #class = "form-control" })
#Html.ValidationMessageFor(s => s.StateId)*#
<label asp-for="StateId "></label>
<select asp-for="StateId " asp-items="Model.States" class="form-control" id="state-target"></select>
<span asp-validation-for="StateId " class="text-danger"></span>
</div>
<div class="form-group">
#*#Html.LabelFor(ct => ct.CityId)
#Html.DropDownListFor(ct => ct.CityId, new SelectList(Model.Citys, "CityId", "Name"), "", new { #class = "form-control" })
#Html.ValidationMessageFor(ct => ct.CityId)*#
<label asp-for="CityId"></label>
<select asp-for="CityId" asp-items="Model.Citys" class="form-control" id="city-target"></select>
<span asp-validation-for="CityId" class="text-danger"></span>
</div>
<div class="form-group">
#Html.LabelFor(z => z.ZipId)
#Html.DropDownListFor(z => z.ZipId, new SelectList(Model.Zips, "ZipId", "PostalCode"), "", new { #class = "form-control" })
#Html.ValidationMessageFor(z => z.ZipId)
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
}
#section scripts {
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
<script src="~/lib/js/example.js"></script>,
}
I had a similar situation but in my example I have a Root folder and depending on which root folder I am using the next drop down list would display the corresponding sub-folders.
Not sure if there is a purly asp.net solution but, I used Jquery/Ajax for this.
Your code should look something like this:
html list:
<label asp-for="StateId "></label>
<select asp-for="StateId " asp-items="Model.States" class="form-control" id="state-target"></select>
<span asp-validation-for="StateId " class="text-danger"></span>
<label asp-for="CityId"></label>
<select asp-for="CityId" asp-items="Model.Citys" class="form-control" id="city-target"></select>
<span asp-validation-for="CityId" class="text-danger"></span>
Jquery code, you write this in .js file and then add it to a specific view with this statement<script src="~/js/example.js"></script>, Don't forget you need to add a jquery library to your project before any other javascript, and your example.js will contain:
$(document).ready(function () {
$("#state-target").on("change", function () {
$list = $("#city-target");
$.ajax({
url: "/getCities",
type: "GET",
data: { id: $("#state-target").val() }, //id of the state which is used to extract cities
traditional: true,
success: function (result) {
$list.empty();
$.each(result, function (i, item) {
$list.append('<option value="' + item["CityId"] + '"> ' + item["Name"] + ' </option>');
});
},
error: function () {
alert("Something went wrong call the police");
}
});
});
});
The Ajax request will call this action in the Controller which will retrieve a list of cities from the database (using something like return dbContext.CityTable.Where(c => c.StateId == id).ToList() inside a getCititesFromDatabaseByStateId(id) method) and then return the Json object, the success function will create a list of options and apply it:
public IActionResult getCities(int id)
{
var cities = new List<City>();
cities = getCititesFromDatabaseByStateId(id); //call repository
return Json(citites);
}
In your ViewModel consider changing IEnumerable<State/City/Zip> (IEnumerable<T>) to IEnumerable<SelectListItem>. I can say as well your Model's are messy (but if you can get data the from the database focus on getting the list working 1st), consider improving them later.
Fix for 2 errors mentioned in the comments:
public List<City> getCititesFromDatabaseByStateId(int id)
{
return db.Citys.Where(c => c.StateId == id).ToList();
}
public ActionResult Create()
{
var states = new SelectList(db.States.ToList(), "StateId", "Abbr");
var citys = new SelectList(db.Citys.ToList(), "CityId", "Name");
var zips = new SelectList(db.Zips.ToList(), "ZipId", "Code");
var viewModel = new CustomerFormVM
{
States = states,
Citys = citys,
Zips = zips
};
return View(viewModel);
}
I am new to asp.net mvc. How can I automatically generate new Guid inside of foreach loop? I am using List<Expense> in view model and GUID as PrimaryKey, how I insert a multiple row from datatable to database insertion?
Here is my view model. I can insert a single row data, but if I insert more than one row data, it will show the error like :
Violation of PRIMARY KEY constraint 'PK__Expense__EBE72675160F4887'.
Cannot insert duplicate key in object 'dbo.Expense'.\r\nThe statement
has been terminated.
public System.Guid MaintenanceId { get; set; }
public System.Guid ExpenseSummaryId { get; set; }
public string BillNo { get; set; }
public Nullable<System.DateTime> BillDate { get; set; }
public string VechicleNo { get; set; }
public string ServiceType { get; set; }
public Nullable<double> Amount { get; set; }
public string Reason { get; set; }
public Nullable<System.Guid> UserRightsId { get; set; }
public Nullable<System.Guid> EmployeeId { get; set; }
public string ProviderName { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string ProviderCity { get; set; }
public string ProviderState { get; set; }
public string ProviderCountry { get; set; }
public string Pincode { get; set; }
public int Sno { get; set; }
public Nullable<bool> IsActive { get; set; }
public Nullable<bool> IsDeleted { get; set; }
public Nullable<System.DateTime> CreatedDate { get; set; }
public Nullable<System.DateTime> EditedDate { get; set; }
public Nullable<System.DateTime> LastActiveOn { get; set; }
public Nullable<System.Guid> RowID { get; set; }
public Nullable<System.Guid> CreatedSessionID { get; set; }
public Nullable<System.Guid> EditedSessionID { get; set; }
public Nullable<bool> OfflineMode { get; set; }
public Nullable<System.Guid> OfflineID { get; set; }
public List<Expense> Expenses { get; set; }
public virtual Employee Employee { get; set; }
public virtual UserRight UserRight { get; set; }
Here is My Controller
public JsonResult SaveOrder(TruckVM TVM)
{
bool status = false;
if (ModelState.IsValid)
{
using (TestDBEntities db = new TestDBEntities())
{
var guid = Guid.NewGuid();
maintenance ObjMaintenance = new maintenance
{
MaintenanceId=guid,
BillNo=TVM.BillNo,
BillDate=TVM.BillDate,
Amount=TVM.Amount
};
foreach (var i in TVM.Expenses)
{
ObjMaintenance.Expenses.Add(i);
}
db.maintenances.Add(ObjMaintenance);
//db.serviceproviders.Add(ObjServiceProvider);
db.SaveChanges();
status = true;
}
}
else
{
status = false;
}
return new JsonResult { Data = new { status = status } };
}`
here is my view
$(document).ready(function () {
var orderItems = [];
$('#add').click(function () {
var isValidItem = true;
if ($('#Particulars').val().trim() == '') {
isValidItem = false;
$('#Particulars').siblings('span.error').css('visibility', 'visible');
}
else {
$('#Particulars').siblings('span.error').css('visibility', 'hidden');
}
if (!($('#qty').val().trim() != '' && !isNaN($('#qty').val().trim()))) {
isValidItem = false;
$('#qty').siblings('span.error').css('visibility', 'visible');
}
else {
$('#qty').siblings('span.error').css('visibility', 'hidden');
}
if (!($('#unitprice').val().trim() != '' && !isNaN($('#unitprice').val().trim()))) {
isValidItem = false;
$('#unitprice').siblings('span.error').css('visibility', 'visible');
}
else {
$('#unitprice').siblings('span.error').css('visibility', 'hidden');
}
//Add item to list if valid
if (isValidItem) {
orderItems.push({
Particulars: $('#Particulars').val().trim(),
qty: parseInt($('#qty').val().trim()),
unitprice: parseFloat($('#unitprice').val().trim()),
TotalAmount: parseInt($('#qty').val().trim()) * parseFloat($('#unitprice').val().trim())
});
//Clear fields
$('#Particulars').val('').focus();
$('#qty').val('')
$('#unitprice').val('')
}
GeneratedItemsTable();
});
$('#submit').click(function () {
//validation of order
var isAllValid = true;
if (orderItems.length == 0) {
$('#orderItems').html('<span style="color:red;">Please add order items</span>');
isAllValid = false;
}
if ($('#BillNo').val().trim() == '') {
$('#BillNo').siblings('span.error').css('visibility', 'visible');
isAllValid = false;
}
else {
$('#BillNo').siblings('span.error').css('visibility', 'hidden');
}
if ($('#BillDate').val().trim() == '') {
$('#BillDate').siblings('span.error').css('visibility', 'visible');
isAllValid = false;
}
else {
$('#BillDate').siblings('span.error').css('visibility', 'hidden');
}
//Save if valid
if (isAllValid) {
var data = {
BillNo: $('#BillNo').val().trim(),
BillDate: $('#BillDate').val().trim(),
Amount: $('#Amount').val().trim(),
Expenses: orderItems
}
$(this).val('Please wait...');
$.ajax({
url: '/VechicleMaintenance/SaveOrder',
type: "POST",
data: JSON.stringify(data),
dataType: "JSON",
contentType: "application/json",
success: function (d) {
//check is successfully save to database
if (d.status == true) {
//will send status from server side
alert('Successfully done.');
//clear form
orderItems = [];
$('#BillNo').val('');
$('#BillDate').val('');
$('#orderItems').empty();
}
else {
alert('Failed');
}
$('#submit').val('Save');
},
error: function () {
alert('Error. Please try again.');
$('#submit').val('Save');
}
});
}
});
function GeneratedItemsTable() {
if (orderItems.length > 0) {
var $table = $('<table/>');
$table.append('<thead><tr><th>Particulars</th><th>qty</th><th>unitprice</th><th>TotalAmount</th></tr></thead>');
var $tbody = $('<tbody/>');
$.each(orderItems, function (i, val) {
var $row = $('<tr/>');
$row.append($('<td/>').html(val.Particulars));
$row.append($('<td/>').html(val.qty));
$row.append($('<td/>').html(val.unitprice));
$row.append($('<td/>').html(val.TotalAmount));
$tbody.append($row);
});
$table.append($tbody);
$('#orderItems').html($table);
}
}
});
<table width="100%">
<tr>
<td>Particulars</td>
<td>qty</td>
<td>unitprice</td>
<td> </td>
</tr>
<tr>
<td>
<input type="text" id="Particulars" />
<span class="error">Item name required</span>
</td>
<td>
<input type="text" id="qty" />
<span class="error">Valid quantity required</span>
</td>
<td>
<input type="text" id="unitprice" />
<span class="error">Valid rate required</span>
</td>
<td>
<input type="button" id="add" value="add" />
</td>
</tr>
</table>
<div id="orderItems" class="tablecontainer">
</div>
<div style="padding:10px 0px; text-align:right">
<input id="submit" type="button" value="Save" style="padding:10px 20px" />
</div>
You're generating a new Guid for the MaintenanceId property of ObjMaintenance, but you're not creating the Guid for the ID property of each Expenses objuect that you're adding. Assuming that property is named ExpenseId, then you loop needs to be
....
maintenance ObjMaintenance = new maintenance
{
MaintenanceId = Guid.NewGuid(),
....
};
foreach (var i in TVM.Expenses)
{
i.ExpenseId = Guid.NewGuid(); // add this
ObjMaintenance.Expenses.Add(i);
}
db.maintenances.Add(ObjMaintenance);
db.SaveChanges();
Side note: I suggest you look at the answers here, here and here for dynamically adding new items to a collection which allows you to add, edit and delete on the fly in 1/10 of the code you currently have.