C# mvc saving deviceconfig as new config id in foreign table - c#

I am trying to create a system where it is possible to add/ change device configurations. The user should be able to add / delete rows at the same time.
Everytime a config is saved, a new config_id is created and VersionNr is increased.
I am 100% sure I am doing something wrong, and what is going wrong. But I dont know how to fix it or improve it.
Here is my code:
public ActionResult Edit(int? Id)
{
//create new list
var Device_Pricelist = new List<Device_Pricelist>(db.Device_Pricelist.Where(r => r.DeviceConfig.Device_config_id == Id));
//create new SelectList in Device_Pricelist
var SelectedCMI = (from d in db.pricelist
select new { d.Price_id, Value = d.bas_art_nr }).Distinct();
//call viewbag based on SelectedCMI query
ViewBag.SelectedCMI = new SelectList(SelectedCMI.Distinct(), "Price_id", "Value");
return View(Device_Pricelist);
}
public ActionResult Edit([Bind(Include = "id,Device_config_id,Price_id,amount,assembly_order")]DeviceConfig deviceConfig, List<Device_Pricelist> device_Pricelists)
{
if (ModelState.IsValid)
{
try
{
try
{
db.DeviceConfig.Add(deviceConfig).Device_config_id = deviceConfig.Device_config_id++;
db.DeviceConfig.Add(deviceConfig).device_type_id = deviceConfig.device_type_id = 13;
db.DeviceConfig.Add(deviceConfig).Active = true;
//Needs to be based on current VersionNr in deviceConfig
db.DeviceConfig.Add(deviceConfig).VersionNr = deviceConfig.VersionNr + 1;
db.DeviceConfig.Add(deviceConfig).Date = deviceConfig.Date = DateTime.Now;
}
finally
{
foreach (var item in device_Pricelists)
{
db.Entry(item).State = EntityState.Added;
}
}
db.SaveChanges();
TempData["SuccesMessage"] = "Data is Succesfully saved";
return RedirectToAction("Index");
}
catch
{
TempData["AlertMessage"] = "Saving Data Failed, " + "Try Again";
}
}
return View(device_Pricelists);
}
view:
#model List<ConcremoteDeviceManagment.Models.Device_Pricelist>
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("Edit", "Home", FormMethod.Post))
{
<h1>
#Html.DisplayName("Edit Configuration")
</h1>
<h2>
#* #Html.DisplayFor(model => model.DeviceType.name)<br />*#dammit
</h2>
if (TempData["AlertMessage"] != null)
{
<p class="alert alert-danger" id="FailMessage">#TempData["AlertMessage"]</p>
}
#Html.ValidationSummary(true)
#Html.AntiForgeryToken()
<div>
#* Add New*#
</div>
<table class="table table-hover" id="dataTable">
<tr>
<th class="table-row">
#Html.DisplayName("BAS artikelnummer")
</th>
<th class="table-row">
#Html.DisplayName("Beschrijving")
</th>
<th class="table-row">
#Html.DisplayName("Aantal")
</th>
<th class="table-row">
#Html.DisplayName("Bouw Volgorde")
</th>
<th class="table-row">
Add New Row
</th>
</tr>
#if (Model != null && Model.Count > 0)
{
int j = 0;
foreach (var item in Model)
{
<tr>
#Html.HiddenFor(a => a[j].id)
#Html.HiddenFor(a => a[j].Device_config_id)
#* #Html.HiddenFor(a => a[j].Price_id)*#
<td class="table-row">
#Html.DropDownListFor(a => a[j].Price_id, (IEnumerable<SelectListItem>)ViewBag.SelectedCMI, null, new { #class = "form-control" })
</td>
<td class="table-row">
#Html.DisplayFor(a => a[j].Pricelist.description, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(a => a[j].Pricelist.description, "", new { #class = "text-danger" })
</td>
<td class="table-row">
#Html.EditorFor(a => a[j].amount, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(a => a[j].amount, "", new { #class = "text-danger" })
</td>
<td class="table-row">
#Html.EditorFor(a => a[j].assembly_order, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(a => a[j].assembly_order, "", new { #class = "text-danger" })
</td>
#*<td class="table-row">
#Html.DisplayFor(a => a[j].DeviceConfig.Date, new { htmlAttributes = new { #class = "form-control" } })
</td>*#
<td>
#if (j > 0)
{
Remove
}
</td>
</tr>
j++;
}
}
</table>
<input type="submit" value="Save Device Data" class="btn btn-primary" />
<button onclick="location.href='#Url.Action("Index", "Home")';return false; " class="btn btn-primary">Back to list</button>
}
#section Scripts{
#*#Scripts.Render("~/bundles/jqueryval")*#
<script language="javascript">
$(document).ready(function () {
//1. Add new row
$("#addNew").click(function (e) {
e.preventDefault();
var $tableBody = $("#dataTable");
var $trLast = $tableBody.find("tr:last");
var $trNew = $trLast.clone();
var suffix = $trNew.find(':input:first').attr('name').match(/\j+/);
$trNew.find("td:last").html('Remove');
$.each($trNew.find(':input'), function (i, val) {
// Replaced Name
var oldN = $(this).attr('name');
var newN = oldN.replace('[' + suffix + ']', '[' + (parseInt(suffix) + 1) + ']', '[' + suffix + ']', '[' + (parseInt(suffix) + 1) + ']', '[' + suffix + ']', '[' + (parseInt(suffix) + 1) + ']');
$(this).attr('name', newN);
//Replaced value
var type = $(this).attr('type');
//if (type.toLowerCase() == "text") {
// $(this).attr('value', '');
//}
// If you have another Type then replace with default value
$(this).removeClass("input-validation-error");
});
$trLast.after($trNew);
// Re-assign Validation
//var form = $("form")
// .removeData("validator")
// .removeData("unobtrusiveValidation");
//$.validator.unobtrusive.parse(form);
});
// 2. Remove
//$('a.remove').live("click", function (e) { --> this is for old jquery library
$('body').on("click", '#remove', function (e) {
e.preventDefault();
$(this).parent().parent().remove();
});
});
</script>
<script type="text/javascript">
function SelectedIndexChanged() {
//Form post
document.demoForm.submit();
}
</script>
I hope somebody is able to help me.
More information will be given when needed.

