The error shows as below:
System.Web.HttpCompileException:
'C:\Users\MEDADUWA\source\repos\CapeXPro\CapeXPro\Views\FAWizard_AddAsset.cshtml(43):
error CS1579: foreach statement cannot operate on variables of type
'FAInfo' because 'FAInfo' does not contain a public definition for
'GetEnumerator''
My ViewModel Look like this:
namespace DAL.Entities
{
public class FAInfo
{
public int WizardId { get; set; }
public string WizardType { get; set; }
public Step2 Step2 { get; set; }
public List<Step2> ListStep2 { get; set; }
public int Status { get; set; }
}
public class Step2
{
public int assetId { get; set; }
public string assetCode { get; set; }
public int assetCategoryId { get; set; }
public int assetTypeId { get; set; }
public int branchId { get; set; }
public int? ccenterId { get; set; }
public string description { get; set; }
public double cost { get; set; }
public double? vat { get; set; }
public double? vatRec { get; set; }
public double? nbt { get; set; }
public double bookValue { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? ModifiedOn { get; set; }
public string ModifiedBy { get; set; }
public int Status { get; set; }
public InvoiceEntities Invoice { get; set; }
public List<Step2> ListAssets { get; set; }
public List<tbl_assetcategory> ListCategories { get; set; }
public List<tbl_branch> ListBranches { get; set; }
public List<tbl_costcenter> ListDepartments { get; set; }
}
}
This is my Controller:
namespace CapeXPro.Controllers
{
[SessionExpire]
public class FAWizardController : Controller
{
UnitOfWork _unitOfWork = new UnitOfWork();
readonly CommonUtilities _commonService = new CommonUtilities();
#region Main View
FAInfo FAInfoComponent(FAInfo model = null)
{
try
{
//var existjournaldepreciation = _unitOfWork.JournalDepreciationRepository.GetAll(x => x.Id == 1 && x.Status != (int)StatusEnum.Delete).FirstOrDefault();
if (model == null)
{
model = new FAInfo()
{
Status = (int)StatusEnum.Active,
};
}
return model;
}
catch (Exception ex)
{
throw ex;
}
}
// GET: FAWizard
public ActionResult FAWizard()
{
return View("FAWizard", FAInfoComponent());
}
#endregion
#region Add Or Edit Step2
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult Step2(FAInfo AssetData, string BtnPrevious, string BtnNext)
{
try
{
var action = string.Empty;
var before = string.Empty;
var after = string.Empty;
AssetData = FAInfoComponent(AssetData);
if (BtnPrevious != null)
{
FAInfo InvObj = new FAInfo();
InvObj.Step1.InvoiceId = AssetData.Step2.Invoice.InvoiceId;
InvObj.Step1.InvoiceNo = AssetData.Step2.Invoice.InvoiceNo;
InvObj.Step1.PoNo = AssetData.Step2.Invoice.PoNo;
return PartialView("_AddInvoice", InvObj);
}
if (BtnNext != null)
{
if (ModelState.IsValid)
{
var existObj = _unitOfWork.AssetRepository.GetAll(x => x.assetId == AssetData.Step2.assetId && x.Status != (int)StatusEnum.Delete).FirstOrDefault();
if (existObj == null)
{
tbl_asset asset = new tbl_asset()
{
assetId = AssetData.Step2.assetId,
assetCode = AssetData.Step2.assetCode,
assetCategoryId = AssetData.Step2.assetCategoryId,
CreatedBy = System.Web.HttpContext.Current.Session[SessionsEnum.UserId.ToString()].ToString(),
CreatedOn = DateTime.Now,
Status = Convert.ToInt32(AssetData.Status)
};
_unitOfWork.AssetRepository.Insert(asset);
//_unitOfWork.Save();
//int id = department.CcId;
action = ActionType.Insert;
before = null;
after = asset.assetId + "," +
asset.assetCode + "," +
asset.assetCategoryId + "," +
asset.Status + "," +
asset.CreatedBy + "," +
asset.CreatedOn + "," +
asset.ModifiedBy + "," +
asset.ModifiedOn;
}
else
{
FAInfo AssetObj = new FAInfo();
AssetObj.Step2.assetId = AssetData.Step2.assetId;
AssetObj.Step2.assetCode = AssetData.Step2.assetCode;
AssetObj.Step2.assetCategoryId = AssetData.Step2.assetCategoryId;
AssetObj.Step2.ModifiedBy = System.Web.HttpContext.Current.Session[SessionsEnum.UserId.ToString()].ToString();
AssetObj.Step2.ModifiedOn = DateTime.Now;
AssetObj.Step2.Status = Convert.ToInt32(AssetData.Status);
_unitOfWork.AssetRepository.Update(existObj);
action = ActionType.Update;
before = null;
after = existObj.assetId + "," +
existObj.assetCode + "," +
existObj.assetCategoryId + "," +
existObj.Status + "," +
existObj.CreatedBy + "," +
existObj.CreatedOn + "," +
existObj.ModifiedBy + "," +
existObj.ModifiedOn;
}
if (_unitOfWork.Save() > 0)
{
//Update Log Table
AuditLog.SystemLog(Tables.AssetTable, action, before, after);
TempData["message"] = Messages.Success;
ModelState.Clear();
return View("AddDepreciation", new FADepreciationEntities());
}
else
{
TempData["message"] = Messages.Failed;
return PartialView("_AddAsset", AssetData);
}
}
return PartialView("_AddAsset", AssetData);
}
return View();
}
catch (Exception ex)
{
TempData["message"] = Messages.Exception + ex.Message;
return PartialView("_AddAsset", AssetData);
}
}
#endregion
}
}
This is my Partial View
#model DAL.Entities.FAInfo
#using DAL.Enums
#using (Html.BeginForm("Step2", "FAWizard", FormMethod.Post, new { #class = "form-horizontal form-label-left", role = "form", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(m => m.Step2.assetId)
<!-- Editable table -->
<div class="card">
<div class="card-body">
<div id="table" class="table-editable">
<span class="table-add float-right mb-3 mr-2">
<a href="#!" class="text-success">
<i class="fas fa-plus fa-2x" aria-hidden="true"></i>
</a>
</span>
<table id=""
class="table table-striped table-hover table-sm table-bordered text-center">
<thead>
<tr>
<th class="text-center">Line No</th>
<th class="text-center">Asset Code</th>
<th class="text-center">Asset Class</th>
</tr>
</thead>
<tbody>
#foreach (DAL.Entities.FAInfo asset in Model)
{
<tr>
<td>1</td>
<td>#asset.Step2.assetCode</td>
<td>#asset.Step2.ListCategories</td>
<td>
<span class="table-remove">
<button type="button"
class="btn btn-danger btn-rounded btn-sm my-0">
Remove
</button>
</span>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
}
This is my MasterView:
#model DAL.Entities.FAInfo
#using DAL.Enums
#{
ViewBag.Title = "FAWizard";
}
<div class="right_col" role="main">
<div class="full-height">
<div class="clearfix"></div>
<div class="row">
<div class="col-md-12 col-sm-12 col-xs-12">
<div class="x_panel">
<div class="x_title">
<h2>Fixed Assets Capitalization <small>CapeXPro</small></h2>
<div class="clearfix"></div>
</div>
<div class="x_content">
<form class="form-horizontal form-label-left" novalidate>
<p>
For Fixed asset registration - CapeXPro | Union Bank of Colombo
</p>
<span class="section">Fixed Asset Info</span>
<!-- Smart Wizard -->
<p>Proceed with the given steps</p>
<div id="wizard" class="form_wizard wizard_horizontal">
<ul class="wizard_steps">
<li>
<a href="#step-1">
<span class="step_no">1</span>
<span class="step_descr">
Step 1<br />
<small>Invoice and Insurance Details</small>
</span>
</a>
</li>
<li>
<a href="#step-2">
<span class="step_no">2</span>
<span class="step_descr">
Step 2<br />
<small>Asset Details</small>
</span>
</a>
</li>
</ul>
<div id="step-1">
#{Html.RenderPartial("_AddInvoice", Model);}
</div>
<div id="step-2">
#{Html.RenderPartial("_AddAsset", Model);}
</div>
</div>
<!-- End SmartWizard Content -->
</form>
</div>
</div>
</div>
</div>
</div>
</div>
System.Web.HttpCompileException: 'C:\Users\MEDADUWA\source\repos\CapeXPro\CapeXPro\Views\FAWizard_AddAsset.cshtml(43): error CS1579: foreach statement cannot operate on variables of type 'FAInfo' because 'FAInfo' does not contain a public definition for 'GetEnumerator''
This error is thrown because in your partial view FAWizard_AddAsset you're trying to iterate your model like this #foreach (DAL.Entities.FAInfo asset in Model). This assumes that Model is an enumerable of FAInfo, like a List<FAInfo> but apparently it's a FAInfo.
Judging by your code I think there's no multiples of FAInfo, but within your FAInfo there's a List<ListStep2>. If you want to iterate that then change your #foreach into this:
#foreach (DAL.Entities.Step2 asset in Model.ListStep2)
In your #model statement you are using a single instance. This is useful for Details and Edit views of single items. To iterate over entities in a view, you can make the model an IEnumerable of MyClass like so:
#model IEnumerable<DAL.Entities.FAInfo>
Related
I'm only starting my adventure with programming, and currently im working on a e-commerce type of aplication in mvc. Recently i tried to make it possible to apply more then one photo and since then i have problems with controller that after clicking on the card was redirecting user to the product page. After click the error appears "System.InvalidOperationException: 'Nullable object must have a value.'" and it points to the values that have "null" value in database, but are not required and before it worked well, also it started showing a page with information that controller could not be found.
Below im showing my code. Thank you everyone in advance.
View
#model roomie.Models.Adviewmodel
#Styles.Render("~/Content/view_ad.css")
#Styles.Render("~/Content/layout.css")
<meta name="viewport" content="width=device-width" />
<title>ViewAd</title>
<div class="add-container">
<div class="add">
<div class="add_title">
<div> <p2> #Model.pro_name </p2> </div>
<div> <p3> AD-ID: #Model.pro_id </p3> </div>
</div>
<div class="pro_image_container">
<div class="pro_image">
#foreach (var image in Model.pro_img_path)
{
<img src="#Url.Content(image)" alt="Image" />
}
</div>
</div>
<div class="add_description">
<p4> Opis: </p4>
<p> #Model.pro_description</p>
</div>
<div class="add_details">
<table class="add_basic_info">
<tr> <td style="font-weight: bold;"> Cena: </td> <td> #Model.pro_price </td> </tr>
<tr> <td style="font-weight: bold;"> Kategoria: </td> <td> #Model.pro_type </td> </tr>
<tr> <td style="font-weight: bold;"> Adres: </td> <td> #Model.nazwa_miasta, #Model.pro_address_street #Model.pro_address_building_num, Piętro: #Model.pro_address_floor </td></tr>
<tr> <td style="font-weight: bold;"> Kontakt: </td> <td> #Model.user_contact </td> </tr>
</table>
<div> <p4> Co w mieszkaniu: </p4></div>
<div class="bool_info">
<div class="icon">
#if (#Model.pro_TV == true)
{
<img src="~/Content/img_icons/tv.png" />
}
</div>
<div class="icon">
#if (#Model.pro_ac == true)
{
<img src="~/Content/img_icons/ac.png" />
}
</div>
<div class="icon">
#if (#Model.pro_elevator == true)
{
<img src="~/Content/img_icons/elevator.png" />
}
</div>
<div class="icon">
#if (#Model.pro_handicapped == true)
{
<img src="~/Content/img_icons/hcp.png" />
}
</div>
<div class="icon">
#if (#Model.pro_internet == true)
{
<img src="~/Content/img_icons/internet.png" />
}
</div>
<div class="icon">
#if (#Model.pro_parking == true)
{
<img src="~/Content/img_icons/parking.png" />
}
</div>
<div class="icon">
#if (#Model.pro_pet == true)
{
<img src="~/Content/img_icons/pet.png" />
}
</div>
<div class="icon">
#if (#Model.pro_smoking == true)
{
<img src="~/Content/img_icons/smoking.png" />
}
</div>
</div>
</div>
</div>
</div>
<div class="user_data">
#if (Convert.ToInt32(Session["user_id"]) == Convert.ToInt32(Model.pro_fk_user))
{
#Html.ActionLink("Close this Ad", "DeleteAd", new { #class = "button", id = Model.pro_id })
}
else
{
<div class="user_data">
<p> Ogłoszenie opublikowane przez: </p>
<div class="data">
<div class="user_photo">
#if (String.IsNullOrEmpty(Model.user_image))
{
<img src="~/Content/img_icons/user.png" />
}
else
{
<img src="#Url.Content(#Model.user_image)" />
}
</div>
<div class="user_info">
<table class="info">
<tr> <td> Użytkownik: </td> <td> #Model.user_name </td></tr>
<tr> <td> Kontakt: </td> <td> #Model.user_contact </td></tr>
<tr> <td> O użytkowniku: </td> <td> #Model.user_description</td></tr>
</table>
<div class="user_icons">
<div class="icon">
#if (Model.user_smoke == true)
{
<img src="~/Content/img_icons/smoking.png" />
}
</div>
<div class="icon">
#if (Model.user_pet == true)
{
<img src="~/Content/img_icons/pet.png" />
}
</div>
</div>
</div>
</div>
</div>
}
</div>
Model
namespace roomie.Models
{
public class Adviewmodel
{
public int pro_id { get; set; }
public string pro_name { get; set; }
public string pro_image { get; set; }
public string pro_address_street { get; set; }
public int pro_address_building_num { get; set; }
public int pro_address_floor { get; set; }
public int pro_price { get; set; }
public string pro_description { get; set; }
public string pro_type { get; set; }
public int pro_room_size { get; set; }
public int pro_room_num { get; set; }
public int pro_bathroom_num { get; set; }
public int pro_roommates { get; set; }
public string pro_room_gender { get; set; }
public bool pro_TV { get; set; }
public bool pro_internet { get; set; }
public bool pro_ac { get; set; }
public bool pro_parking { get; set; }
public string pro_heating { get; set; }
public bool pro_elevator { get; set; }
public bool pro_balcony { get; set; }
public bool pro_handicapped { get; set; }
public bool pro_smoking { get; set; }
public bool pro_pet { get; set; }
public int pro_prefe_gender { get; set; }
public int pro_fk_user { get; set; }
public int user_id { get; set; }
public string user_name { get; set; }
public string user_image { get; set; }
public string user_contact { get; set; }
public string user_description { get; set; }
public bool user_smoke { get; set; }
public bool user_pet { get; set; }
public int pro_fk_address_city { get; set; }
public string nazwa_miasta { get; set; }
public string nazwa_województwa { get; set; }
public IEnumerable<string> pro_img_path { get; set; }
public IEnumerable<string> pro_img_fk_pro_id { get; set; }
}
}
Controller
public ActionResult ViewAd(int id)
{
Adviewmodel ad = new Adviewmodel();
tbl_product p = db.tbl_product.Where(x => x.pro_id == id).SingleOrDefault();
ad.pro_id = p.pro_id;
ad.pro_name = p.pro_name;
//ad.pro_fk_images = p.pro_fk_images;
//ad.pro_fk_address_city = p.pro_fk_address_city;
ad.pro_address_street = p.pro_address_street;
ad.pro_address_building_num = (int)p.pro_address_building_num;
ad.pro_address_floor = (int)p.pro_address_floor;
ad.pro_price = (int)p.pro_price;
ad.pro_description = p.pro_description;
ad.pro_type = p.pro_type;
ad.pro_room_size = (int)p.pro_room_size;
ad.pro_room_num = (int)p.pro_room_num;
ad.pro_roommates = (int)p.pro_roommates;
ad.pro_TV = (bool)p.pro_TV;
ad.pro_internet = (bool)p.pro_internet;
ad.pro_ac = (bool)p.pro_ac;
ad.pro_parking = (bool)p.pro_parking;
ad.pro_heating = p.pro_heating;
ad.pro_elevator = (bool)p.pro_elevator;
ad.pro_balcony = (bool)p.pro_balcony;
ad.pro_handicapped = (bool)p.pro_handicapped;
ad.pro_smoking = (bool)p.pro_smoking;
ad.pro_pet = (bool)p.pro_pet;
//ad.pro_prefe_gender = (int)p.pro_prefe_gender;
tbl_user u = db.tbl_user.Where(x => x.user_id == p.pro_fk_user).SingleOrDefault();
ad.user_name = u.user_name;
ad.user_image = u.user_image;
ad.user_contact = u.user_contact;
ad.pro_fk_user = u.user_id;
tbl_wojewodztwa_miasta wm = db.tbl_wojewodztwa_miasta.Where(x => x.id == p.pro_fk_address_city).SingleOrDefault();
ad.nazwa_miasta = wm.nazwa_miasta;
ad.nazwa_województwa = wm.nazwa_województwa;
ad.pro_img_path = Directory.EnumerateFiles(Server.MapPath("~/ Content / user_upload")).Select(x => "~/ Content / user_upload" + Path.GetFileName(x));
return View(ad);
}
Okay, so i solved my issue, i don't know will it be any help to someone.
In the Model and Controller i added the "?" to the int values that were not required.
i have selectList with multiple attr which is filled through cascading(on select a company i just show selected Company Models) Now i want to allow user to select multiple models such that on select, item should add in c# list and display in page and then allow user to select more of any other company.Picture attached
Following is my code.
OrderViewModel
public class OrderViewModel
{
[Display(Name ="Order ID")]
public int order_id { get; set; }
[Required]
public string cus_name { get; set; }
public string cus_phone { get; set; }
public System.DateTime Date { get; set; }
[DataType(DataType.Date)]
public System.DateTime Date { get; set; }
public int Amount { get; set; }
public List<Products> Products { get; set; }
}
i want to bind selected Item in 'Products' List of OrderViewModel which will be send to server with Further fields.
Products
public class Products
{
public int id { get; set; }
public int modelId { get; set; }
public int Phoneid { get; set; }
public int Quantity { get; set; }
public double price { get; set; }
public bool isSelected { get; set; }
public int order_id { get; set; }
}
Razor View
<div class="form-group row">
<label class="control-label col-6">Company Name</label>
<div class="col-12">
<select id="CompanyId" class="custom-select mr-sm-2"
asp-items="#(new SelectList( #ViewBag.Companies,"Phoneid","Com_name"))">
<option value="">Please Select</option>
</select>
</div>
<span class="text-danger"></span>
</div>
<div class="form-group row">
<label class="control-label col-6"></label>
<div class="col-12">
<select id="modelId" multiple class="custom-select mr-sm-2"
asp-items="#(new SelectList(string.Empty,"modelId","model_name","--Select--"))">
<option value="">Please Select</option>
</select>
</div>
<span class="text-danger"></span>
</div>
what i have tried yet to add item in list
<script>
$("#modelId").change(function () {
var list = #(Model.Products);
let item = $(this).children("option:selected").val();
list.forEach(x => {
if (x.modelId != item) {
#{
Products products = new Products()
{
isSelected=true,
modelId= item,
};
Model.Products.Add(products);
}
}
});
})
#for (int i = 0; i < Model.Products.Count; i++)
{
}
</script>
I display all selected product throught partial view now i just want to send these selected products along with Quanity and Price of each to Server
Here is a working demo like below:
Model:
public class Model
{
[Key]
public int modelId { get; set; }
[Display(Name = "Model Name")]
public string model_name { get; set; }
public int Phoneid { get; set; }
public IList<Products> Products { get; set; }
}
public class Company
{
[Key]
public int Phoneid { get; set; }
[Display(Name = "Company Name")]
public string Com_name { get; set; }
}
public class Products
{
public int id { get; set; }
public int modelId { get; set; }
public int Phoneid { get; set; }
public int Quantity { get; set; }
public double price { get; set; }
public bool isSelected { get; set; }
public int order_id { get; set; }
}
View(Index.cshtml):
#model Products
<div>
<div style="float:left;width:40%">
<form id="form">
<div class="form-group row">
<label>Company Name</label>
<div class="col-12">
<select id="CompanyId" asp-for="Phoneid" class="custom-select mr-sm-2"
asp-items="#(new SelectList( #ViewBag.Companies,"Phoneid","Com_name"))">
<option value="">Please Select</option>
</select>
</div>
</div>
<div class="form-group row">
<label>Model Name</label>
<div class="col-12">
<select id="modelId" multiple class="custom-select mr-sm-2" name="modelId"
asp-items="#(new SelectList(string.Empty,"modelId","model_name","--Select--"))">
<option value="">Please Select</option>
</select>
</div>
</div>
<div>
<input type="button" id="saveBtn" value="Save" />
</div>
</form>
</div>
<div style="float:right;width:60%">
<h5>Products</h5>
<div id="products"></div>
</div>
</div>
#section Scripts
{
<script>
$(function () {
$('#CompanyId').change(function () {
var data = $("#CompanyId").val();
console.log(data);
$.ajax({
url: '/Home/GetModel?Phoneid=' + $("#CompanyId").val(),
type: 'Get',
success: function (data) {
var items = "<option value='0'>Select</option>";
$.each(data, function (i, item) {
items += "<option value='" + item.value + "'>" + item.text + "</option>";
});
$('#modelId').html(items);
}
})
});
$('#saveBtn').click(function () {
$.ajax({
url: '/Home/GetProduct?Phoneid=' + $("#CompanyId").val() + "&modelId=" + $('#modelId').val(),
type: 'Post',
success: function (data) {
$('#products').html(data);
}
})
})
})
</script>
}
Partial View(_Partial.cshtml):
#model IEnumerable<Products>
<table class="table">
<tbody>
#foreach (var item in Model)
{
<tr>
<td>check</td>
<td>
<input asp-for="#item.isSelected" />
</td>
<td>Product Id</td>
<td>
#Html.DisplayFor(modelItem => item.id)
</td>
</tr>
<tr>
<td>Quantity</td>
<td>
#Html.DisplayFor(modelItem => item.Quantity)
</td>
<td>Price</td>
<td>
#Html.DisplayFor(modelItem => item.price)
</td>
</tr>
}
</tbody>
</table>
Controller:
public class HomeController : Controller
{
private readonly MvcProj3Context _context;
public HomeController(MvcProj3Context context)
{
_context = context;
}
public IActionResult Index()
{
ViewBag.Companies = _context.Company.ToList();
return View();
}
public JsonResult GetModel(int Phoneid)
{
List<Model> model = new List<Model>();
model = (from m in _context.Model
where m.Phoneid == Phoneid
select m).ToList();
return Json(new SelectList(model, "modelId", "model_name"));
}
[HttpPost]
public IActionResult GetProduct(int Phoneid, string[] modelId)
{
var data = new List<Products>();
var ids = modelId[0].Split(',');
foreach(var item in ids)
{
var id = int.Parse(item);
//guess the modelA in CompanyA contains several products
var product = (from p in _context.Products
where p.Phoneid == Phoneid && p.modelId == id
select p).ToList();
foreach (var pro in product)
{
data.Add(pro);
}
}
return PartialView("_Partial", data);
}
}
Result:
I have a List of objects in my Model, how can I make a form for it?
I want to have select box and number input box to add objects and be able to keep adding more before posting form.
If it was just public Cargo cargo I would just make a select box to choose cargo type and input box for amount and that's it. But it's a list so I want to add as much cargo as I want and then post a form. I already have input fields for address (like city, street etc.) in my form but I'm stuck with this list.
Order model (Form model):
public class Order
{
public int Id { get; set; }
public Address PickUpAddress { get; set; }
public Address DropOffAddress { get; set; }
[...]
public List<Cargo> Cargo { get; set; }
}
Cargo model:
public class Cargo
{
public int Id { get; set; }
public int Amount { get; set; }
public CargoType CargoType { get; set; }
}
My solution
I implemented this function manually without any JS code.
The code is very simple. You can refer to my code here directly.
Solving process
We have to insert the order table before we can insert the cargo table. Otherwise, we can't connect the two tables.
We need these three form models.We use the cargocount field to link the two order pages with the cargo page.
public class CargoViewModel
{
public int OrderId { get; set; }
public int Amount { get; set; }
public string CargoType { get; set; }
//Other use
public int CargoCount { get; set; }
public List<CargoViewModel> Cargos { get; set; }
}
public class OrderViewModel
{
public int OrderId { get; set; }
public string PickUpAddress { get; set; }
public string DropOffAddress { get; set; }
public int CargoCount { get; set; }
public List<CargoViewModel> Cargos { get; set; }
}
public class OrdersViewModel
{
public List<OrderViewModel> Orders { get; set; } = new List<OrderViewModel>();
}
When we create an order page, we need to provide the data of cargocount. When we submit the order page, we will save the existing data to the order table, jump to the cargo page, and generate cargocount input tags.
Next, submit the list form.
Submit page code
<form asp-controller="Order" asp-action="CreateCargo" method="post">
#if (Model.CargoCount != 0)
{
for (int itemCount = 0; itemCount < Model.CargoCount; itemCount++)
{
<div class="row">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<div class="form-group" style="width:300px; height:auto; float:left; display:inline">
<label asp-for="#Model.Cargos[itemCount].Amount" class="control-label"></label>
<input asp-for="#Model.Cargos[itemCount].Amount" class="form-control" />
<span asp-validation-for="#Model.Cargos[itemCount].Amount" class="text-danger"></span>
</div>
<div class="form-group" style="width:300px; height:auto; float:left; display:inline">
<label asp-for="#Model.Cargos[itemCount].CargoType" class="control-label"></label>
<input asp-for="#Model.Cargos[itemCount].CargoType" class="form-control" />
<span asp-validation-for="#Model.Cargos[itemCount].CargoType" class="text-danger"></span>
</div>
</div>
</div>
}
}
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
Background data processing code
[HttpPost]
public async Task<IActionResult> CreateCargo(CargoViewModel model)
{
var orderId = await _context.Order.Select(o => o.OrderId).MaxAsync();
var cargos = model.Cargos;
foreach (var item in cargos)
{
var cargo = new Cargo
{
OrderId = orderId,
Amount = item.Amount,
CargoType = item.CargoType
};
await _context.AddAsync(cargo);
await _context.SaveChangesAsync();
}
return RedirectToAction(nameof(Index));
}
Using JS implementation
We need this form models.
public class OrderAndCargoViewModel
{
public int OrderId { get; set; }
public string PickUpAddress { get; set; }
public string DropOffAddress { get; set; }
public List<CargoViewModel> Cargos { get; set; }
}
Next, submit the table form. Submit page code.
<div style="float:right;">
<table id="tb">
<tr>
<th> <label class="control-label">ID</label></th>
<th> <label asp-for="#Model.Cargos.FirstOrDefault().Amount" class="control-label"></label> </th>
<th><label asp-for="#Model.Cargos.FirstOrDefault().CargoType" class="control-label"></label></th>
</tr>
#{
var countId = 0;
for (var itemCount = 0; itemCount < 3; itemCount++)
{
<tr id="trs">
<td>#(++countId)</td>
<td><input asp-for='#Model.Cargos[itemCount].Amount' class= 'form-control' /></td>
<td><input asp-for='#Model.Cargos[itemCount].CargoType' class='form-control' /></td>
</tr>
}
}
</table>
</div>
<input id="btnAdd" value="Add" type="button" class="btn btn-primary" onclick="btnAddClick()">
JS Code.
#section scripts{
<script src="~/js/jquery-3.4.1/jquery-3.4.1.js" type="text/javascript"></script>
<script src="~/js/jquery-3.4.1/jquery-ui-1.12.1.js" type="text/javascript"></script>
<script src="~/js/jquery-3.4.1/jquery.unobtrusive-ajax.js" type="text/javascript"></script>
<script>
var btnAddClick = function () {
var trLen = $("#tb tr[id='trs']").length;
var $lastTr = $("#tb tr[id='trs']").last();
var tr = "<tr id='trs'>";
tr += "<td>" + (trLen + 1) + "</td>";
tr += "<td><input class='form-control' type='number' data-val='true' data-val-required='The Amount field is required.' id='Cargos_"+trLen+"__Amount' name='Cargos["+trLen+"].Amount' value=''></td>";
tr += "<td><input class='form-control' type='text' id='Cargos_"+trLen+"__CargoType' name='Cargos["+trLen+"].CargoType' value=''>";
tr += "</tr>";
$(tr).insertAfter($lastTr);
}
</script>
}
Controller Code.
[HttpPost]
public async Task<IActionResult> CreateOrderAndCargo(OrderAndCargoViewModel model)
{
var order = new Order()
{
PickUpAddress = model.PickUpAddress,
DropOffAddress = model.DropOffAddress
};
await _context.AddAsync(order);
await _context.SaveChangesAsync();
var orderId = await _context.Order.Select(o => o.OrderId).MaxAsync();
var cargos = model.Cargos;
foreach (var item in cargos)
{
var cargo = new Cargo
{
OrderId = orderId,
Amount = item.Amount,
CargoType = item.CargoType
};
await _context.AddAsync(cargo);
await _context.SaveChangesAsync();
}
return RedirectToAction(nameof(Index));
}
Click here to view source codes.
Reference page
About'#'.
JS operation.
It will solve the problem if you use more than one related model in View pages and give a list parameter in actions..
An example;
View;
<input type="text" name="name" id="name1" />
<input type="text" name="name" id="name2" />
Action
public actionresult post(string [] name)
I'm beginner in asp.net mvc.
I have a product model and I want implement user comments for any product.
I want to show comments as tree for each level.
I use a recursive method in my view to show comments and reply comment but
it cant show reply comments in third level .
The first level terms when replyId is empty displayed. Reply to first comment are displayed first. But the answer of Previous reply does not show in the third level.
Please help me. Thank you so much.
This is my model
namespace Mvc_Shop.Models
{
public class Comment
{
public Comment()
{
this.Children = new HashSet<Comment>();
}
public int Id { set; get; }
public string Body { set; get; }
public System.DateTime CommentDate { get; set; }
public int? ReplyId { get; set; }
public ICollection<Comment> Children { get; set; }
public virtual Comment Reply { set; get; }
public string User_Id { get; set; }
[ForeignKey("User_Id")]
public virtual User User { get; set; }
public int Product_Id { get; set; }
[ForeignKey("Product_Id")]
public virtual Product Product { get; set; }
}
}
This is my view
#helper TreeView(IEnumerable<Mvc_Shop.Models.Comment> Comments)
{
foreach (var item in Comments)
{
<div class="media">
<div class="media-body" id="Comment_#(item.Id)" style="padding: 3px;width: 100%;">
<h4 class="media-heading">
#item.User.UserName
<label class="badge pull-left" style="font-weight: normal">#item.CommentDate.ToString("dddd, dd MMMM yyyy - HH:mm")</label>
</h4>
<div class="clearfix">
#item.Body
</div>
<fieldset id="reply-cmnt-form_#(item.Id)" class="spr-form-review" style="display:none">
<div class="spr-form-review-body">
#Html.LabelFor(model => model.Comment.Body, new { #class = "spr-form-label" })
#Html.TextAreaFor(model => model.Comment.Body, new { #class = "spr-form-input spr-form-input-text", id = "commentbody" + #item.Id })
#Html.ValidationMessageFor(model => model.Comment.Body)
</div>
</fieldset>
<a id="btn-hide-div_#(item.Id)" class="btn btn-xs pull-left btn-primary" style="clear: both; display:none" onclick="opencmntdiv(#item.Id);"> بستن</a>
<a id="btn-send-div_#(item.Id)" class="btn btn-xs pull-left btn-primary" style="clear: both;float:right;display:none" onclick="ReplyComment(#item.Id);"> ارسال پاسخ</a>
<a id="btn-show-div_#(item.Id)" class="btn btn-xs pull-left btn-primary" style="clear: both" onclick="opencmntdiv(#item.Id);"> پاسخ</a>
</div>
</div>
<hr class="clearfix" />
if (item.Children.Any())
{
#TreeView(item.Children)
}
}
}
#TreeView(Model.Comments)
and this is my action
public ActionResult ShowProducts(string ProductName)
{
_dbContext = HttpContext.GetOwinContext().Get<ShopContext>();
var model = new UserCommentViewModel();
if (string.IsNullOrEmpty(ProductName))
{
return RedirectToAction("Index");
}
else
{
model.Products = blproduct.Where(p => p.Name.Trim() == ProductName.Trim()).ToList();
model.Comments = (from u1 in _dbContext.Users
join u2 in _dbContext.Comments
on u1.Id equals u2.User.Id
where u2.ReplyId == null
select new {
Id = u2.Id, Body = u2.Body, CommentDate = u2.CommentDate, User = u1,Children = u2.Children
}).ToList().Select(x => new Comment
{
Id = x.Id, Body = x.Body, CommentDate = x.CommentDate, User = x.User,Children = x.Children
}).ToList();
if (model != null)
{
return View(model);
}
else
{
return RedirectToAction("Index");
}
}
}
Thanks a lot.
I have my order class created, you can make Orders and View the orders. However now I am trying to create a "Returns" page that basically allows the user to enter a return reason and then print the reason/invoice. I have the orders create form however I am not sure how to link the 2 to say This Returns Belongs To This Order all I can do is create a generic return that is linked to nothing. I have set up the relationship Im just not sure how to connect the return to the specific order. I know this is a basic question, I just couldn't find anything online to help me. Im a student and an explanation would be very beneficial as I need to use similar methods to this in other aspects
Here is my controller to view MyOrders and the ReturnsForm
namespace T_shirt_Company_v3.Controllers
{
public class MyOrderController : Controller
{
TshirtStoreDB db = new TshirtStoreDB();
/// <summary>
/// Returns a list of Orders made by the user
/// </summary>
/// <param name="date">choose date period viewing orders</param>
/// <param name="order">Orders being viewed</param>
/// <returns></returns>
[Authorize]
public ActionResult Index(string date, Order order)
{
TshirtStoreDB db = new TshirtStoreDB();
string currentUser = this.User.Identity.GetUserName();
List<T_shirt_Company_v3.ViewModels.MyOrdersViewModel> list = (from o in new TshirtStoreDB().Orders
.Where(o => o.Username == currentUser)
.OrderByDescending(o => o.OrderDate)
.Select(o => new MyOrdersViewModel()
{
OrderId = o.OrderId,
Address = o.Address,
FirstName = o.FirstName,
LastName = o.LastName,
City = o.City,
OrderDate = o.OrderDate,
PostalCode = o.PostalCode,
Total = o.Total,
HasBeenShipped = o.HasBeenShipped,
PostageList = o.PostageList,
Details = (from d in o.OrderDetails
select new MyOrderDetails
{
Colour = d.Product.Colour,
Quantity = d.Quantity,
Title = d.Product.Title,
UnitPrice = d.UnitPrice
}).ToList()
}).ToList() select o).ToList();
if (date != null)
{
DateTime today = DateTime.Now.AddDays(Convert.ToInt32(date) * -1);
return View(list.Where(x => x.OrderDate >= today).ToList());
}
return View(list);
}
public ActionResult ReturnsForm()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ReturnsForm([Bind(Include = "ReturnId,OrderId,ReturnDate,Reason")] returnDetails returnDetails)
{
if (ModelState.IsValid)
{
if (returnDetails != null)
{
returnDetails.ReturnDate = DateTime.Now;
}
db.returnDetails.Add(returnDetails);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(returnDetails);
}
}
}
and my MyOrders view
#model List<T_shirt_Company_v3.ViewModels.MyOrdersViewModel>
#{
ViewBag.Title = "My Orders";
}
<style>
table, th, td {
border: 0px solid black;
border-collapse: collapse;
margin-bottom:50px;
padding-bottom:50px;
}
th, td {
padding: 5px;
border-spacing: 10px;
text-align: center;
}
</style>
<center>
<h1>My Orders</h1>
<br />
#using (Html.BeginForm("Index", "MyOrder", FormMethod.Get))
{
<text>Orders Made </text><select id="date" name="date">
<option value="9999">All Orders</option>
<option value="1">In the last day</option>
<option value="7">In the last week</option>
<option value="30">In the last month</option>
<option value="365">In the last year</option>
</select>
<input type="submit" name="submit" value="Search" />
}
<table>
#foreach (var m in Model)
{
<tr>
#*<td style="background-color: #ffffe0"><b>Order Status</b> <br />#ViewBag.ShippedMessage</td>*#
<td style="background-color: #ffffe0"><b>Order Status</b> <br />#(m.HasBeenShipped ? "Order has been shipped" : "Order is being processed") <br /> #ViewBag.PostageStatus</td>
<td style="background-color: #ffffe0"><b>Order Placed</b> <br />#m.OrderDate <br /> #m.PostageList</td>
<td style="background-color: #ffffe0"><b>Dispatched to</b> <br />#m.FirstName #m.LastName</td>
<td style="background-color: #ffffe0"><b>Delivery Address</b><br /> #m.Address <br /> #m.City <br /> #m.PostalCode <br /> </td>
<td style="background-color: #ffffe0"><b>Total Cost</b><br /> £#m.Total</td>
<td style="background-color: #ffffe0"><b>Order Number</b><br /> #m.OrderId</td>
</tr>
foreach (var d in m.Details)
{
<tr>
<td colspan="3" style="text-align: left; background-color:#ADD8E6;"><b>Product Name</b> #d.Title <br /><b>Colour</b> #d.Colour</td>
<td style="background-color: #ADD8E6"><b>Price: </b> £#d.UnitPrice</td>
<td colspan="2" style="background-color: #ADD8E6"><b>Quantity Ordered: </b> #d.Quantity</td>
</tr>
}
<tr><td>#Html.ActionLink("Return Order", "ReturnsForm")</td></tr>
<tr><td></td></tr>
<tr><td></td></tr>
<tr><td></td></tr>
}
</table>
</center>
My ReturnsCreate View
#model T_shirt_Company_v3.Models.returnDetails
#{
ViewBag.Title = "ReturnsForm";
}
<h2>ReturnsForm</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>returnDetails</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Reason, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Reason, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Reason, "", new { #class = "text-danger" })
</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>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Classes
namespace T_shirt_Company_v3.Models
{
//[Bind(Exclude = "OrderId")]
public partial class Order
{
[ScaffoldColumn(false)]
public int OrderId { get; set; }
[ScaffoldColumn(false)]
public System.DateTime OrderDate { get; set; }
[ScaffoldColumn(false)]
[Remote("CheckUserName", "Account")]
public string Username { get; set; }
[Required]
[StringLength(16, ErrorMessage = "Your name is too long")]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Your last name is required.")]
[StringLength(16, ErrorMessage = "Last name is too long.")]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required(ErrorMessage = "Address is required.")]
public string Address { get; set; }
[Required(ErrorMessage = "City is required.")]
public string City { get; set; }
[Required(ErrorMessage = "Postcode is required.")]
[Display(Name = "Post Code")]
public string PostalCode { get; set; }
[Required(ErrorMessage = "Country is required.")]
public string Country { get; set; }
[Required(ErrorMessage = "Phone number is required.")]
public string Phone { get; set; }
[RegularExpression(#"[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage = "Email doesn't look like a valid email address.")]
public string Email { get; set; }
[System.ComponentModel.DataAnnotations.Compare("Email")]
[Display(Name = "Confirm your email address")]
public string EmailConfirm { get; set; }
[ScaffoldColumn(false)]
public string PaymentTransactionId { get; set; }
[ScaffoldColumn(false)]
public bool HasBeenShipped { get; set; }
[ScaffoldColumn(false)]
//[ReadOnly(true)]
public decimal Total { get; set; }
[Required]
[Range(0, 2, ErrorMessage = "Select a delivery method")]
public Postage? PostageList { get; set; }
public CardDetails cardDetails { get; set; }
//public List<CardDetails> cardDetails { get; set; }
public List<OrderDetail> OrderDetails { get; set; }
public int ReturnId { get; set; }
public virtual returnDetails returns { get; set; }
}
public enum Postage {[Display(Name = "Standard Delivery - Free")]StandardDelivery, [Display(Name = "First Class Delivery - £5")]FirstClass, [Display(Name = "24 Hour Delivery - £10")]TwentyFourHour }
public class returnDetails
{
[Key]
public int ReturnId { get; set; }
[ScaffoldColumn(false)]
public System.DateTime ReturnDate { get; set; }
[Required]
public string Reason { get; set; }
[ForeignKey("Order")]
public int OrderId { get; set; }
public virtual Order order { get; set; }
}
}
Keys
In the Return class
[ForeignKey("Order")]
public int OrderId { get; set; }
public virtual Order order { get; set; }
In the Order Class
public int ReturnId { get; set; }
public virtual returnDetails returns { get; set; }
In your MyOrders.cshtmlview, you need to generate a link to your ReturnsForm() method and pass the ID of the order
#foreach (var m in Model)
{
....
#Html.ActionLink("Return Order", "ReturnsForm", new { orderID = m.OrderId })
}
and modify the method to
public ActionResult ReturnsForm(int orderID)
{
returnDetails model = new returnDetails()
{
OrderId = orderID
};
return View(model );
}
and then in your ReturnsCreate.cshtml view, include a hidden input for the property
#Html.HiddenFor(m => m.OrderId )
so is value will be bound when you post back the model.
Side note: The code above uses your data model but that is poor practice and you should be using a view model for Returns