Generic type in Views - asp.net

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>
}

Related

List of Items always null MVC 5

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>
}
}

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);
}

Radio button list using editor templates for merging contacts

I am trying to display a form for merging two contacts in ASP.net MVC 5.
The form should look like this where each row holds a radio button group consisting of 2 options:
The form shows up just fine, and the radio groups work (I can select each group). However, when the model is posted back to the server, the Values list is empty (not preserved). I would like to get both the selected id but of course also the actual text value back in the controller. I prefer to do this using Editor Templates and if possible without for loops.
The current results (Values = null):
EDIT to respond to comments: I would prefer not to re-fetch the values in the controller again, because it results in a call to a web service. I have tried some variants of HiddenFor without results.
My models look like this:
public class Contact
{
public List<ContactRow> Rows { get; set; }
public Contact()
{
this.Rows = new List<ContactRow>();
this.Rows.Add(new ContactRow("First Name", "Homer", "Homie"));
this.Rows.Add(new ContactRow("Last Name", "Simpson", "Simson"));
this.Rows.Add(new ContactRow("Email", "mail1", "mail2"));
this.Rows.Add(new ContactRow("Company Phone", "Phone1", "Phone2"));
this.Rows.Add(new ContactRow("Mobile Phone", "Mobile1", "Mobile2"));
}
}
public class ContactRow
{
public int Selection { get; set; }
public string Label { get; set; }
public List<ValueSet> Values { get; set; }
public ContactRow(string Label, string LeftValue, string RightValue, int Selection = 0)
{
if (LeftValue== null) LeftValue= "";
if (RightValue== null) RightValue= "";
this.Label = Label;
this.Selection = Selection;
this.Values = new List<ValueSet>(2);
this.Values.Add(new ValueSet() { ID = 0, ValueText = LeftValue});
this.Values.Add(new ValueSet() { ID = 1, ValueText = RightValue});
}
public ContactRow() { }
}
public class ValueSet
{
public int ID { set; get; }
public string ValueText { set; get; }
}
The Controller:
public ActionResult Index()
{
Contact model = new Contact();
return View(model);
}
public ActionResult MergeContacts(Contact model)
{
return RedirectToAction("Index");
}
And the views:
Index.cshtml
#model RadioTest.Models.Contact
#{
ViewBag.Title = "Home Page";
}
#using (Html.BeginForm("MergeContacts", "Home", FormMethod.Post, new { encType = "multipart/form-data", id = "contactDetailsForm", name = "contactDetailsForm" }))
{
<div>
<table class="table" width="100%">
<tr>
<th style="text-align:left">Label</th>
#*<th style="text-align:right">R1</th>*#
<th style="text-align:left">
Left Value
</th>
#*<th style="text-align:right">R2</th>*#
<th style="text-align:left">
Right Value
</th>
</tr>
#Html.EditorFor(model => model.Rows)
</table>
<input type="submit" />
</div>
}
Editor Template for ContactRow:
ContactRow.cshtml
#model RadioTest.Models.ContactRow
<tr>
<td style="text-align:left">
#Html.DisplayFor(model => model.Label)
</td>
#foreach (var v in Model.Values)
{
<td style="text-align:left">
#Html.RadioButtonFor(model => model.Selection, v.ID) #v.ValueText
</td>
}
</tr>
#Html.HiddenFor(model => model.Label)
Just change your foreach to for:
#model MVCApp.Controllers.ContactRow
<tr>
<td style="text-align:left">
#Html.DisplayFor(model => model.Label)
</td>
#for (int i = 0; i < Model.Values.Count; i++)
{
<td style="text-align:left">
#Html.RadioButtonFor(model => model.Selection, Model.Values[i].ID) #Model.Values[i].ValueText
#Html.HiddenFor(model => Model.Values[i].ID)
#Html.HiddenFor(model => Model.Values[i].ValueText)
</td>
}
</tr>
#Html.HiddenFor(model => model.Label)

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);
}

Issue with a single razor view accessing two models (ASP.NET MVC3)