Your method accepts 2 parameters but you are only posting 1 object - List<Device_PriceList>. Let's assume you want to construct a new DeviceConfig based on the existing one, you should change your Action method to the following:
public ActionResult Edit(List<Device_Pricelist> device_Pricelists)
{
if (ModelState.IsValid)
{
try
{
var deviceConfig = db.DeviceConfig.Find(device_Pricelists.First().Device_config_id);
deviceConfig.device_type_id = 13;
deviceConfig.Active = true;
deviceConfig.VersionNr++;
deviceConfig.Date = DateTime.Now;
db.DeviceConfig.Add(deviceConfig);
foreach(var item in device_Pricelists)
{
item.Device_config_id = deviceConfig.Device_config_id;
}
db.Device_Pricelists.AddRange(device_Pricelists);
db.SaveChanges();
TempData["SuccesMessage"] = "Data is Succesfully saved";
return RedirectToAction("Index");
}
catch
{
TempData["AlertMessage"] = "Saving Data Failed, Try Again";
}
}
return View(device_Pricelists);
}
Remember when posting a list, you need to post complete sets of the object you're trying to map to. That is for example [0].Id, [0].Device_config_id (etc), [1].Id, [1].Device_config_id (etc).
Your JS doesn't seem correct, particularly the .replace(..) call with 6 parameters, so you're probably seeing lots of [0]s when you clone the rows. Some simpler JS that will get you the same result is:
var oldN = $(this).attr('name');
var idx = parseInt(oldN.substr(1, oldN.indexOf(']')));
var newN = oldN.replace('[' + idx + ']', '[' + (idx + 1) + ']');

Related

How to add an SelectedItem from Dropdownlist to a <Table> using model List<>

