Having trouble accessing virtual collection from cshtml razor - c#

I have a class which has a collection of the activity lines of the heder which is a one to many linked by activitylines id.
public class ActivityHeader
{
public int ActivityHeaderId { get; set; } //(int, null)
public DateTime? ActivityDate { get; set; } //(date, null)
public string Name { get; set; } //(nvarchar(350), null)
public DateTime? ActivityEndDate { get; set; } //(datetime, null)
public string ProblemDescription { get; set; }
public string Description { get; set; } //(nvarchar(max), null)
public int? ActivityLinesId { get; set; } //(int, null)
public int? HoursLeftOnProject { get; set; } //(time(7), null)
public int? Status { get; set; } //(nchar(10), null)
public DateTime? CreatedDate { get; set; } //(date, null)
public string CreatedBy { get; set; } //(nvarchar(50), null)
public bool? isActive { get; set; } //(bit, null)
public bool? isDeleted { get; set; } //(bit, null)
public bool? isArchived { get; set; } //(bit, null)
public int? SOP { get; set; } //(nvarchar(50), null)
public int? OnSite { get; set; }
public int? Remote { get; set; }
public int? DepartmentId { get; set; } //(int, null)
public string EmployeeName { get; set; } //(nvarchar(301), null)
[ForeignKey("StaffId")]
public int? StaffId { get; set; }
public virtual StaffMembers StaffMembers { get; set; }
public ICollection<ActivityLines> ActivityLines { get; set; }
}
Activity Lines classs
public class ActivityLines
{
[Key]
public int ActivityLineId { get; set; } //(int, not null)
public int ActivitiyHeadId { get; set; } //(int, null)
public string Description { get; set; } //(nvarchar(max), null)
public string Notes { get; set; } //(nvarchar(max), null)
public DateTime StartTime { get; set; } //(time(7), null)
public DateTime EndTime { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; } //(time(7), null)
public int? StaffMemeber { get; set; } //(int, null)
public bool? isActive { get; set; } //(bit, null)
public bool? isDeleted { get; set; } //(bit, null)
public string CreatedBy { get; set; } //(nvarchar(50), null)
public DateTime? CreatedDate { get; set; } //(date, null)
public int? Status { get; set; } //(int, null)
}
However as you see it not allowing me to link without going to the first record using linq what is the best practise in being able to reference the lines correclty.
#model ActivityTrackerDal.ViewModels.ActivityEditViewModal
<div class="container py-5">
<div class="row">
<div class="col-md-10 mx-auto">
<form>
<div class="form-group row">
<div class="col-sm-9">
<label for="inputFirstname">Activty Name</label>
<input type="text" class="form-control" id="inputFirstname" placeholder="Activity name">
</div>
</div>
<div class="form-group row">
<div class="col-sm-3">
<label for="inputLastname" class="form-control">Activity Start Date</label>
#Html.Kendo().DateTimePickerFor(model => model.ActivityDate)
</div>
<div class="col-sm-3">
<label for="inputLastname" class="form-control">Activity End Date</label>
#Html.Kendo().DateTimePickerFor(model => model.ActivityEndDate)
</div>
</div>
<div class="form-group row">
<div class="col-sm-3">
<label for="inputLastname" class="form-control">Location</label>
#foreach (var item in (SelectList)ViewBag.Location)
{
#Html.RadioButtonFor(model => model.OnSite, item.Value, false)
<label class="control-label">#item.Text</label>
}
</div>
</div>
<div class="form-group row">
<div class="col-md-10">
<label for="inputLastname" class="form-control">Description</label>
#Html.TextAreaFor(model => model.Description, new { #class = "whatever-class", #cols = 115, #rows = 10 })
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<label for="inputCity">Status </label>
<select asp-for="Status"
class="form-control"
asp-items="#(new SelectList(#ViewBag.ProjectStatusTypes,"LookupCode", "LookupDescription"))"></select>
</div>
<div class="col-sm-3">
<label for="inputState">ActivityType </label>
<select asp-for="ActivityType"
class="form-control"
asp-items="#(new SelectList(#ViewBag.ProjectTypes,"LookupCode", "LookupDescription"))"></select>
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<label for="inputCity">Staff </label>
<select asp-for="StaffID"
class="form-control"
asp-items="#(new SelectList(#ViewBag.ListOfStaff,"StaffID", "FirstName"))"></select>
</div>
<div class="col-sm-3">
<label for="inputState">Hours Left On Project </label>
<label for="inputState"><div class="badge" style="font-size:18px;">26</div> </label>
<label for="projecthours">If Porject hours fall below ten Contact Charlie.</label>
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
#(Html.Kendo().Grid<FuelActivityTrackerDal.Models.ActivityLines>().Name("activityLines")
.Columns(columns =>
{
columns.Bound(p => p.Description).Filterable(false);
columns.Bound(p => p.StartTime).Filterable(false);
columns.Bound(p => p.EndTime).Filterable(false);
columns.Bound(p => p.Status);
columns.Command(command => command.Custom("ViewDetails").Click("showDetails"));
})
.DataSource(dataSource => dataSource
.Ajax()
.Events(events => events.Error("error_handler"))
.Model(model => model.Id(p => p.ActivityLineId))
.Read(read => read.Action("ActivityLines_Read", "Activity"))))
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
</div>
</div>
<button type="button" class="btn btn-primary px-4 float-right">Add Work Item</button>
<button type="button" class="btn btn-primary px-4 float-right">Put Case & Client On Hold</button>
<button type="button" class="btn btn-primary px-4">Cancel</button>
</form>
</div>
</div>
#(Html.Kendo().Window().Name("Details")
.Title("Activity Details")
.Visible(false)
.Modal(true)
.Draggable(true)
.Width(400)
)
<script type="text/x-kendo-template" id="template">
<form method="post" action="#Url.Action("SaveWorkItem", "Activity")">
<div id="details-container">
ActivitiyHeadId
<div class="form-group row">
<div class="col-sm-9">
<label for="inputFirstname">Activty Name</label>
<input type="text" class="form-control" id="inputFirstname" placeholder="Activity name">
</div>
</div>
<div class="form-group row">
<div class="col-md-10">
<label for="inputLastname" class="form-control">Description</label>
#Html.Kendo().TimePickerFor(model => model.ActivityLines.First(), new { #class = "whatever-class", #cols = 115, #rows = 10 })
</div>
</div>
<div class="form-group row">
<div class="col-md-6">
<label for="inputLastname" class="form-control">Start Time</label>
</div>
<div class="col-md-6">
<label for="inputLastname" class="form-control">End Time </label>
</div>
</div>
</div>
<input type="submit" class="btn btn-file px-4" value="Save Work Item" />
<button type="button" class="btn btn-primary px-4">Cancel</button>
</form>
</script>
<script type="text/javascript">
var detailsTemplate = kendo.template($("#template").html());
function showDetails(e) {
e.preventDefault();
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
var wnd = $("#Details").data("kendoWindow");
wnd.content(detailsTemplate(dataItem));
wnd.center().open();
}
</script>
</div>
Its this popup within I am having the issue with being able to reference the the activity lines
<script type="text/x-kendo-template" id="template">
<form method="post" action="#Url.Action("SaveWorkItem", "Activity")">
<div id="details-container">
ActivitiyHeadId
<div class="form-group row">
<div class="col-sm-9">
<label for="inputFirstname">Activty Name</label>
<input type="text" class="form-control" id="inputFirstname" placeholder="Activity name">
</div>
</div>
<div class="form-group row">
<div class="col-md-10">
<label for="inputLastname" class="form-control">Description</label>
#Html.Kendo().TimePickerFor(model => model.ActivityLines.First(), new { #class = "whatever-class", #cols = 115, #rows = 10 })
</div>
</div>
<div class="form-group row">
<div class="col-md-6">
<label for="inputLastname" class="form-control">Start Time</label>
</div>
<div class="col-md-6">
<label for="inputLastname" class="form-control">End Time </label>
</div>
</div>
</div>
<input type="submit" class="btn btn-file px-4" value="Save Work Item" />
<button type="button" class="btn btn-primary px-4">Cancel</button>
</form>
</script>
This is the main block from above I am having the issue with.
<div class="form-group row">
<div class="col-md-10">
<label for="inputLastname" class="form-control">Description</label>
#Html.Kendo().TimePickerFor(model => model.ActivityLines.First(), new { #class = "whatever-class", #cols = 115, #rows = 10 })
</div>
</div>
Do I need to use include here on the ActivityHeader get statement like I have done for the staff?.
public List<ActivityEditViewModal> GetAllActivites()
{
var staffRepo = new StaffRepositry(_db);
List<ActivityHeader> activity = new List<ActivityHeader>();
activity = _db.ActivityHeader.AsNoTracking()
.Include(x => x.StaffMembers)
.ToList();
if (activity != null)
{
List<ActivityEditViewModal> activityDisplay = new List<ActivityEditViewModal>();
foreach (var x in activity)
{
var customerDisplay = new ActivityEditViewModal()
{
ActivityHeaderId = x.ActivityHeaderId,
ActivityDate = x.ActivityDate,
Name = x.Name,
ActivityEndDate = x.ActivityEndDate,
Description = x.Description
};
activityDisplay.Add(customerDisplay);
}
return activityDisplay;
}
return null;
}