View(Index.chtml) is returning 0 rows while accessing two models in the view. Please see the code below. I am new to ASP.NET and I am still learning. I tried to debug and I see the table data is not being passed to correctly. Please help
================================================================================
Controller: (OrganizationCodesController.cs)
================================================================================
namespace MvcProject.Controllers
{
public class OrganizationCodesController : Controller
{
//
// GET: /OrganizationCodes/
public ActionResult Index()
{
List<TABLE_CODES> temp_codes = new List<TABLE_CODES>();
List<TABLE_ORGANIZATIONS> temp_organizations = new List<TABLE_ORGANIZATIONS>();
var viewModel = new OrganizationCodesModel(temp_codes, temp_organizations);
return View(viewModel);
}
}
============================================================================
Model: (OrganizationCodesModel.cs)
============================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Collections;
namespace MvcProject.Models
{
public class OrganizationCodesModel
{
public List<TABLE_CODES> TABLE_CODES { get; set; }
public List<TABLE_ORGANIZATIONS> TABLE_CODES { get; set; }
public OrganizationCodesModel(List<TABLE_CODES> _codes, List<TABLE_ORGANIZATIONS> _organizations)
{
TABLE_CODES = _codes;
TABLE_ORGANIZATIONS = _organizations;
}
}
}
========================================================================
View: (Index.chtml)
========================================================================
#model MvcProject.Models.OrganizationCodesModel
<table>
<thead>
<tr>
<th>
ORGANIZATION_NAME
</th>
<th>
RANK
</th>
<th>
LEVEL
</th>
</thead>
<tbody>
#foreach (var item in Model.TABLE_CODES) {
<tr>
<td>
#foreach (var item_1 in Model.TABLE_ORGANIZATIONS)
{
if (item.LOCATION == item_1.ID)
{
#item1.NAME
break;
}
}
</td>
<td>
#item.RANK
</td>
<td>
#item.LEVEL
</td>
</tr>
}
</tbody>
</table>
List<TABLE_CODES> temp_codes = new List<TABLE_CODES>();
List<TABLE_ORGANIZATIONS> temp_organizations = new List<TABLE_ORGANIZATIONS>();
var viewModel = new OrganizationCodesModel(temp_codes, temp_organizations);
your instanciating two empty lists...
you should put something in your lists !
something like
List<TABLE_CODES> temp_codes = GetTempCodesFromSomewhere();
or
List<TABLE_CODES> temp_codes = new List<TABLE_CODES> {
new TABLE_CODES {LOCATION = 1, RANK = 1, LEVEL =1},
new TABLE_CODES{LOCATION = 2, RANK = 3, LEVEL = 12345}
};
Modiy your Model Class like this:
public class OrganizationCodesModel
{
public List<TABLE_CODES> listTABLE_CODES { get; set; }
public List<TABLE_ORGANIZATIONS> listTABLE_ORGANIZATIONS { get; set; }
}
I have also added text "list" as prefix to the name of the list to distinguish it from the class name otherwise both list name and class name are same.
Ok Now you have to also modify your Index action method like this:
public ActionResult Index()
{
OrganizationCodesModel model = new OrganizationCodesModel();
List<TABLE_CODES>listCodes = new List<TABLE_CODES> {
new TABLE_CODES {LOCATION = 1, RANK = 1, LEVEL =1},
new TABLE_CODES{LOCATION = 2, RANK = 3, LEVEL = 12345}
};
List<TABLE_ORGANIZATIONS> listOrganisation = new List<TABLE_ORGANIZATIONS> {
new TABLE_ORGANIZATIONS {ID = 1,NAME="ABC"},
new TABLE_ORGANIZATIONS{ID = 2,NAME="XYZ"}
};
model.ListTABLE_CODES = listCodes;
model.ListTABLE_ORGANIZATIONS = listOrganisation;
return View(model);
}
and in your View just replace your List name like this:
#foreach (var item in Model.listTABLE_CODES )
#foreach (var item_1 in Model.listTABLE_ORGANIZATIONS )
That is all. Now you will be able to see your output like this:

Resources