I'm working on a page that will add the selected item from a dropdownlist to a List<> using button onclick.
The problem is the new selecteditem is overwriting the old value.
I simply would like to display a table from the selected items like this:
#---Model-----Remove-----
1 Model#1 x
2 Model#2 x
3 Model#3 x
4 Model#4 x
5 Model#5 x
-------------------------
Please see my code below,
ModelDescription.cs (model):
public class ModelDescription
{
public string modelDesc { get; set; }
}
method in controller:
public ActionResult StockOnHand()
{
bindModelDesc();
return View();
}
public void bindModelDesc()
{
var mc = db.ModelMaster_tbl.ToList();
List<SelectListItem> mclist = new List<SelectListItem>();
mclist.Add(new SelectListItem { Text = "--Select Model Type--", Value = "0" });
mclist.Add(new SelectListItem { Text = "--Select All Model--", Value = "1" });
foreach (var m in mc.Select(x => x.modelDesc).Distinct())
{
mclist.Add(new SelectListItem { Text = m, Value = m });
ViewBag.ModelDescs = mclist;
}
}
public ActionResult AddToListSOH(ModelDescription model)
{
var result = new List<ModelDescription>();
var res = db.ModelMaster_tbl.Where(x => x.modelDesc == model.modelDesc).SingleOrDefault();
result.Add(new ModelDescription { modelDesc = res.modelDesc });
return PartialView("AddToListSOH", result);
}
StockOnHand.cshtml (view):
#using (Html.BeginForm("StockOnHand", "PWSupermarket", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<div class="card">
<div class="card-body">
<form class="form-horizontal" role="form">
<h5 class="card-title">Stock On Hand</h5>
<p class="card-text">Generates the buildable quantity of a unit. </p>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#if (TempData["Message"] != null)
{
<span class="text-success"><strong>#TempData["Message"]</strong></span>
}
<div class="form-group">
#Html.LabelFor(model => model.modelDesc, htmlAttributes: new { #class = "col-md-3 control-label" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.modelDesc, ViewBag.ModelDescs as List<SelectListItem>, htmlAttributes: new { #class = "form-control" })
<button class="btn btn-outline-primary mt-1" type="button" onclick="AddToList()">Add To List</button>
</div>
</div>
<div id="foo1" class="mt-2">
</div>
</form>
</div>
</div>
}
Javascript to render the list of selected items partial view:
<script type="text/javascript">
function AddToList() {
$.ajax({
type: "Get",
url: '#Url.Action("AddToListSOH", "PWSupermarket")',
data: { modelDesc: $('#modelDesc').val() },
contentType: "application/html; charset=utf-8",
success: function (result) {
$('#foo1').html(result);
},
error: function (ex) { alert('failed.'); }
})
}
</script>
AddToListSOH.cshtml (Partial View for the list of selected items):
#model IEnumerable<MESProject_P1_csmvc.Models.ModelDescription>
<div>
#{ var count = 0;}
<table class="table table-sm table-striped" #*style="font-size: .7rem;"*#>
<caption>List of Models</caption>
<thead class="thead-dark">
<tr>
<th>#</th>
<th>Model</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#count
</td>
<td>
#Html.DisplayFor(i => item.modelDesc)
</td>
</tr>
}
</tbody>
</table>
</div>
screen shot of the page
Example to make SelectListItem List
private List<SelectListItem> ModelDeskList(ModelDesk modelDesc)
{
List<SelectListItem> selectList = new List<SelectListItem>();
selectList.Add(new SelectListItem { Value = "", Text = "------Select-----",Selected=true });
foreach (var model in modelDesc)
{
selectList.Add(new SelectListItem { Value = model.Id.ToString(), Text = model.Name});
}
return selectList;
}
I hope you find your solution from it
I solved my problem thanks to this link:
I'm storing the list of emails in Session["emails"] and every time I add a new email to the list, I just update it a pass it to a new list with all the records and at the end return the partial view.
.NET use partial view multiple times #Rolando F
I've changed some of my codes:
ModelDescription.cs
public class ModelDescription
{
public IEnumerable<string> modelsAdded { get; set; }
}
AddToListSOH method in controller:
public ActionResult AddToListSOH(string model)
{
if (Session["modelInputs"] == null)
{
List<string> temphandler1 = new List<string>();
temphandler1.Add(model);
Session["modelInputs"] = temphandler1;
}
else
{
List<string> temphandler2 = new List<string>();
temphandler2 = (List<string>)Session["modelInputs"];
temphandler2.Add(model);
Session["modelInputs"] = temphandler2;
}
var result = new ModelDescription { modelsAdded = (List<string>)Session["modelInputs"] };
return PartialView("AddToListSOH", result);
}
AddToListSOH.cshtml (Partial View):
<table class="table table-sm table-striped" #*style="font-size: .7rem;"*#>
<caption>List of Models</caption>
<thead class="thead-dark">
<tr>
<th>#</th>
<th>Model</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.modelsAdded)
{
<tr>
<td>
#count
</td>
<td>
#Html.DisplayFor(i => item)
</td>
<td>
Remove
</td>
</tr>
}
</tbody>
</table>

I can't fill data by dropdownlist change event for dynamically created textboxes in asp.net mvc 5