Ok So this is what I had to do I had to use the function called include which is explained in this article on Microsoft web site. Its called defered loading and by the reason of this is EF6 used to take forever to load one to many relationships actually a problem i had with an old app as EF6 uses lazy loading which always loaded all one to many relationships now you can load them when you require them.
https://learn.microsoft.com/en-us/ef/core/querying/related-data
public List<ActivityEditViewModal> GetAllActivites()
{
var staffRepo = new StaffRepositry(_db);
List<ActivityHeader> activity = new List<ActivityHeader>();
activity = _db.ActivityHeader.AsNoTracking()
.Include(x => x.StaffMembers)
.Include(x=>x.ActivityLines)
.ToList();
if (activity != null)
{
List<ActivityEditViewModal> activityDisplay = new
List<ActivityEditViewModal>();
foreach (var x in activity)
{
var customerDisplay = new ActivityEditViewModal()
{
ActivityHeaderId = x.ActivityHeaderId,
ActivityDate = x.ActivityDate,
Name = x.Name,
ActivityEndDate = x.ActivityEndDate,
Description = x.Description,
ActivityLines = x.ActivityLines
};
activityDisplay.Add(customerDisplay);
}
return activityDisplay;
}

Related

ModelState Invalid on form submit - IEnumerable<SelectListItem> is required

I have a form that adds a branch, the form has a drop down to select the company name.
I created a viewModel that has the SelectListItem of the companies and the Branch Model
When submit a form, modelState.IsValid equals to false.
reason for that is because CompaniesList is required.
any idea why is it required? how can i overcome this?
Branch model:
public class Branch
{
public int Id { get; set; }
public int CompanyId { get; set; }
[MaxLength(50)]
public string? City { get; set; }
[MaxLength(50)]
public string? BranchName { get; set; }
public DateTime CreatedAt { get; set; }
[MaxLength(100)]
public string? CreatedBy { get; set; }
}
ViewModel:
public class BranchVM
{
public Branch branch { get; set; }
[AllowNull]
public IEnumerable<SelectListItem> CompaniesList { get; set; }
}
Create.cshtml:
#model Click2Lock.Models.BranchVM
<form method="post" enctype="multipart/form-data">
<div class="border p-3 mt-4">
<div class="row pb-2">
<h2 class="text-primary">Create Branch</h2>
<hr/>
</div>
<div class="col-8">
<label asp-for="branch.BranchName">Branch Name</label>
<input asp-for="branch.BranchName" class="form-control"/>
<span asp-validation-for="branch.BranchName" class="text-danger"></span>
</div>
<div class="col-8">
<label asp-for="branch.City">City</label>
<input asp-for="branch.City" class="form-control"/>
<span asp-validation-for="branch.City" class="text-danger"></span>
</div>
<div class="col-8 pb-4">
<div class="form-group row">
<div class="col-4">
<label asp-for="branch.CompanyId">Company</label>
</div>
<div class="col-8">
#Html.DropDownListFor(m => m.branch.CompanyId, Model.CompaniesList , "Select Order",
new { #class = "form-control" })
<span asp-validation-for="branch.CompanyId" class="text-danger"></span>
</div>
</div>
</div>
<div class="col-8">
<input type="hidden" asp-for="branch.CreatedAt" class="form-control" value="#DateTime.Now" />
</div>
<div class="col-8">
<input type="hidden" asp-for="branch.CreatedBy" class="form-control" value=#ViewBag.userName />
</div>
<button type="submit" class="btn btn-primary" style="width:200px">Add New Branch</button>
<a asp-controller="Company" asp-action="Index" class="btn btn-secondary" style="width:150px">
Back To List
</a>
</div>
</form>
create on Controller :
public IActionResult Create()
{
ViewBag.userName = (_unitOfWork.ApplicationUser.GetAll().
Where(q => q.UserName == User.Identity.Name).Select(q => q.FullName)).FirstOrDefault();
BranchVM branchVM = new BranchVM()
{
branch = new Branch(),
CompaniesList = _unitOfWork.Company.GetAll().OrderBy(a=>a.CompanyName).
Select(i => new SelectListItem
{
Text = i.CompanyName,
Value = i.Id.ToString()
})
};
return View(branchVM);
}
//POST
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(BranchVM branchVM)
{
ViewBag.msgCreate = 0;
ViewBag.msgGeneralException = 0;
if (ModelState.IsValid)
{
try
{
_unitOfWork.Branch.Add(branchVM.branch);
_unitOfWork.Save();
ViewBag.msgCreate = 1;
return View(branchVM);
}
catch (Exception ex)
{
ViewBag.msgGeneralException = 1;
return View(branchVM);
}
}
ViewBag.msgGeneralException = 1;
return View(branchVM);
}
One technique is to make it nullable:
public IEnumerable<SelectListItem>? CompaniesList { get; set; }

How to match the value when I use DropDownListFor in a For Loop? .NET MVC RAZOR

Now I get a JsonString from a column of a dbTable, and then I need to map them into the classes I wrote.
The Problem is that, when I use a for loop to map all the value in razor page, it's totally fine when I use #textBoxFor, but #DropDownListFor no.
this is my razor page code.
#model unitManager.Models.VM_PC_Unit_Mstr
#using unitManager.Models
#{
Layout = "~/Views/Shared/_PageLayout.cshtml";
ViewBag.Title = "Edit";
var controller = ViewContext.RouteData.Values["controller"].ToString();
var action = ViewContext.RouteData.Values["action"].ToString();
bool isCreate = action.EndsWith("Create", StringComparison.OrdinalIgnoreCase);
ViewBag.title = isCreate ? "Create" : "Edit";
}
<style>
.menu_item {
background-color:darkgray;
}
.sub_item{
background-color:azure;
}
</style>
<!-- Basic Inputs Validation start -->
<div class="card">
<div class="card-block">
<form id="main" method="post" #*action="/" novalidate=""*#>
#* Course Name *#
<div class="form-group row">
<label class="col-sm-1 col-form-label">Course Name</label>
<div class="col-sm-3">
#if (!isCreate)
{
#Html.TextBoxFor(n => n.unit_id, new { #class = "form-control", #readonly = "true" })
}
else
{
#Html.TextBoxFor(n => n.unit_id, new { #class = "form-control required", #required = "required" })
}
<span class="messages"></span>
</div>
<div>
#Html.ValidationMessageFor(n => n.unit_id, null, new { #class = "text-danger text-center" })
</div>
</div>
#{
if (Model.menu_obj.menus != null)
{
for (var i = 0; i < Model.menu_obj.menus.Count; i++)
{
var item = Model.menu_obj.menus[i];
string menu_id = "menu-" + i;
<div id="#menu_id" class="menu_item">
#* type *#
<div class="form-group row">
<label class="col-md-3 col-form-label">Type</label>
<div class="col-md-9">
<input id="#(menu_id + "-type")" type="text" value="#item.type">
</div>
</div>
#* No *#
<div class="form-group row">
<label class="col-md-3 col-form-label">No</label>
<div class="col-md-9">
<input id="#(menu_id + "-No")" type="text" value="#item.No">
</div>
</div>
#* tittle *#
<div class="form-group row">
<label class="col-md-3 col-form-label">Title</label>
<div class="col-md-9">
<input id="#(menu_id + "-title")" type="text" value="#item.title">
</div>
</div>
#* url *#
<div class="form-group row">
<label class="col-md-3 col-form-label">Url</label>
<div class="col-md-9">
<input id="#(menu_id + "-url")" type="text" value="#item.url">
</div>
</div>
#* subItem *#
<div class="form-group row">
<label class="col-md-3 col-form-label">SubItem</label>
<div class="col-md-9">
#if (item.content != null)
{
for (var j = 0; j < item.content.Count; j++)
{
var subItem = item.content[j];
string sub_id = "m-" + i + "-sub-" + j;
<div class="sub_item">
#* type *#
<div class="form-group row">
<label class="col-sm-3 col-form-label">Type</label>
<div class="col-sm-9">
#Html.TextBoxFor(p => p.menu_obj.menus[i].content[j].type)
#Html.DropDownListFor(p => p.menu_obj.menus[i].content[j].type, ModelSelectList.subType())
</div>
</div>
#* SubNo *#
<div class="form-group row">
<label class="col-sm-3 col-form-label">Intro</label>
<div class="col-sm-9">
<input id="#(sub_id + "-SubNo")" type="text" value="#subItem.SubNo">
</div>
</div>
#* intro *#
<div class="form-group row">
<label class="col-sm-3 col-form-label">Intro</label>
<div class="col-sm-9">
<input id="#(sub_id + "-intro")" type="text" value="#subItem.intro">
</div>
</div>
#* title *#
<div class="form-group row">
<label class="col-sm-3 col-form-label">Title</label>
<div class="col-sm-9">
<input id="#(sub_id + "-title")" type="text" value="#subItem.title">
</div>
</div>
#* shortcut *#
<div class="form-group row">
<label class="col-sm-3 col-form-label">Shortcut</label>
<div class="col-sm-9">
<input id="#(sub_id + "-shortcut")" type="text" value="#subItem.shortcut">
</div>
</div>
#* url *#
<div class="form-group row">
<label class="col-sm-3 col-form-label">Url</label>
<div class="col-sm-9">
<input id="#(sub_id + "-url")" type="text" value="#subItem.url">
</div>
</div>
#* record_timing *#
<div class="form-group row">
<label class="col-sm-3 col-form-label">Record_timing</label>
<div class="col-sm-9">
<input id="#(sub_id + "-recordtime")" type="text" value="#subItem.record_timing">
</div>
</div>
</div>
}
}
</div>
</div>
</div>
}
}
}
<div class="form-group row">
<div class="col-sm-4" style="display:flex;justify-content:flex-end">
<a type="button" class="btn btn-primary" style="color:white;margin:10px;" href="#Url.Action("Index","UnitMgr")">Cancel</a>
<button type="submit" class="btn btn-primary" style="color:white;margin:10px;">Submit</button>
</div>
</div>
</form>
</div>
</div>
<script>
$("div[id ^='menu-']").each(function () {
console.log($(this));
let menu_idx = $(this).attr("id").replace("menu-", "");
console.log(menu_idx);
$("input[id ^= 'm-" + menu_idx + "-sub-']").each(function () {
console.log("sub", $(this), $(this).val());
});
});
$(function () {
$(".select2").select2();
});//document ready
</script>
this is my controller action looks like
[HttpGet]
public ActionResult Menu(string unit_id)
{
VM_PC_Unit_Mstr model= PC_Unit_Mstr.getMenuByunitID(unit_id);
model.menu_obj = JsonConvert.DeserializeObject<Menu>(model.menus_json);
return View(model);
}
and the ViewModel I use
public class VM_PC_Unit_Mstr
{
public string unit_id { get; set; }
public string menus_json { get; set; }
public VM_Menu.Menu menu_obj { get; set; }
}
The problem I met is in here, which I can map the value with TextBoxFor successfully, but not dropDownListFor.
#Html.TextBoxFor(p => p.menu_obj.menus[i].content[j].type)
#Html.DropDownListFor(p => p.menu_obj.menus[i].content[j].type, ModelSelectList.subType())
And this is the result I get in the web page:
This is the simple function I wrote to get the DropDownList :
public static SelectList subType()
{
List<SelectListItem> itemList = new List<SelectListItem>();
SelectListItem itemSpeaking = new SelectListItem
{
Value = "speaking",
Text = "speaking",
};
SelectListItem itemWords = new SelectListItem
{
Value = "words",
Text = "words",
};
SelectListItem itemGame = new SelectListItem
{
Value = "game",
Text = "game",
};
itemList.Add(itemSpeaking);
itemList.Add(itemWords);
itemList.Add(itemGame);
return new SelectList(itemList, "Value", "Text");
}
This is what VM_Menue is:
public class VM_Menu
{
#region MenuList (MenuListInfo)
public class MenuList
{
public string WelcomeImage { get; set; }
public string Menus { get; set; }
}
public class Menu
{
public string welcomeImg { get; set; }
public List<MenuData> menus { get; set; }
}
public class MenuData
{
public string type { get; set; } //video or game or conclusion
public string No { get; set; }
public string title { get; set; }
public string url { get; set; }
public List<SubItemData> content { get; set; }
}
public class SubItemData
{
public string type { get; set; } //speaking or words or game
public string SubNo { get; set; }
public string intro { get; set; }
public string title { get; set; }
public string shortcut { get; set; }
public string url { get; set; }
public float? record_timing { get; set; }
}
#endregion
}
At first, my purpose is to make a two level input/dropDownList tree,
which allows user to edit dynamically, how many parent node user wants,
below the current parent node, how many sub node user wants to edit, create or delete.
So, before this function I want to make, I firstly encounter this dropdownlist mapping problem
with #html function.
Hope the intention and information I offer is enough and clear.
Thank you all for reviewing my codes, it is a mess I know.
I'm afraid you cannot set selected option with #Html.DropDownListFor.You can try to foreach ModelSelectList.subType() and add selected to the option if the value is the same with menu_obj.menus[i].content[j].type:
<select name="menu_obj.menus[#i].content[#j].type">
#foreach (var item in ModelSelectList.subType())
{
if (item.Text == Model.menu_obj.menus[i].content[j].type)
{
<option value=#item.Value selected>#item.Text</option>
}
else
{
<option value=#item.Value>#item.Text</option>
}
}
</select>
ModelSelectList.subType()
#foreach (var item in ModelSelectList.subType()) {
//
}

