List of Items always null MVC 5 - asp.net

I am stuck in this problem and i cannot solve it.
This is my ViewModel
public class AddOrderReceive
{
public string item_name { get; set; }
public DateTime? date_received { get; set; }
public decimal? quantity_received { get; set; }
public bool IsSelected { get; set; }
public decimal? item_rate { get; set; }
}
This is my View
#model List<newtest.Models.AddOrderReceive>
#if(Model != null && Model.Count > 0)
{
for(var i = 0; i < Model.Count; i++)
{
<tr>
#if(Model[i].quantity_remaining == 0)
{
<td colspan="6" class="text-center">Already Sent</td>
}
else
{
#Html.HiddenFor(r => Model[i].item_id)
<td>#Html.CheckBoxFor(r => Model[i].IsSelected)</td>
<td>#Html.EditorFor(r => Model[i].item_rate)</td>
}
</tr>
}
}
And finally, This is my Controller:
[HttpGet]
public ActionResult AddRAR(int? my_id)
{
try
{
var get_items = (from or in db.orders
where or.id == my_id
select new AddOrderReceive()
{
item_name = or.item_name,
quantity_received = or.quantity_receive,
date_received = or.date_receive,
order_receive_id = or.order_receive_id
}).ToList();
foreach(var t in get_items)
{
var get_remain = (from ra in db.order_detail
where ra.contract_id == t.ca_id && ra.order_receive_id == t.order_receive_id
select new
{
consump_quantity = ra.consump_quantity
});
t.quantity_remaining = t.quantity_received - get_remain.Sum(r => r.consump_quantity) ?? t.quantity_received;
}
return View(get_items);
}
catch(Exception ex)
{
}
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddReceivng(List<AddOrderReceive> rc_form)
{
//Some Logic
}
The problem is that whenever I post the form, it is always null. But when I remove this block:
#if(Model[i].quantity_remaining == 0)
{
<td colspan="6" class="text-center">Already Sent</td>
}
It starts working. I don't know what's the problem. I've searched everywhere but still can't figure out the problem here.

Your #if(Model[i].quantity_remaining == 0) block of code, if its executed in the first iteration, means that your collection indexers would not be zero based. The DefaultModelBinder requires that collection indexers start at zero and be consecutive.
You can override this behavior by including a hidden input for the indexer. Note also that an <input> is not a valid child of a <tr>, and should be inside a <td> element.
for(var i = 0; i < Model.Count; i++)
{
#if(Model[i].quantity_remaining == 0)
{
<td colspan="6" class="text-center">Already Sent</td>
}
else
{
<td>
<input type="hidden" name="Index" value="#i" /> // Add this
#Html.HiddenFor(r => r[i].item_id)
#Html.CheckBoxFor(r => r[i].IsSelected)
</td>
<td>#Html.EditorFor(r => r[i].item_rate)</td>
}
}

Related

Get value in View from ICollection to pass an ActionLink parameter

Hellow!, i'm need to be able to get the Id from Compromisos in a View of Gestion. My needs is to get the Id to passess to an ActionLink and go to the View Details of Compromisos
public class Gestion
{
//abbreviated to not make the long post
public Personales Personales { get; set; }
public ICollection<Compromisos> Compromisos { get; set; }
}
and
public class Compromisos
{
//abbreviated to not make the long post
public Personales Personales { get; set; }
public Gestion Gestion { get; set; }
}
Actually i get the Id using this
#foreach (var item in Model.Gestion)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Compromisos)
</td>
</tr>
}
but i want to be able to do this: #Html.ActionLink("Detalle", "Details", "Compromisos", new { id = item.Compromisos}) but doesn't work.
Any suggestions?
Should you be iterating the Model.Compromisos model instead of Model.Gestion? Maybe post your whole model.
#foreach (var item in Model.Compromisos)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Gestion.[Property])
</td>
<td>
#Html.ActionLink("Detalle", "Details", "Compromisos", new { id = item.Compromisos.Id})
</td>
</tr>
}
#Waragi I finally did it.
#foreach (var Item in Model.Compromisos)
{
#if (item.Id == Item.GestionId)
{
<a asp-action="Details" asp-controller="Compromisos" target="_blank" asp-route-id="#Item.Id">Detalle</a>
}
}
In the controller I added .Include(c => c.Compromisos)
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var gestion = await _context.Gestion
.Include(c => c.Compromisos) //before I had included .ThenInclude(c => c.Compromisos)
.SingleOrDefaultAsync(m => m.Id == id);
if (gestion == null)
{
return NotFound();
}
return View(gestion);
}

Viewmodel nested checkbox not binding on post