I have got a problem as follows:
I have created a table with dynamic rows by clicking "add button".A row includes some textboxes and one dropdown list. When I select a value from dropdown list as a term to automatically fill for other textboxes by data I get from the server. Now I just can apply for the first row.I don't know how to apply for the new row when click "add button".Please help me how to solve this problem. Thanks a lot.
This is my webpage
This is my controller code:
using Phieu90.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Phieu90.Controllers
{
public class XuLyPhieuController : Controller
{
XuLyPhieu90Entities1 db;
public XuLyPhieuController()
{
db = new XuLyPhieu90Entities1();
}
public ActionResult Index()
{
var lislinhkien = new SelectList(db.PA_LINHKIEN.ToList(), "ITEM_CODE", "ITEM_CODE");
ViewBag.LinhKien = lislinhkien;
List<PA_CHITIETPHIEU> listchitiet = new List<PA_CHITIETPHIEU> { new PA_CHITIETPHIEU { NHACUNGCAP = "", TENSP = "", MASP = "", MADUTOAN = "", SOLUONG = 0, DONVI = "", DONGIA = 0, SOTIEN = 0 } };
return View(listchitiet);
}
[HttpPost]
public JsonResult GetLinhKien(string Prefix)
{
var result = db.PA_LINHKIEN.SingleOrDefault(x => x.ITEM_CODE == Prefix);
return Json(result, JsonRequestBehavior.AllowGet);
}
}
}
This is my View:
<body>
<h2 style="text-align:center;margin-top:50px;margin-bottom:50px;">Bill Detail</h2>
#using (Html.BeginForm("PhieuMuaLinhKien", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div>Add New Row <i class="fas fa-plus-circle"></i></div>
<table id="dataTable" border="0" cellpadding="0" cellspacing="0" class="table table-bordered">
<tr>
<th class="title">Bill ID</th>
<th class="title">Supplier</th>
<th class="title">Item name</th>
<th class="title">Item code</th>
<th class="title">Reference code</th>
<th class="title">Quantity</th>
<th class="title">Unit</th>
<th class="title">Price</th>
<th class="title">Sum</th>
<th class="title">Delete</th>
</tr>
#if (Model != null && Model.Count > 0)
{
int j = 0;
foreach (var i in Model)
{
<tr style="border:1px solid black">
<td class="title">#Html.TextBoxFor(a => a[j].MACHITIET, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required" })</td>
<td class="title">#Html.TextBoxFor(a => a[j].NHACUNGCAP, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required", #id = "txtncc" })</td>
<td class="title">#Html.TextBoxFor(a => a[j].TENSP, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required",#id= "txttensp" })</td>
#using (Html.BeginForm())
{
#*<td class="title">#Html.TextBoxFor(a => a[j].MASP, new { #class = "form-control view-data", #style = "width:120px;margin-left:12px;", #required = "required"})</td>*#
<td>#Html.DropDownListFor(a => a[j].MASP, ViewBag.LinhKien as SelectList, "--*--", new { #class = "form-control view-data", #style = "width:120px;margin-left:12px;", #required = "required",#id="ddllinhkien" })</td>
}
<td class="title">#Html.TextBoxFor(a => a[j].MADUTOAN, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required" })</td>
<td class="title">#Html.TextBoxFor(a => a[j].SOLUONG, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required" })</td>
<td class="title">#Html.TextBoxFor(a => a[j].DONVI, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required" })</td>
<td class="title">#Html.TextBoxFor(a => a[j].DONGIA, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required", #id = "txtdongia" })</td>
<td class="title">#Html.TextBoxFor(a => a[j].SOTIEN, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required" })</td>
<td>
#if (j > 0)
{
Remove <i class="fas fa-trash"></i>
}
</td>
</tr>
j++;
}
}
</table>
}
<div style="margin-left:660px;margin-top:30px;">
<button type="submit" class="btn btn-primary" id="btnSubmit" style="">Save <i class="fas fa-save"></i></button>
</div>
enter code here
<script type="text/javascript">
$(document).ready(function () {
//1. Add new row
$("#addNew").click(function (e) {
e.preventDefault();
var $tableBody = $("#dataTable");
var $trLast = $tableBody.find("tr:last");
var $trNew = $trLast.clone().insertAfter($trLast);
var suffix = $trNew.find(':input:first').attr('name').match(/\d+/);
$trNew.find("td:last").html('<a href="#" class="btn btn-block btn-
danger remove">Xóa <i class="fas fa-trash"></i></a>');
$.each($trNew.find(':input'), function (i, val) {
// Replaced Name
var oldN = $(this).attr('name');
var newN = oldN.replace('[' + suffix + ']', '[' +
(parseInt(suffix) + 1) + ']');
$(this).attr('name', newN);
$(this).attr('id', newN);
//Replaced value
var type = $(this).attr('type');
if (type.toLowerCase() == "text") {
$(this).attr('value', '');
}
$(this).removeClass("input-validation-error");
});
$trLast.after($trNew);
var form = $("form")
.removeData("validator")
.removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(form);
});
//2. Remove
//$('a.remove').on("click", function (e) {
// e.preventDefault();
// $(this).parent().parent().remove();
//});
$("#dataTable").on("click", ".remove", function () {
$(this).closest('tr').remove();
});
$('.view-data').change(function () {
var malk = $(this).val();
$.ajax({
url: "/XuLyPhieu/GetLinhKien",
type: "POST",
dataType: "json",
data: { Prefix: malk },
success: function (data) {
//do something
})
}
})
})
});

reload one part of page after clicking button in form asp.net