How to check if model parameter with is >= with repository pattern

In this method, I want to check that the var Total don't exceed the TotalMonths variable.
The problem is, that the var Total is always received with a value of zero, and I don't understad why. Here the method:
/********EDIT MONTH DETAILS POST*********/
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult EditMonthDetail(BudgetViewModel budget)
{
//var Total = budget.FBudget.UnitPrice * budget.FBudget.Quantity;
//budget.FBudget.TotalAmount = budget.FBudget.UnitPrice * budget.FBudget.Quantity;
//var Total = _unitOfWork.Budget.Get(budget.FBudget.TotalAmount);
var Total = BudgetVM.FBudget.TotalAmount;
/*Always retrieved with 0*/
if (Total >= budget.FBudget.TotalMonths)
{
_unitOfWork.Budget.EditMonthDetails(BudgetVM.FBudget);
_unitOfWork.Save();
return RedirectToAction("Success");
}
return RedirectToAction("FailedTotal");
}
Here is how the TotalAmount is implemented in the model:
public float TotalAmount
{
get
{
return UnitPrice * Quantity;
}
}
Here is the View with a form of type Post:
#{
Layout = "~/Views/Shared/_Layout.cshtml";
var title = "title";
}
<form method="post" asp-action="EditMonthDetail">
<div class="row px-2 mx-2">
<div class="col-12">
#if (Model.FBudget.BudgetId != 0)
{
<input type="hidden" asp-for="FBudget.BudgetId" />
title = "Edit Month details";
}
<br />
<h2 class="text-primary">#title</h2>
</div>
<br />
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="FBudget.Jan"></label>
</div>
<div class="col-8">
<input asp-for="FBudget.Jan" class="form-control" />
<span asp-validation-for="FBudget.Jan" class="text-danger"></span>
</div>
</div>
</div>
<br />
<br />
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="FBudget.Feb"></label>
</div>
<div class="col-8">
<input asp-for="FBudget.Feb" class="form-control" />
<span asp-validation-for="FBudget.Feb" class="text-danger"></span>
</div>
</div>
</div>
<br />
<br />
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="FBudget.Mar"></label>
</div>
<div class="col-8">
<input asp-for="FBudget.Mar" class="form-control" />
<span asp-validation-for="FBudget.Mar" class="text-danger"></span>
</div>
</div>
</div>
<br />
<br />
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="FBudget.Apr"></label>
</div>
<div class="col-8">
<input asp-for="FBudget.Apr" class="form-control" />
<span asp-validation-for="FBudget.Apr" class="text-danger"></span>
</div>
</div>
</div>
<br />
<br />
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="FBudget.May"></label>
</div>
<div class="col-8">
<input asp-for="FBudget.May" class="form-control" />
<span asp-validation-for="FBudget.May" class="text-danger"></span>
</div>
</div>
</div>
<br />
<br />
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="FBudget.Jun"></label>
</div>
<div class="col-8">
<input asp-for="FBudget.Jun" class="form-control" />
<span asp-validation-for="FBudget.Jun" class="text-danger"></span>
</div>
</div>
</div>
<br />
<br />
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="FBudget.Jul"></label>
</div>
<div class="col-8">
<input asp-for="FBudget.Jul" class="form-control" />
<span asp-validation-for="FBudget.Jul" class="text-danger"></span>
</div>
</div>
</div>
<br />
<br />
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="FBudget.Ago"></label>
</div>
<div class="col-8">
<input asp-for="FBudget.Ago" class="form-control" />
<span asp-validation-for="FBudget.Ago" class="text-danger"></span>
</div>
</div>
</div>
<br />
<br />
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="FBudget.Sept"></label>
</div>
<div class="col-8">
<input asp-for="FBudget.Sept" class="form-control" />
<span asp-validation-for="FBudget.Sept" class="text-danger"></span>
</div>
</div>
</div>
<br />
<br />
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="FBudget.Oct"></label>
</div>
<div class="col-8">
<input asp-for="FBudget.Oct"class="form-control" />
<span asp-validation-for="FBudget.Oct" class="text-danger"></span>
</div>
</div>
</div>
<br />
<br />
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="FBudget.Nov"></label>
</div>
<div class="col-8">
<input asp-for="FBudget.Nov"class="form-control" />
<span asp-validation-for="FBudget.Nov" class="text-danger"></span>
</div>
</div>
</div>
<br />
<br />
<div class="col-8">
<div class="form-group row">
<div class="col-4">
<label asp-for="FBudget.Dec"></label>
</div>
<div class="col-8">
<input asp-for="FBudget.Dec"class="form-control" />
<span asp-validation-for="FBudget.Dec" class="text-danger"></span>
</div>
</div>
</div>
<br />
<br />
<div class="col-8">
<div class="form-group row">
<div class="col-8 offset-4">
<button type="submit" class="btn btn-primary form-control">Update</button>
</div>
</div>
</div>
</div>
</form>
I also tried to create a GetTotalAmount() method in the repository but it doesn't seems to work.
What am I doing wrong here?
EDIT
Here is the model:
namespace SalesBudget.Models
{
public class FBudget
{
[Key]
public int BudgetId { get; set; }
[Required(ErrorMessage = "Year is required.")]
public int Year { get; set; }
[Required(ErrorMessage = "FoC is required.")]
public string FreeOfCharge { get; set; }
[Required(ErrorMessage = "Currency is required.")]
public string Currency { get; set; }
[Required(ErrorMessage = "Unit price is required.")]
[Display(Name = "Unit Price")]
public float UnitPrice { get; set; }
public int Jan { get; set; }
public int Feb { get; set; }
public int Mar { get; set; }
public int Apr { get; set; }
public int May { get; set; }
public int Jun { get; set; }
public int Jul { get; set; }
public int Ago { get; set; }
public int Sept { get; set;}
public int Oct { get; set; }
public int Nov { get; set; }
public int Dec { get; set; }
public int TotalMonths
{
get
{
return Jan + Feb + Mar + Apr + May
+ Jun + Jul + Ago + Sept + Oct + Nov + Dec;
}
}
[Display(Name = "Month Nr")]
[Required(ErrorMessage = "Month Nr is required.")]
[Range(1, 12, ErrorMessage = "The value must be between 1 and 12!")]
public string MonthNr { get; set; }
[Display(Name = "Unit of Measure")]
[Required(ErrorMessage = "Unit of Measure is required.")]
public string UnitOfMeasure { get; set; }
[Display(Name = "Quantity")]
[Required(ErrorMessage = "Quantity in untis is required.")]
public int Quantity { get; set; }
public float TotalAmount
{
get
{
return UnitPrice * Quantity;
}
}
public string LastUser
{
//automatically set the last user that used the app
get; set;
}
public int ProgramId
{
//automatically set the last sw that used the app
get; set;
}
public DateTime LastUpdate { get; set; } = DateTime.Now;
//FKs
//Access to ItemMaster
[Display(Name = "Item")]
public int ItemMasterId { get; set; }
public ItemMaster ItemMaster { get; set; }
//Access to Company
[Display(Name = "Company")]
public int CompanyId { get; set; }
public Company Company { get; set; }
//Access to LedgerType
[Display(Name = "Scenario")]
public int LedgerTypeId { get; set; }
public LedgerType LedgerType { get; set; }
//Access to Customer
[Display(Name = "Customer")]
public int CustomerId { get; set; }
public Customer Customer { get; set; }
}
}
And here is the ViewModel:
namespace SalesBudget.Models.ViewModels
{
public class BudgetViewModel
{
public FBudget FBudget { get; set; }
public IEnumerable<FBudget> RecordsList { get; set; }
public IEnumerable<SelectListItem> ItemNumberList { get; set; }
public IEnumerable<SelectListItem> ItemDescriptionList { get; set; }
public IEnumerable<SelectListItem> PharmaFormList { get; set; }
public IEnumerable<SelectListItem> ProductGroupList { get; set; }
public IEnumerable<SelectListItem> CompanyList { get; set; }
public IEnumerable<SelectListItem> LedgerTypeList { get; set; }
public IEnumerable<SelectListItem> LedgerScenarioList { get; set; }
public IEnumerable<SelectListItem> CustomerList { get; set; }
public IEnumerable<SelectListItem> LicensingAreaList { get; set; }
public IEnumerable<SelectListItem> YearsList { get; set; }
public IEnumerable<SelectListItem> CurrencyList { get; set; }
}
}
RESOLVED
I forgot to add hidden input fields in the view in order to retrieve the values that I needed:
<div class="col-12">
#if (Model.FBudget.BudgetId != 0)
{
<input type="hidden" asp-for="FBudget.BudgetId" />
<input type="hidden" asp-for="FBudget.Quantity" />
<input type="hidden" asp-for="FBudget.UnitPrice" />
<input type="hidden" asp-for="FBudget.TotalAmount" />
title = "Edit Month details";
}
<br />
</div>
So now when the form is submitted so are the values captured with hidden fields.