I have a subscription form that contains a matrix of options. The form can be seen in screenshot Subscription table
I am having trouble with ASP.NET MVC generating appropriate ID's and then on postback having the binder populate the model with the form selections.
The add on name is down the left side and when posted back the collection of SubscriptionInputModel.Addons get populated ok. But SubscriptionInputModel.Addons[i].SubscriptionLevelCombos is null as seen in debug screenshot
The current code is using CheckBoxFor but I've also tried manually generating ID's in format:
#Html.CheckBox("addon[" + a + "].SubscriptionLevelCombo[" + i + "].AddonSelected", addon.SubscriptionLevelCombos[i].AddonSelected)
Neither format has worked and also experimented while debugging but no luck. I would appreciate any ideas. Worst case I assume I would need to read the raw form collection?
I assume the level of nested object shouldn't matter as it is all object path notation and array indexes in html tag names?
Here are snippets of current code to help illustrate what exists.
View Models
public class SubscriptionInputModel
{
//other stuff to come
//....
//add on's, listed down left of table
public List<SubscriptionInputAddonModel> Addons;
}
public class SubscriptionInputAddonModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Note { get; set; }
public List<SubscriptionInputAddonComboModel> SubscriptionLevelCombos { get; set; }
}
public class SubscriptionInputAddonComboModel
{
public int? Id { get; set; }
public decimal? AddonCost { get; set; }
public CostTimeUnitOption? CostTimeUnit { get; set; }
public bool? IsComplimentaryBySubscriptionLevel { get; set; }
public string ComboText { get; set; }
public bool AddonSelected { get; set; }
public int? AddonId { get; set; }
}
SubscriptionController
[Route("identity/subscription")]
// GET: Subscription
public ActionResult Index()
{
SubscriptionInputModel model = new SubscriptionInputModel();
ArrbOneDbContext db = new ArrbOneDbContext();
List<SubscriptionInputAddonModel> addons = Mapper.Map<Addon[], List<SubscriptionInputAddonModel>>(db.Addons.OrderBy(a => a.OrderPosition).ToArray());
model.Addons = addons;
foreach(var addon in model.Addons)
{
var addonCombos = db.Database.SqlQuery<SubscriptionInputAddonComboModel>(#"SELECT SLA.Id, AddonCost, CostTimeUnit, IsComplimentaryBySubscriptionLevel, ComboText, AddonId
FROM SubscriptionLevel L
LEFT OUTER JOIN SubscriptionLevelAddon SLA ON L.Id = SLA.SubscriptionLevelId AND SLA.AddonId = #p0
ORDER BY L.OrderPosition", addon.Id);
addon.SubscriptionLevelCombos = addonCombos.ToList();
}
return View(model);
}
[Route("identity/subscription")]
[ValidateAntiForgeryToken]
[HttpPost]
// POST: Subscription
public ActionResult Index(SubscriptionInputModel model)
{
ArrbOneDbContext db = new ArrbOneDbContext();
List<SubscriptionInputAddonModel> addons = Mapper.Map<Addon[], List<SubscriptionInputAddonModel>>(db.Addons.OrderBy(a => a.OrderPosition).ToArray());
model.Addons = addons;
//debug breakpoint to inspect returned model values
return View();
}
Index.cshtml
#model Identity_Server._Code.ViewModel.Subscription.SubscriptionInputModel
#{
ViewBag.Title = "Subscription";
}
#using (Html.BeginForm("Index", "Subscription", new { signin = Request.QueryString["signin"] }, FormMethod.Post))
{
#Html.ValidationSummary("Please correct the following errors")
#Html.AntiForgeryToken()
...
// ADD ONs ----------------------------------------------------------------------------------
#for (int a = 0; a < Model.Addons.Count; a++)
{
var addon = Model.Addons[a];
<tr>
<td class="text-left">#addon.Name
<div class="SubscriptionItemNote">#addon.Note
#Html.HiddenFor(m => m.Addons[a].Id)
</div>
</td>
#for (int i = 0; i < addon.SubscriptionLevelCombos.Count; i++)
{
<td>
#if (addon.SubscriptionLevelCombos[i].Id.HasValue)
{
if (addon.SubscriptionLevelCombos[i].AddonCost.HasValue && addon.SubscriptionLevelCombos[i].AddonCost.Value > 0)
{
#Html.Raw("<div>+ " + #addon.SubscriptionLevelCombos[i].AddonCost.Value.ToString("0.##") + " / " + #addon.SubscriptionLevelCombos[i].CostTimeUnit.Value.ToString() + "</div>")
}
else if (addon.SubscriptionLevelCombos[i].IsComplimentaryBySubscriptionLevel.HasValue && #addon.SubscriptionLevelCombos[i].IsComplimentaryBySubscriptionLevel.Value)
{
<span class="glyphicon glyphicon-ok"></span>
}
if (!string.IsNullOrEmpty(addon.SubscriptionLevelCombos[i].ComboText))
{
<div>#addon.SubscriptionLevelCombos[i].ComboText</div>
}
if (addon.SubscriptionLevelCombos[i].AddonCost.HasValue && addon.SubscriptionLevelCombos[i].AddonCost.Value > 0)
{
#Html.HiddenFor(m => m.Addons[a].SubscriptionLevelCombos[i].Id)
#Html.CheckBoxFor(m => m.Addons[a].SubscriptionLevelCombos[i].AddonSelected)
}
}
</td>
}
</tr>
}

CheckBox List in ASP.net MVC3

I have an SuperVisor Form and I need to show a list of Employees with checkboxes for selection.
Once I click Save , supervisor information and the selected employees id should be saved to DB.
Which is best option to achieve this ?
Model
public class SelectEmployee
{
public int _EmployeeID;
public string _EmployeeName;
public bool _check;
public int EmployeeID { get { return _EmployeeID; } set { _EmployeeID = value; } }
public string EmployeeName { get { return _EmployeeName; } set { _EmployeeName = value; } }
public bool check { get { return _check; } set { _check = value; } }
}
public class DemoManager
{
public static List<SelectEmployee> GetSelectedEmployee()
{
DemoEntities db = new DemoEntities();
var query = (from i in db.EmployeeMasters
select new SelectEmployee { EmployeeID = i.EmployeeID, EmployeeName = i.EmployeeName, check = false }).ToList();
return query;
}
}
View
#using(Html.BeginForm())
{
<table class="table">
#for (var i = 0; i < Model.Count; i++) {
<tr>
<td>
#Html.DisplayFor(modelEmployee => modelEmployee[i].EmployeeID)
</td>
<td>
#Html.CheckBoxFor(modelEmployee => modelEmployee[i].check)
</td>
<td>
#Html.DisplayFor(modelEmployee => modelEmployee[i].EmployeeName)
</td>
</tr>
}
</table>
<input type="submit" value="click" />
}
Controller
public ActionResult Index()
{
return View(DemoManager.GetSelectedEmployee());
}
[HttpPost]
public ActionResult Index(List<SelectEmployee> emp)
{
var query = (from i in emp
where i.check == true
select i);
// Here you can set the insert statements the query will contain only selected items
return View(model);
}

Passing complex objects in asp.net mvc

I am trying to pass complex object from my view to my controller.
I give the ability to the client to create infinity listBox.
How can I transfer this to the controller?
Here is description:
For every CompanyFeedbackTopic, the client can insert infinite CompanyFeedBackQuestion(Text with int).
I have this objects:
public class CompanyFeedbackTopic
{
/***fields***/
private readonly int m_topicId;
private int m_companyFeedbackId;
private int m_formatFeedbackId;
private int m_percent;
private List<CompanyFeedbackQuestion> m_companyFeedbackQuestionList;
/***constractors***/
public CompanyFeedbackTopic(int topicId, int companyFeedbackId, int formatFeedbackId, int percent,
List<CompanyFeedbackQuestion> companyFeedbackQuestionList)
{
m_topicId = topicId;
m_companyFeedbackId = companyFeedbackId;
m_formatFeedbackId = formatFeedbackId;
m_percent = percent;
m_companyFeedbackQuestionList = companyFeedbackQuestionList;
}
/***get/set***/
public int TopicId
{ get { return m_topicId; } }
public int CompanyFeedbackId
{ get { return m_companyFeedbackId; } set { m_companyFeedbackId = value; }}
public int FormatFeedbackId
{ get { return m_formatFeedbackId; } set { m_formatFeedbackId = value; }}
public int Percent
{ get { return m_percent; } set { m_percent = value; }}
public List<CompanyFeedbackQuestion> CompanyFeedbackQuestionList
{ get { return m_companyFeedbackQuestionList; } set { m_companyFeedbackQuestionList = value; }
}
/***functions***/
}
public class CompanyFeedbackQuestion
{
/***fields***/
private readonly int m_questionId;
private int m_topicId;
private string m_question;
private int m_fieldGradeOptions;
/***constractors***/
public CompanyFeedbackQuestion(int questionId, int topicId, string question, int fieldGradeOptions)
{
m_questionId = questionId;
m_topicId = topicId;
m_question = question;
m_fieldGradeOptions = fieldGradeOptions;
}
/***get/set***/
public int QuestionId
{ get { return m_questionId; } }
public int TopicId
{ get { return m_topicId; } set { m_topicId = value; }}
public string Question
{ get { return m_question; } set { m_question = value; } }
public int FieldGradeOptions
{ get { return m_fieldGradeOptions; } set { m_fieldGradeOptions = value; }}
}
And this is the view:
#using (Html.BeginForm("SubmitNewForm", "ManageFeedback", FormMethod.Post))
{
#Html.Label("Choose feedback type: ")
#Html.DropDownListFor(model => model.SelectedFeedbaclType, Model.FeedbackTypesDic.Select(i => new SelectListItem() { Text = i.Value, Value = i.Key.ToString() }), "---")
<div id="formTable">
#foreach (var item in Model.FormatFeedbackDic)
{
<h4>#item.Value</h4>
<table id="#item.Key">
<tr>
<td class="tableHeader">#</td>
<td class="tableHeader">question</td>
<td class="tableHeader">Grade Options</td>
</tr>
<tr>
<td>1</td>
<td>#Html.TextBox("SS", "", new { style = "width:500px" })</td>
<td>#Html.DropDownList("fieldGradeOptions", Model.GetDropDownList()) </td>
</tr>
</table>
<br />
<button onclick="AddNewRow(#item.Key);">+</button>
<hr />
}
</div>
<br />
<button onclick="SubmitForm();">Create new feedback</button>
}
How can I transfer it to the view?
You have to do two things
Replace all the foreach loops with simple for loops. Example -
for(int i = o; i< Model.FormatFeedbackDic.Count; i++){}
2.Replace this line //button onclick="SubmitForm();">Create new feedback// with
/input type = "sumbit" />
Now it will pass the complex model back to controller

Generic type in Views

My Goal : Implement a Grid with Partial View. so i created a class for Grid
My code
public class HomeController : Base_Controller
{
//
// GET: /Home/
public ActionResult Index()
{
// return View("~/Views/Home/User/Login");
if (System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
{
var users = UserBL.GetAllUsers();
Type type = users.FirstOrDefault().GetType();
Models.Grid<DAL.Entities.User_Details> grid = new Models.Grid<DAL.Entities.User_Details>(users);
ViewBag.GridData = grid;
return View();
}
else
{
return RedirectToAction("Login", "User");
}
// return "Hellow";
}
}
And My Grid Class is
public class Grid<T>
{
public Grid(object datasource)
{
Data = (List<T>)datasource;
}
public Grid()
{
}
public List<T> Data
{
get;
set;
}
public IEnumerable<System.Reflection.PropertyInfo> Props
{
get
{
return typeof(T).GetProperties().AsEnumerable();
}
}
}
MY view Code is
#using DAL.Entities;
#{
ViewBag.Title = "Index";
}
<h1>welcome User....!</h1>
#{Models.Grid<User_Details> modelgrid = (Models.Grid<User_Details>)#ViewBag.GridData;}
#Html.Partial("GridView",modelgrid)
My Partial View is this. in this code first line have here i want to use any reflection mechanism. can any one change code to workable code
#model AC.Models.Grid<Need a solution here>
#if (Model != null)
{
<table>
<thead>
<tr>
#foreach (var col in Model.Props)
{
<td>#Html.Display(col.Name)</td>
}
</tr>
</thead>
<tbody>
#foreach (var item in Model.Data)
{
<tr>
#foreach (var prop in Model.Props)
{
<td>#Html.Display(prop.GetValue(item, null).ToString())</td>
}
</tr>
}
</tbody>
</table>
}
Since you are already using reflection there's not much benefit of using generics here. How about:
public class Grid
{
private readonly Type type;
public Grid(IEnumerable datasource)
{
if (datasource == null)
{
throw new ArgumentNullException("datasource");
}
this.type = datasource.GetType().GetGenericArguments().SingleOrDefault();
if (this.type == null)
{
throw new ArgumentException("The datasource must be generic");
}
this.Data = datasource;
}
public IEnumerable Data { get; private set; }
public IEnumerable<System.Reflection.PropertyInfo> Props
{
get
{
return this.type.GetProperties().AsEnumerable();
}
}
}
and then:
#model AC.Models.Grid
#if (Model != null)
{
<table>
<thead>
<tr>
#foreach (var col in Model.Props)
{
<td>#Html.Display(col.Name)</td>
}
</tr>
</thead>
<tbody>
#foreach (var item in Model.Data)
{
<tr>
#foreach (var prop in Model.Props)
{
<td>#Html.Display(prop.GetValue(item, null).ToString())</td>
}
</tr>
}
</tbody>
</table>
}

Resources