Good news everyone. I have question, again. I have page with personal information block, personal informaion edit block and pasword block. I need reload only password block after click on button. But I have a problem, when I clicked on button, my page try to reload all page. And requires to again call the method of load personal and password information. But, I need only show message and do things with passwords in password block without affecting personal information block. (Also I need to work with personal information block without affecting password block, but I think it's will be the same answer below).
PersonalInf cotroller:
[HttpPost]
public ActionResult changePassword(PersonalPageModel personalPage)
{
var passwordDetauls = dbModel.USERS.Where(model =>
model.vPassword == personalPage.usersModel.NewPassword
).FirstOrDefault();
if (passwordDetauls != null)
{
personalPage.usersModel.ChangePasswordErrorMessage = "Новый пароль совпадает со старым!";
return View("~/Views/home/PersonalPage.cshtml", personalPage);
}
else
{
var userDetails = dbModel.USERS.Where(model =>
model.vPassword == personalPage.usersModel.vPassword).FirstOrDefault();
if (userDetails == null)
{
personalPage.usersModel.LoginErrorMessage = "Неверный пароль!";
return View("~/Views/home/PersonalPage.cshtml", personalPage);
}
else
{
int iIdUsers = Convert.ToInt32(Session["iIdUsers"].ToString());
//Change password here!
var query = from ord in dbModel.USERS
where ord.iIdUsers == iIdUsers
select ord;
foreach (var ord in query)
{
ord.vPassword = personalPage.usersModel.NewPassword;
}
try
{
dbModel.SaveChanges();
}
catch(Exception exc)
{
personalPage.usersModel.ChangePasswordErrorMessage = exc.Message;
}
ViewBag.SuccessMessage = "Пароль был успешно изменен!";
//Session["iIdUsers"] = userDetails.iIdUsers;
//Session["vNickName"] = userDetails.vNickName;
//return RedirectToAction("PersonalPage", "Home");
return View("~/Views/home/PersonalPage.cshtml", personalPage);
}
}
}
and view code, code like autherize form:
#using (Html.BeginForm("changePersonalInf", "PersonalPage", FormMethod.Post))
{
#Html.AntiForgeryToken()
<tr>
<td><p>Город:</p></td>
<td>#Html.EditorFor(model => model.personalInfModel.vCity, new { htmlAttributes = new { #class = "form-control" } })</td>
</tr>
<tr>
<td><p>ФИО:</p></td>
<td>#Html.EditorFor(model => model.personalInfModel.vFIO, new { htmlAttributes = new { #class = "form-control" } })</td>
</tr>
<tr>
<td><p>Индекс:</p></td>
<td>#Html.EditorFor(model => model.personalInfModel.vIndex, new { htmlAttributes = new { #class = "form-control" } })</td>
</tr>
<tr>
<td><p>Населенный пункт:</p></td>
<td>#Html.EditorFor(model => model.personalInfModel.vLocality, new { htmlAttributes = new { #class = "form-control" } })</td>
</tr>
<tr>
<td><p>Улица:</p></td>
<td>#Html.EditorFor(model => model.personalInfModel.vStreet, new { htmlAttributes = new { #class = "form-control" } })</td>
</tr>
<tr>
<td><p>Дом/корпус/строение:</p></td>
<td>#Html.EditorFor(model => model.personalInfModel.vHome, new { htmlAttributes = new { #class = "form-control" } })</td>
</tr>
<tr>
<td><p>Квартира:</p></td>
<td>#Html.EditorFor(model => model.personalInfModel.vApartment, new { htmlAttributes = new { #class = "form-control" } })</td>
</tr>
<tr>
<td><p>Телефон:</p></td>
<td>#Html.EditorFor(model => model.personalInfModel.vPhone, new { htmlAttributes = new { #class = "form-control" } })</td>
</tr>
<tr>
<td><input type="submit" value="Изменить" class="btn-problem" /></td>
<td><input type="reset" value="Очистка" class="btn-problem" /></td>
</tr>
}
Put the change password block in a partial view and change the form to Ajax form:
#using (Html.BeginForm("changePersonalInf", "PersonalPage", FormMethod.Post)) {
}
to
#using (Ajax.BeginForm("changePersonalInf", "PersonalPage", null, new AjaxOptions {
UpdateTargetId = "id_of_your_change_password_block"
}, new { role = "form", id = "AssignCoachForm" })) {
}
This will automatically update the block with the given ID. Alternatively, you can do that by yourself in JavaScript and have more control over it:
#using (Ajax.BeginForm("changePersonalInf", "PersonalPage", null, new AjaxOptions {
OnSuccess = "your_js_success_function(data);",
OnFailure = "your_js_failure_function();",
}, new { role = "form", id = "AssignCoachForm" })) {
}

HTML Table data not updating in model