Combox causing razor page not to render

I should expect to see a drop down box with items from the staff remembers table but instead my view does not render. This there for makes the page appear broken I was wondering also is their a way to get the error that caused the page not to render correclty.
#model FuelActivityTrackerDal.ViewModels.ActivityEditViewModal
<div class="container py-5">
<div class="row">
<div class="col-md-10 mx-auto">
<form>
<div class="form-group row">
<div class="col-sm-6">
<label for="inputFirstname">Activty Name</label>
#Html.TextBoxFor(model => model.Name, new { #class = "whatever-class", #cols = 10, #rows = 25 })
</div>
<div class="col-sm-3">
<label for="inputLastname">Activity Start Date</label>
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
#Html.TextAreaFor(model => model.Description, new { #class = "whatever-class", #cols = 10, #rows = 25 })
</div>
<div class="col-sm-3">
<label for="inputAddressLine2">HoursLeftOnProject </label>
<input type="text" class="form-control" id="inputAddressLine2" placeholder="HoursLeftOnProject ">
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<label for="inputCity">Status </label>
<input type="text" class="form-control" id="inputCity" placeholder="Status ">
</div>
<div class="col-sm-3">
<label for="inputState">ActivityType </label>
<input type="text" class="form-control" id="inputState" placeholder="ActivityType ">
</div>
<div class="col-sm-3">
<label for="inputPostalCode">SOP</label>
<div class="form-group">
#Html.LabelFor(x => Model.StaffID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-5">
<div class="form-group">
#Html.LabelFor(x => Model.StaffID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-5">
#Html.DropDownListFor(x => Model.StaffID, new SelectList(Model.StaffMemmbers, "Value", "Text"), htmlAttributes: new { #class = "form-control", #id = "Region" })
#Html.ValidationMessageFor(x => x.StaffID, "", new { #class = "text-danger" })
</div>
</div>
</div>
</div>
</div>
</div>
<button type="button" class="btn btn-primary px-4 float-right">Save</button>
<button type="button" class="btn btn-primary px-4 float-right">Cancel</button>
</form>
</div>
</div>
</div>
However I am using the ActivityEditViewModal to populate my view.
public class ActivityEditViewModal
{
public int ActivityHeaderId { get; set; } //(int, null)
public DateTime? ActivityDate { get; set; } //(date, null)
public string Name { get; set; } //(nvarchar(350), null)
public DateTime? ActivityEndDate { get; set; } //(datetime, null)
public string Description { get; set; } //(nvarchar(max), null)
public int? ActivityLinesId { get; set; } //(int, null)
public int? HoursLeftOnProject { get; set; } //(time(7), null)
public int Status { get; set; } //(nchar(10), null)
public int ActivityType { get; set; } //(int, null)
public DateTime? CreatedDate { get; set; } //(date, null)
public string CreatedBy { get; set; } //(nvarchar(50), null)
public bool? isActive { get; set; } //(bit, null)
public bool? isDeleted { get; set; } //(bit, null)
public bool? isArchived { get; set; } //(bit, null)
public int? SOP { get; set; } //(nvarchar(50), null)
public int? DepartmentId { get; set; } //(int, null)
public string EmployeeName { get; set; } //(nvarchar(301), null)
public string StaffName { get; set; }
public int StaffID { get; set; }
public IEnumerable<SelectListItem> StaffMemmbers { get; set; }
}
In my Activity Repo I am populating the staff members are such which you can see from screen shot is working.
public List<ActivityEditViewModal> GetAllActivites()
{
var staffRepo = new StaffRepositry(_db);
List<ActivityHeader> activity = new List<ActivityHeader>();
activity = _db.ActivityHeader.AsNoTracking()
.Include(x => x.StaffMembers)
.ToList();
if (activity != null)
{
List<ActivityEditViewModal> activityDisplay = new List<ActivityEditViewModal>();
foreach (var x in activity)
{
var customerDisplay = new ActivityEditViewModal()
{
ActivityHeaderId = x.ActivityHeaderId,
ActivityDate =x.ActivityDate,
Name=x.Name,
ActivityEndDate = x.ActivityEndDate,
Description = x.Description,
StaffID =(int)x.StaffId
};
customerDisplay.StaffMemmbers = staffRepo.GetStaffs();
activityDisplay.Add(customerDisplay);
}
return activityDisplay;
}
return null;
}
public IEnumerable<SelectListItem> GetStaffs()
{
List<SelectListItem> staff = _db.Staff
.OrderBy(n => n.FirstName)
.Select(n =>
new SelectListItem
{
Value = n.StaffID.ToString(),
Text = n.FirstName + " " + n.LastName
}).ToList();
var staffip = new SelectListItem()
{
Value = null,
Text = "--- select staff ---"
};
staff.Insert(0, staffip);
return new SelectList(staff, "Value", "Text");
}
}
The result is a full broken page. When i take out the code for the dropdown it works fine.