I have a ViewModel that contains two lists of Conditions - BuyConditions and SellConditions - plus a couple of attributes - Name etc. The lists are displayed using tables in the view. jQuery allows the tables to be manipulated - adding Conditions to the tables (from Buy Condition / Sell Condition DDL's) and removing Conditions from the tables.
My problem is that the Condition lists are not updated in the model when it is posted back to the controller.
Something that may point to the issue is that when the model is returned to the view (due to ModelStat.IsValid failing), the data in the Markets DDL still exists, but the data in the Buy and Sell Condition DDL's doesn't.
I can't find an example on the net to figure out where I'm going wrong. Anyone done this before?
ViewModel:
public class StrategyViewModel
{
public string ID { get; set; }
[Display(Name = "Strategy Name")]
public string StrategyName { get; set; }
[Display(Name = "Market")]
public string SelectedMarketID { get; set; }
[Display(Name = "Asset Type")]
public string SelectedShareTypeID { get; set; }
[Display(Name = "Share")]
public string SelectedShareID { get; set; }
public bool Active { get; set; }
public IEnumerable<Market> Markets { get; set; } // top level of three cascading DDL's - the other two populated via JQuery
public IEnumerable<Condition> BuyConditionList { get; set; } // used to populate DDL
public IEnumerable<Condition> SellConditionList { get; set; } // used to populate DDL
public List<BuyCondition> BuyConditions { get; set; } // list of Buy Conditions
public List<SellCondition> SellConditions { get; set; } // list of Sell Conditions
AppRepository repository = new AppRepository();
public StrategyViewModel()
{
// populate lists
Markets = ListUtils.AddDefaultOptionToMarketList( repository.GetMarkets(), -1, "Select a Market" ).AsEnumerable();
BuyConditionList = repository.GetConditions();
SellConditionList = repository.GetConditions();
BuyConditions = new List<BuyCondition>();
SellConditions = new List<SellCondition>();
}
}
Controller:
public ActionResult Create()
{
StrategyViewModel model = new StrategyViewModel();
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "User, Admin")]
public ActionResult Create(StrategyViewModel model)
{
// for debugging
var errorList = ModelState.Values.SelectMany(v => v.Errors);
if (ModelState.IsValid)
{
var user = repository.GetCurrentUser(User.Identity.GetUserId());
var strategy = new Strategy();
strategy.StrategyName = model.StrategyName;
strategy.ShareID = Convert.ToInt32(model.SelectedShareID);
strategy.BuyConditions = model.BuyConditions.ToList();
strategy.SellConditions = model.SellConditions.ToList();
strategy.Active = model.Active;
int strategyID = repository.AddStrategy(user, strategy);
return RedirectToAction("Index");
}
return View(model);
}
View:
#model ShareTrigger.Models.StrategyViewModel
#{
ViewBag.Title = "Create";
}
#{Html.EnableUnobtrusiveJavaScript(true);}
<script type="text/javascript">
$(document).ready(function () {
$(function () {
$('#SelectedMarketID').change(function () {
var selectedMarketID = $(this).val();
$.getJSON('#Url.Action("ShareTypes")', { marketId: selectedMarketID }, function (shareTypes) {
var shareTypesSelect = $('#SelectedShareTypeID');
shareTypesSelect.empty();
$.each(shareTypes, function (index, shareType) {
shareTypesSelect.append($('<option/>').attr('value', shareType.Value).text(shareType.Text));
});
$('#SelectedShareTypeID').trigger("change");
});
});
$('#SelectedShareTypeID').change(function () {
var selectedShareTypeId = $(this).val();
var selectedMarketID = $('#SelectedMarketID').val();
$.getJSON('#Url.Action("Shares")', { shareTypeId: selectedShareTypeId, marketID: selectedMarketID }, function (shares) {
var sharesSelect = $('#SelectedShareID');
sharesSelect.empty();
$.each(shares, function (index, share) {
sharesSelect.append($('<option/>').attr('value', share.Value).text(share.Text));
});
});
});
});
$('#AddBuyCondition').click(function () {
var conditionID = +$("#BuyConditionList").val();
if (conditionID != -2) {
conditionID = +$("#BuyConditionList").val();
var conditionText = $("#BuyConditionList").find('option:selected').text();
$("tr:contains('Add')").remove();
$('#BCDropDownRow').before('<tr class="bcrow"><td class="BuyConditionCell" data-conditionID="' + conditionID + '"><input data-val="true" data-val-number="The field ConditionID must be a number." data-val-required="The ConditionID field is required." id="item_ConditionID" name="item.ConditionID" type="hidden" value="' + conditionID + '">' + conditionText + '</td><td><button class="RemoveBuyCondition type="button" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-minus"></span></button></td></tr>');
$("#BuyConditionList").find('option:selected').remove();
var rows = $('#BuyConditionList option').size();
if (rows == 0) { $("#BuyConditionList").append('<option value="-2">No more conditions to select</option>'); }
}
});
$('#BuyConditionsTable').on('click', '.RemoveBuyCondition', function () {
var conditionID = +$(this).parent().parent().find('.BuyConditionCell').data('conditionid');
var conditionText = $(this).parent().parent().find('.BuyConditionCell').text();
$(this).closest('.bcrow').remove();
$('#BuyConditionList option[value="-2"]').remove();
$("#BuyConditionList").append('<option value="' + conditionID + '">' + conditionText + '</option>');
var options = $('#BuyConditionList option');
var arr = options.map(function (_, o) { return { t: $(o).text(), v: o.value }; }).get();
arr.sort(function (o1, o2) { return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0; });
options.each(function (i, o) {
o.value = arr[i].v;
$(o).text(arr[i].t);
});
});
$('#AddSellCondition').click(function () {
var conditionID = +$("#SellConditionList").val();
if (conditionID != -2) {
conditionID = +$("#SellConditionList").val();
var conditionText = $("#SellConditionList").find('option:selected').text();
$("tr:contains('Add')").remove();
$('#SCDropDownRow').before('<tr class="scrow"><td class="SellConditionCell" data-conditionID="' + conditionID + '"><input id="item_ConditionID" name="item.ConditionID" type="hidden" value="' + conditionID + '">' + conditionText + '</td><td><button class="RemoveSellCondition type="button" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-minus"></span></button></td></tr>');
$("#SellConditionList").find('option:selected').remove();
var rows = $('#SellConditionList option').size();
if (rows == 0) { $("#SellConditionList").append('<option value="-2">No more conditions to select</option>'); }
}
});
$('#SellConditionsTable').on('click', '.RemoveSellCondition', function () {
var conditionID = +$(this).parent().parent().find('.SellConditionCell').data('conditionid');
var conditionText = $(this).parent().parent().find('.SellConditionCell').text();
$(this).closest('.scrow').remove();
$('#SellConditionList option[value="-2"]').remove();
$("#SellConditionList").append('<option value="' + conditionID + '">' + conditionText + '</option>');
var options = $('#SellConditionList option');
var arr = options.map(function (_, o) { return { t: $(o).text(), v: o.value }; }).get();
arr.sort(function (o1, o2) { return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0; });
options.each(function (i, o) {
o.value = arr[i].v;
$(o).text(arr[i].t);
});
});
});
</script>
<h2>Create Strategy</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.StrategyName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.StrategyName)
#Html.ValidationMessageFor(model => model.StrategyName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SelectedMarketID, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(x => x.SelectedMarketID, new SelectList(Model.Markets, "MarketId", "MarketCode"))
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SelectedShareTypeID, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(x => x.SelectedShareTypeID, Enumerable.Empty<SelectListItem>(), "Select an Asset Type")
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SelectedMarketID, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(x => x.SelectedShareID, Enumerable.Empty<SelectListItem>(), "Select a Share")
</div>
</div>
<div>
</div>
<div class="col-md-10">
<table class="table" id="BuyConditionsTable">
<tr>
<th>
#Html.DisplayName("Buy Conditions")
</th>
<th></th>
</tr>
#foreach (var item in Model.BuyConditions)
{
<tr>
<td>
#Html.HiddenFor(modelItem => item.ConditionID)
#Html.DisplayFor(modelItem => item.ConditionName)
</td>
<td></td>
</tr>
}
<tr id="BCDropDownRow">
<td>
<button id="AddBuyCondition" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-plus"></span>
</button>
#Html.DropDownListFor(x => x.BuyConditionList, new SelectList(Model.BuyConditionList, "ConditionID", "ConditionName"))
</td>
<td></td>
</tr>
</table>
</div>
<div>
</div>
<div class="col-md-10">
<table class="table" id="SellConditionsTable">
<tr>
<th>
#Html.DisplayName("Sell Conditions")
</th>
<th></th>
</tr>
#foreach (var item in Model.SellConditions)
{
<tr>
<td>
#Html.HiddenFor(modelItem => item.ConditionID)
#Html.DisplayFor(modelItem => item.ConditionName)
</td>
<td></td>
</tr>
}
<tr id="SCDropDownRow">
<td>
<button id="AddSellCondition" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-plus"></span>
</button>
#Html.DropDownListFor(x => x.SellConditionList, new SelectList(Model.SellConditionList, "ConditionID", "ConditionName"))
</td>
<td></td>
</tr>
</table>
</div>
<div class="form-group">
<div class="col-md-offset-9 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
}
The reason you're getting BuyConditions and SellConditions empty because of the following code
#Html.HiddenFor(modelItem => item.ConditionID)
This will render ALL as
<input type="hidden" id="item_ConditionID" name="item.ConditionID" />
It can't be resolved in the controller action Create due to the wrong naming.
Instead, it should have been
#Html.HiddenFor(x => x.SellConditions[index].ConditionID)
This will render the control as (if index is 0)
<input type="hidden" id="SellConditions_0__ConditionID" name="SellConditions[0].ConditionID" />
Therefore, the foreach block should be as follow
#foreach (int index = 0; index < Model.SellConditions.Count; index++)
{
<tr>
<td>
#Html.HiddenFor(x => x.SellConditions[index].ConditionID)
#Html.DisplayFor(x => x.SellConditions[index].ConditionName)
</td>
<td></td>
</tr>
}
And the same rule for BuyConditions too.

Store mutiple options in dropdown for a selected value in MVC

Am using MVC and manipulating values using ViewData. I have the code in controller as
IList<SelectListItem> sizeList = new List<SelectListItem>();
foreach (var item in sizeInfo)
{
SelectListItem listItem = new SelectListItem();
listItem.Value = item._price.ToString();
listItem.Text = item._sizeOption;
sizeList.Add(listItem);
}
ViewData["SizeList"] = sizeList;
productInstance.SizeCount = true;
How ever along with the text and value ie price and size option of the list items i want to store another value based on user selection in the drop down.
My drop down fetches this ViewData as
#Html.Raw(#Html.DropDownList("SizeList", ViewData["SizeList"] as SelectList, new { #id = "ddsize1" }))
how can i add one more attribute other than text and value based on user selection of particular selected drop down.?
Controller:
you can take one more list, it contains price and the attribute you want.
place that list in hidden field in view.
IList<SelectListItem> CustomList = new List<SelectListItem>();
foreach (var item in sizeInfo)
{
SelectListItem listItem = new SelectListItem();
listItem.Value = item.yourattribue.ToString();
listItem.Text = item._sizeOption;
sizeList.Add(listItem);
}
ViewData["CustomList"] = CustomList;
in view:
#using (Html.BeginForm())
{
<div id="divPrice1"style="display:none">
<table>
<tr>
<td class="divSizehPrice" style="text-align:right">#Html.Raw(#Model.dtcurrentCurrency.Rows[0]["HTMLENTITY"])</td>
<td class="divSizehPrice" style="width:24%; text-align:left; color:Red;"><div id="PriceDiv1"></div></td>
<td class="divSearchRRPPrice" style="text-align:right"><div id="divOffer">RRP #Html.Raw(#Model.dtcurrentCurrency.Rows[0]["HTMLENTITY"])</div></td>
<td class="divSearchRRPPrice" style="width:70%; text-align:left"><div id="PriceDiv2"></div></td>
</tr>
</table>
</div>
<table style="width:100%">
<tr>
#if (#Model.SizeCount == true)
{
<td><label>Size: </label></td>
<td>
<span style="display:none;">
#Html.DropDownList("CustomList", ViewData["customList"] as SelectList, new { #id = "ddPrice" })
</span>
#Html.Raw(#Html.DropDownList("SizeList", ViewData["SizeList"] as SelectList, new { #id = "ddsize1" }))
</td>
}
else
{
if (#Model.dtProduct.Rows[0]["Size"] != null)
{
if (#Model.dtProduct.Rows[0]["Size"].ToString().Length > 0)
{
<td colspan=2><p><label>Size:</label>#Model.dtProduct.Rows[0] ["Size"]</p></td>
}
}
}
</tr>
</table>
<br />
Change currency
<br />
#Html.Hidden("ProductId", #Model.dtProduct.Rows[0]["ProductId"])
#Html.Hidden("ProductPriceId", #Model.dtProduct.Rows[0]["ProductPriceId"])
#Html.Hidden("ProductPrice", #APrice)
#Html.Hidden("tempPrice", null, new { #id = "tempPrice" })
#Html.Hidden("ddlSize",null, new { #id="ddlSizeId" })
<input type="submit" value="Add to Shopping Cart" data-theme="f" />
}
javascript/jquery:
<script type="text/javascript">
$('#ddsize1').change(function () {
var selectedValue = $('option:selected', $(this)).val();
var selectedText = $('#ddsize1 option:selected').text();
document.getElementById('ddlSizeId').value = selectedText;
var offerPrice = #Model.offerPrice;
if( offerPrice == 0)
{
var price = selectedValue * #Model.dtcurrentCurrency.Rows[0]["EXCHANGERATE"];
$("#priceTable1").hide();
document.getElementById('tempPrice').value=price.toFixed(2);
document.getElementById('PriceDiv1').innerHTML = price.toFixed(2);
$("#divPrice1").show();
$("#divOffer").hide();
// return false;
}
else{
var el = document.getElementById("ddPrice");
for(var i=0; i<el.options.length; i++)
{
var txtPrice = el.options[i].text;
var priceMatch = selectedValue * 1;
var MatchPrice = priceMatch.toFixed(2);
if ( txtPrice == MatchPrice ) {
$("#priceTable1").hide();
var txtOfferPrice = el.options[i].value * #Model.dtcurrentCurrency.Rows[0]["EXCHANGERATE"];
var txtOriginalPrice = el.options[i].text * #Model.dtcurrentCurrency.Rows[0]["EXCHANGERATE"];
document.getElementById('tempPrice').value = txtOfferPrice.toFixed(2);
document.getElementById('PriceDiv1').innerHTML = txtOfferPrice.toFixed(2);
document.getElementById('PriceDiv2').innerHTML = txtOriginalPrice.toFixed(2);
$("#divPrice1").show();
}
}
}
});
</script>
in Model:
public string tempPrice {get;set;}
Now you can access the your attributes in controller. i hope it will help full to your problem.

Categories

Resources