Can't get value from web form for double value in .net core

Have this class:
public class ClientViewModel
{
public long PKID { get; set; }
[Required]
public string Name { get; set; }
public string Unit { get; set; }
public string StreetNumber { get; set; }
public string Street { get; set; }
public string Suburb { get; set; }
public string State { get; set; }
public string PostCode { get; set; }
public string Country { get; set; }
public string DT_RowId { get; set; }
public double Longitude { get; set; }
public double Latitude { get; set; }
public bool IsActive { get; set; }
}
And this code for razor view:
<form method="post" asp-controller="Clients" asp-action="Edit">
<input asp-for="PKID" type="hidden" />
<div class="portlet-body">
<div class="row">
<div class="form-group col-md-2">
<label asp-for="Name">Name:</label>
<input class="form-control input-sm" type="text" placeholder="Name" asp-for="Name">
<span class="help-block has-error" asp-validation-for="Name"></span>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="row physical-row default-row">
<div class="col-md-2">
<label class="control-label">Unit</label>
#Html.TextBoxFor(model => model.Unit, new {placeholder = "Unit", id = "physicalLocationUnit", #class = "form-control input-sm"})
</div>
<div class="col-md-4">
<label class="control-label">Street</label>
#Html.TextBoxFor(model => model.Street, new {placeholder = "PhysicalAddress", id = "physicalLocation", onfocus = "physicalinitialize()", #class = "form-control input-sm"})
</div>
<div class="col-md-2 postcode-box">
<label class="control-label">Post Code</label>
<div>
<input type="text"
tabindex="-1"
class="form-control input-sm" />
</div>
</div>
<div class="col-md-2 lattitude-box">
<label class="control-label" asp-for="Latitude">Latitude</label>
<div>
<input type="text"
tabindex="-1"
class="form-control input-sm" asp-for="Latitude" />
</div>
</div>
<div class="col-md-2 longitude-box">
<label class="control-label" asp-for="Longitude">Longitude</label>
<div>
<input type="text"
tabindex="-1"
class="form-control input-sm" asp-for="Longitude" />
</div>
</div>
</div>
</div>
<div class="form-actions">
<div class="col-md-offset-6 col-md-6">
<button type="submit" class="btn green">Save</button>
<a asp-controller="Clients" asp-action="WorkManage" asp-route-id="#Model.PKID" class="btn green">Add Work</a>
</div>
</div>
</div>
</div>
</form>
In Longitude and Latitude has value for example 1.3 and 2.45 but when i try to call controller method i have just 0 value in this variables. Where i was wrong?
Cheers!
The reason it is not working with a period, is that the default CultureInfo on your server accepts only commas as decimal separators.
You might want to try setting the default culture to one that expects periods as decimal separators.
You could do that in your startup.cs, like this :
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, FinOsDbContext context)
{
app.UseRequestLocalization();
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("*insert culture*");
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("*insert culture*");
}
If you always intend to use a period as decimal separator, regardless of the culture's default, you could specify which decimal separator the culture should use like so :
System.Globalization.CultureInfo customCulture = new CultureInfo("*insert culture*");
customCulture.NumberFormat.NumberDecimalSeparator = ".";
CultureInfo.DefaultThreadCurrentCulture = customCulture;
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;

Categories