Multiple kendo grids in view using MVC Razor #foreach - asp.net-mvc

Is it possible to create multiple kendo grids using MVC Razor #foreach?
I've tried the following and nothing is rendering in the view, it looks like the data is correct as I can see the correct JSON data in the script but no grid displays
#using Kendo.Mvc.UI
#model ProjectMVC.Models.IndexViewModel
#{
ViewData["Heading"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
#{
int gridIndex = 0;
foreach (var Heading in Model.Headings)
{
gridIndex++;
var Groups = Model.Groups.Where(x => x.Group == Heading);
tblGroups Group = Model.Groups.Where(x => x.Group == Heading).First();
#(Html.Kendo().Grid(Groups)
.Name($"grid{gridIndex}")
.Columns(columns =>
{
columns.Bound(c => c.Date).Width(140);
columns.Bound(c => c.User).Width(190);
columns.Bound(c => c.Category);
columns.Bound(c => c.Group).Width(110);
})
.Pageable()
.Filterable()
.Scrollable()
)
}
}
The following code does work using <\table> instead of Html.Kendo().Grid but I have been unable to recreate this using a kendo grid instead of tables. Can anyone point out where I might be going wrong?
Specifically this is aspnet core mvc.
MODEL:
public class tblGroups
{
[Key]
public int ID { get; set; }
public DateTime Date { get; set; }
public string User { get; set; }
public string Category { get; set; }
public string Group { get; set; } //<<Want separate tables split by this field
}
public class IndexViewModel
{
public List<tblGroups> Groups { get; set; }
public List<string> Headings { get; set; }
Public IndexViewModel()
{
Groups = new List<tblGroups>();
Headings = new List<string>();
}
}
VIEW:
#model MVC.Models.IndexViewModel
#{
ViewData["Heading"] = "Index";
}
<h2>Index</h2>
<p>
<a asp-action="Create">Create New</a>
</p>
#{
foreach (var Heading in Model.Headings)
var Groups = Model.Groups.Where(x => x.Group == Heading);
tblGroups Group = Model.Groups.First(x => x.Prodcut == Heading);
<text>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => Group.Date)
</th>
<th>
#Html.DisplayNameFor(model => Group.User)
</th>
<th>
#Html.DisplayNameFor(model => Group.Category)
</th>
<th>
#Html.DisplayNameFor(model => Group.Group)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Groups)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
<td>
#Html.DisplayFor(modelItem => item.User)
</td>
<td>
#Html.DisplayFor(modelItem => item.Category)
</td>
<td>
#Html.DisplayFor(modelItem => item.Group)
</td>
<td>
</td>
</tr>
}
</tbody>
</table>
</text>
}
}
CONTROLLER:
public class tblGroupsController : Controller
{
public async Task<IActionResult> Index()
{
var allGroups = await _context.tblGroups.ToListAsync();
var Headings = allGroups.Select(x => x.Group).Distinct();
var model = new Models.IndexViewModel()
{
Groups = allGroups,
Headings = Headings
};
return View(model);
}
}

In order to use the same partial view multiple times, grid ID should be unique so passing the ID in partial view data is one possible solution. I have used the same grid multiple times in a PartialView by passing some parameters and retrieving different data via these parameters as shown below:
View:
<div class="row">
<div class="col-lg-6">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title" id="panel-title">New Issues</h3>
</div>
<div>
#Html.Partial("_List", new ViewDataDictionary { { "name", "grid-all-issues" }, { "style", "border:none; height:622px;" }, { "pageSize", "25" } })
</div>
</div>
</div>
<div class="col-lg-6">
<div class="row">
<div class="col-lg-12">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title" id="panel-title">Active Issues</h3>
</div>
<div>
#Html.Partial("_List", new ViewDataDictionary { { "name", "grid-waiting-issues" }, { "style", "border:none; height:273px;" }, { "pageSize", "10" } })
</div>
</div>
</div>
<div class="col-lg-12 top-10">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title" id="panel-title">Watched Issues</h3>
</div>
<div>
#Html.Partial("_List", new ViewDataDictionary { { "name", "grid-watched-issues" }, { "style", "border:none; height:273px;" }, { "pageSize", "10" } })
</div>
</div>
</div>
</div>
</div>
</div>
PartialView:
#(Html.Kendo().Grid<Models.ViewModel>()
.HtmlAttributes(new { style = #ViewData["style"].ToString() })
.Name(#ViewData["name"].ToString())
//...
.Columns(columns =>
{
columns.Bound(m => m.Key).Title("Issue No");
})
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(Convert.ToInt32(#ViewData["pageSize"]))
)
)
Update: You can pass column parameter by using an approach below.
For passing parameter to a PartialView in ASP.NET MVC:
#Html.Partial("~/PathToYourView.cshtml", null, new ViewDataDictionary { { "VariableName", "some value" } })
And to retrieve the passed in values:
#{
string valuePassedIn = this.ViewData.ContainsKey("VariableName") ?
this.ViewData["VariableName"].ToString() : string.Empty;
}
Hope this helps...

Related

How to make an insert form and a table displaying data from database in a single view in MVC?

I'm making a CRUD but I want the create and read parts to be in a single MVC view. The create part is done, I've been trying to fill an HTML table with data from a database table when the view loads, but it won't let me do both things at once in a single view.
Here's the view header:
#model Console.Models.Product
#{
ViewBag.Title = "Create";
}
Here's the insert form:
#using (Html.BeginForm())
{
<div class="box-body">
<div class="form-horizontal">
#Html.AntiForgeryToken()
#Html.Hidden("productID", 0)
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<div class="col-md-6">
#Html.EditorFor(model => model.productName, new { htmlAttributes = new { #class = "form-control", #name = "txtProductName", #id = "txtProductName" } })
</div>
#Html.ValidationMessageFor(model => model.productName, "", new { #class = "text-danger", Type = "productName" })
</div>
<div class="form-group">
<div class="col-md-6">
#Html.EditorFor(model => model.productQuantity, new { htmlAttributes = new { #class = "form-control", #name = "txtProductQuantity", #id = "txtProductQuantity" } })
</div>
#Html.ValidationMessageFor(model => model.productQuantity, "", new { #class = "text-danger" })
</div>
<div class="form-group">
<div class="col-md-6">
#Html.EditorFor(model => model.productColor, new { htmlAttributes = new { #class = "form-control", #name = "txtProductColor", #id = "txtProductColor" } })
</div>
#Html.ValidationMessageFor(model => model.productColor, "", new { #class = "text-danger" })
</div>
</div>
</div>
}
This is the table that should show the products that are inserted into the database in the form above:
<table id="Data_table" class="table table-bordered table-striped">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.productName)
</th>
<th>
#Html.DisplayNameFor(model => model.productQuantity)
</th>
<th>
#Html.DisplayNameFor(model => model.productColor)
</th>
<th>
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.productName)
</td>
<td>
#Html.DisplayFor(modelItem => item.productQuantity)
</td>
<td>
#Html.DisplayFor(modelItem => item.productColor)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.productID }, new { #class = "btn btn-success btn-sm" })
#Html.ActionLink("Delete", "Delete", new { id = item.productID }, new { #class = "btn btn-danger btn-sm" })
</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<th><div class="panel-footer">Total = #Model.Count()</div></th>
</tr>
</tfoot>
</table>
Problem is that I get an error at the foreach telling me to use IEnumerable with the model but whenever I do, the insert form gets an error. Is there any way to get around this?
Edit:
Here's the view model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Console.Models
{
public class ProductViewModel
{
public int productID{ get; set; }
public string productName{ get; set; }
public int productQuantity{ get; set; }
public string productColor{ get; set; }
public IEnumerable<Product> Products { get; set; }
}
}
In your view you do pass a single model, and then you try to iterate over it, that of course is not possible.
You should use view models. Create a view model that contains both the fields you need for the form and the list of products you want to iterate over on foreach.
#model ProductViewModel
#{
ViewBag.Title = "Create";
}
Create a view model, like this:
public class ProductViewModel {
public string ProductName { get; set; }
// Other fields for the form
public IEnumerable<Product> Products { get; set; } // Your list of products for the table
}
And then in your view:
#Html.EditorFor(model => model.ProductName,
// Continue with the form
#foreach (var item in Model.Products)
{ //...continue with your table

View is expecting for viewmodel while List item has been passed to controller

Error::
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[ProjDAL.Models.ViewModels.EmpViewModel]', but this dictionary requires a model item of type 'ProjDAL.Models.ViewModels.EmpViewModel'.
I am working on a mvc application. For one view which basically has a functionality for multiple parameter search. I am using same view for get and post method... It means i am passing 1 or more parameters to the textboxes and fetching the result using linq and mapping to a datatable.
After passing the parameters, the values are going to the controller and fetching the exact result using linq but the problem is coming when i am trying to map the linq result-set to my view.
Here is the code for the project -
Controller -
[HttpPost]
public ActionResult EmpSearch([Bind(Include = "employee,EmpID,PAN")] Get_EmpDetails_Result get_EmpDetails_Result)
{
var result = from emp in dbCollections.Employees
join nat in dbCollections.NationalID on emp.EmpID equals nat.EmpID
select new EmpViewModel
{
PAN = nat.pan,
EmpID = emp.EmpID,
employee = emp.Name
};
var searchRes = result
.Where(s => s.PAN.Contains(get_EmpDetails_Result.pan)
|| s.EmpID.Contains(get_EmpDetails_Result.empid)
|| s.employee.Contains(get_EmpDetails_Result.employee));
var modelSys = searchRes.ToList();
return View(modelSys);
}
View ::::
#model NewProjDAL.Models.ViewModels.EmpViewModel
#{
ViewBag.Title = "empDetails";
Layout = "~/Views/Shared/_Layout.cshtml";
}
//////////// this part is for the multiple criteria search
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<label>By EmpID</label>
<div class="col-md-10">
#Html.EditorFor(model => model.GetEmpDetails.FirstOrDefault().empid, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
<label>By PAN</label>
<div class="col-md-10">
#Html.EditorFor(model => model.GetEmpDetails.FirstOrDefault().pan, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
<label>By Name</label>
<div class="col-md-10">
#Html.EditorFor(model => model.GetEmpDetails.FirstOrDefault().employee, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-actions center">
<button type="submit" data-animation="pulse" class="btn btn-lg font-medium-1 btn-outline-teal mb-1 block-multiple-msgs buttonAnimation">
<i class="fa fa-check-square-o"></i> Go
</button>
</div>
</div>
}
//////////////////////////////this part is to fetch the result of the previously mentioned multiple search
#if (Model.EmpDetails.Count != 0)
{
<div class="table-responsive">
<table class="table table-striped table-bordered dom-jQuery-events compact" id="DataTbl">
<thead class="navbar-dark navbar-dark bg-blue-grey white">
<tr>
<th>
employee
</th>
<th>
PAN
</th>
<th>
empid
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.GetEmpDetails)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.employee)
</td>
<td>
#Html.DisplayFor(modelItem => item.PAN)
</td>
<td>
#Html.DisplayFor(modelItem => item.empid)
</td>
</tr>
}
</tbody>
</table>
</div>
}
It's told you exactly what the problem is. You've set up the view to accept a single EmpViewModel as the Model, but your controller is passing a List
You need to create a view model to represent the search criteria and the results
public class EmployeeSearchViewModel
{
public string EmpId { get; set; }
public string PAN { get; set; }
public string Employee { get; set; }
public List<EmpViewModel> Employees { get; set; } = new List<EmpViewModel>();
}
then in your controller method:
var modelSys = searchRes.ToList();
var viewModel = new EmployeeSearchViewModel
{
PAN = get_EmpDetails_Result.pan,
EmpId = get_EmpDetails_Result.empid,
Employee = get_EmpDetails_Result.employee
Employees = modelSys
};
return View(viewModel);
In the view:
#Model EmployeeSearchViewModel
Then your parameters display don't need to pull the EmpID, PAN, etc. from the collection, just from the view model, and you can bind your repeated results to the inner collection "Employees".

Mvc 5 pagination using view model

Hi i am newbie to Mvc i have a json service which returns a list of walletstatementlogs based on fromdate and todate. I have a controller TopUpReqLogController every time when i hit the action index of the controller it will go to service and fetch the data and returns to view as Ipagedlist and genrates pagelinks. How do i prevent servicecall everytime in TopUpReqLogController index action i just want to load service data once and pass it to index and display data in pages using int ? page please suggest
public class WalletTopUpRequest
{
public string SlNo { get; set; }
public string Sequence { get; set; }
public string Merchant { get; set; }
public string CustomerCode { get; set; }
public string CustomerName { get; set; }
public string BankName { get; set; }
public string TransactionDate { get; set; }
public string Reference { get; set; }
public string Amount { get; set; }
public string ApprovalStatus { get; set; }
public string ApproveUser { get; set; }
public string ApprovalDate { get; set; }
public string RemarKs { get; set; }
}
public ViewResult Index(int? page)
{
int pageSize = 3;
int pageNumber = (page ?? 1);
List<WalletTopUpRequest> wallettoprq = new List<WalletTopUpRequest>();
if (page == null)
{
AgentBusiness business = new AgentBusiness();
var result = business.Topuprequestlog("99910011010", "99810001110", "jBurFDoD1UpNPzWd/BlK4hVpV8GF+0eQT+AfNxEHHDKMB25AHf6CVA==", "25052017000000", "01062017000000");
wallettoprq = result.wallettopuprequest.ToList();
var viewmodel = wallettoprq.ToPagedList(pageNumber, pageSize);
return View(viewmodel);
}
return View(wallettoprq.ToPagedList(pageNumber, pageSize));
}
#using PagedList;
#using PagedList.Mvc;
#model IPagedList<HaalMeer.MVC.Client.Models.WalletTopUpRequest>
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<html>
<head>
</head>
<body>
<div id="page-wrapper">
<div class="page-title-container">
#*<div class="container-fluid">*#
<div class="page-title pull-left">
<h2 class="entry-title">Topup Request Log</h2>
</div>
<ul class="breadcrumbs pull-right">
<li>Home</li>
<li class="active">Topup Request Log</li>
</ul>
</div>
</div>
<section id="content" class="gray-area">
<div class="container">
<div class="row">
<div class="col-md-3">
</div>
#using (Html.BeginForm("Index", "TopUpReqLog", FormMethod.Get))
{
<div class="col-md-3">
<div class="form-group">
<label>From Date</label>
<div class="datepicker-wrap blue">
#*<input type="text" name="date_from" class="input-text full-width" placeholder="mm/dd/yy" style="background-color: #fff" />*#
#Html.TextBox("Fromdate", ViewBag.fromdate as string, new { #class = "input-text full-width", #placeholder = "mm/dd/yyy",#style = "background-color: #fff" }) <br />
</div>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label>To Date</label>
<div class="datepicker-wrap blue">
#*<input type="text" name="date_from" class="input-text full-width" placeholder="mm/dd/yy" style="background-color: #fff" />*#
#Html.TextBox("Todate", ViewBag.todate as string, new { #class = "input-text full-width", #placeholder = "mm/dd/yyy", #style = "background-color: #fff" }) <br />
</div>
</div>
<button type="submit">Submit</button>
</div>
}
<div class="col-md-3">
</div>
</div>
<div class="row">
<div class="col-md-12 col-sm-12">
<div class="table-responsive">
<table class="table">
<tr class="info" style="text-align: center; font-weight: bold; color: #000">
<td class="col-md-1">Sl</td>
<td class="col-md-2">Date</td>
<td class="col-md-1">Bank Ref.</td>
<td class="col-md-1">Bank Name</td>
<td class="col-md-2">Remarks</td>
<td class="col-md-1">Amount</td>
<td class="col-md-1">Status</td>
<td class="col-md-2">Action Date</td>
</tr>
#foreach (var item in Model)
{
<tr>
<td class="hmcenter">#Html.DisplayFor(modelItem => item.SlNo)</td>
<td class="hmcenter">#Html.DisplayFor(modelItem => item.TransactionDate)</td>
<td class="hmcenter">#Html.DisplayFor(modelItem => item.Reference)</td>
<td class="hmcenter">#Html.DisplayFor(modelItem => item.BankName)</td>
<td class="hmleft">#Html.DisplayFor(modelItem => item.RemarKs)</td>
<td class="hmright">#Html.DisplayFor(modelItem => item.Amount) </td>
<td class="hmcenter">#Html.DisplayFor(modelItem => item.ApprovalStatus)</td>
<td class="hmcenter">#Html.DisplayFor(modelItem => item.ApprovalDate)</td>
</tr>
}
</table>
<br/>
Page #(Model.PageCount<Model.PageNumber? 0 : Model.PageNumber) of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("Index",new { page
}))
#*<div class="form-group">
<ul class="pagination">
<li>1</li>
<li class="active">2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</div>*#
</div>
</div>
</div>
</div>
</section>
So, from what I understand you want just make it work only on client side. If your model is not empty this code should work. If you want to load data as one result and make pagination on client side, then IPageList is not what you are looking for. Because, it is used only on the server side, and always returns ONE page of data to brake large results. You also can try to pass list of data to the view and turn it to IPageList result in the view and display each
page in tab, but is not a good practice. I would use datatables in this situation to make pagination only on the client side using regular data list:
https://datatables.net/.
Hint to improve current code:
Controller:
public ViewResult Index(int? page = 1)
{
AgentBusiness business = new AgentBusiness();
var result = business.Topuprequestlog("99910011010", "99810001110", "jBurFDoD1UpNPzWd/BlK4hVpV8GF+0eQT+AfNxEHHDKMB25AHf6CVA==", "25052017000000", "01062017000000");
return View(result.wallettopuprequest.ToPagedList(pageNumber, 3));
}
View:
#Html.PagedListPager(Model, page => Url.Action("Index", new { page }), PagedListRenderOptions.ClassicPlusFirstAndLast)
Below example shows the paging to be done at server side and Client Side :
Here is my Model :
public partial class Employee
{
public int Id { get; set; }
public string FName { get; set; }
public string Lname { get; set; }
}
Action:
public ActionResult Index(int? Page)
{
return View();
}
/// returns Partial View
public ActionResult _PartialIndex(int? Page)
{
return PartialView(db.Employees.ToList().ToPagedList(Page ?? 1, 10));
}
Views :
1.Index View :Index.cshtml
#{
ViewBag.Title = "Index";
}
<script src="https://cdn.jsdelivr.net/jquery.ajax.unobtrusive/3.2.4/jquery.unobtrusive-ajax.min.js"></script>
<script>
$(document).ready(function () {
$('#loading').show();
debugger;
var Page = '';
$.ajax({
url: '/Employees/_PartialIndex',
contentType: "application/json; charset=utf-8",
type: 'get',
datatype: 'html'
}).success(function (result) {
$('#main').html(result);
$('#loading').hide();
});
});
</script>
<h2>Index</h2>
<div class="col-md-8 col-md-offset-2">
<center>
<div id="loading" style="display:none; z-index:200; position:absolute; top:50%; left:45%;">
<img src="~/Content/loading.gif" />
</div>
</center>
<div id="main">
</div>
</div>
2.Partial View :_PartialIndex.cshtml
#using PagedList.Mvc
#using PagedList;
#model IPagedList<samplePaging.Models.Employee>
#{
ViewBag.Title = "Index";
}
<h2>Employee List</h2>
<table class="table">
<tr>
<th>
First Name
</th>
<th>
Last Name
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.FName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Lname)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
#Html.ActionLink("Details", "Details", new { id = item.Id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.Id })
</td>
</tr>
}
</table>
<center>
#Html.PagedListPager(Model, page => Url.Action("_PartialIndex", new { page }), PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(new PagedListRenderOptions() { DisplayPageCountAndCurrentLocation = true }, new AjaxOptions() { HttpMethod = "GET", UpdateTargetId = "main", LoadingElementId = "loading" }))
</center>
If you want to do the paging at client side then follow below steps:
Action:
public ActionResult JsonIndex(int? Page)
{
return Json(db.Employees.ToList(), JsonRequestBehavior.AllowGet);
}
View:
#{
ViewBag.Title = "Index2";
}
<h2>Index2</h2>
<link rel="stylesheet" type="text/css" href="//cdn.datatables.net/1.10.10/css/jquery.dataTables.min.css">
<script type="text/javascript" language="javascript" src="//cdn.datatables.net/1.10.10/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
//Call EmpDetails jsonResult Method
$.getJSON("/Employees/JsonIndex",
function (json) {
var tr;
//Append each row to html table
for (var i = 0; i < json.length; i++) {
tr = $('<tr/>');
tr.append("<td>" + json[i].FName + "</td>");
tr.append("<td>" + json[i].LName + "</td>");
$('table').append(tr);
}
$('#EmpInfo').DataTable();
});
});
</script>
<hr />
<div class="form-horizontal">
<table id="EmpInfo" class="table table-bordered table-hover">
<thead>
<tr>
<th>Fname</th>
<th>LName</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
Hope this help you !

asp.net mvc onr-to-many details partial view in master main view

I am sorry if im asking same thing for the nth time but i can not find the answer to my question...
I have problem adding partial views...
I have One-to-Many relation in the database tables.
My Model is:
using System;
using System.Collections.Generic;
public partial class Job
{
public Job()
{
this.Flights = new HashSet<Flight>();
}
public int JobID { get; set; }
public string JobNumber { get; set; }
public int ClientID { get; set; }
public virtual Client Client { get; set; }
public virtual ICollection<Flight> Flights { get; set; }
}
My Controller (Create):
// GET: /Jobs/Create
public ActionResult Create()
{
ViewBag.ClientID = new SelectList(db.Clients, "ClientID", "ClientName");
return View();
}
And View (for create Job):
#model AOG.Models.Job
<div class="form-horizontal">
<h4>Job</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.JobNumber, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.JobNumber)
#Html.ValidationMessageFor(model => model.JobNumber)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ClientID, "ClientID", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("ClientID", String.Empty)
#Html.ValidationMessageFor(model => model.ClientID)
</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>
Now if i add partial view (Generated Partial List View) On Create Job Page:
#html.Partial("_PartialFlights");
I get an error: Object reference not set to an instance of an object on
Line 23: #foreach (var item in Model) {
in my partial view. This is the code:
#model IEnumerable<AOG.Models.Flight>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.FlightName)
</th>
<th>
#Html.DisplayNameFor(model => model.FlightETD)
</th>
<th>
#Html.DisplayNameFor(model => model.FlightETA)
</th>
<th>
#Html.DisplayNameFor(model => model.Job.JobNumber)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.FlightName)
</td>
<td>
#Html.DisplayFor(modelItem => item.FlightETD)
</td>
<td>
#Html.DisplayFor(modelItem => item.FlightETA)
</td>
<td>
#Html.DisplayFor(modelItem => item.Job.JobNumber)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.FlightID }) |
#Html.ActionLink("Details", "Details", new { id=item.FlightID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.FlightID })
</td>
</tr>}</table>
How ever If i put this in the details view:
#foreach (var item in Model.Flights)
{
<div>
<table>
<tr><th>Flight</th><th>ETD</th><th>ETA</th></tr>
<tr>
<td>#Html.DisplayFor(modelItem => item.FlightName)</td>
<td>#Html.DisplayFor(modelItem => item.FlightETD)</td>
<td>#Html.DisplayFor(modelItem => item.FlightETA)</td>
</tr></table>
</div>
}
It shows everything I need, but i want to learn how to do it with the partial views.
Thank you all so much!
You need to pass an IENumerable<Flight> instance to your partial view, so in stead of:
#html.Partial("_PartialFlights");
...do this:
#html.Partial("_PartialFlights", Model.Flights);

How to add a list to a View Model MVC

I'm using MVC 3 with View Model, in my case I have a View Model that should display a list of items and also a form for inserting some input.
I have problem in my View because I'm not able to associate the Form for inserting the data with the view model, could you tell me what I'm doing wrong?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using TestGuestBook.Models;
namespace TestGuestBook.ViewModel
{
public class ListAddCommentsViewModel
{
public int CommentId { get; set; }
[Required]
public string Nominative { get; set; }
[Email]
public string Email { get; set; }
[Required]
public string Content { get; set; }
public List<Comment> CommentItems { get; set; }
}
}
View
#model IEnumerable<TestGuestBook.ViewModel.ListAddCommentsViewModel>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>ListAddCommentsViewModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.CommentId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CommentId)
#Html.ValidationMessageFor(model => model.CommentId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Nominative)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Nominative)
#Html.ValidationMessageFor(model => model.Nominative)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Content)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Content)
#Html.ValidationMessageFor(model => model.Content)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
CommentId
</th>
<th>
Nominative
</th>
<th>
Email
</th>
<th>
Content
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.CommentId)
</td>
<td>
#Html.DisplayFor(modelItem => item.Nominative)
</td>
<td>
#Html.DisplayFor(modelItem => item.Email)
</td>
<td>
#Html.DisplayFor(modelItem => item.Content)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
</tr>
}
</table>
You dont need to pass a Collection to your View. Only one object of the ViewModel is enough. Your ViewModel already have property to holde the collection (List of Comments)
So in your GET Action, return only one instance of this viewModel to the View
public ActionResult GetComments(int postId)
{
var viewModel=new ListAddCommentsViewModel();
viewModel.CommentItems =db.GetComments(postId);
return View(viewModel);
}
and now in your View, Let it bind to a single instance of ListAddCommentsViewModel
#model TestGuestBook.ViewModel.ListAddCommentsViewModel
And Inside your view, to Show your List of comments, use the Collection type property (Model.CommentItems) in your ViewModel
#foreach (var item in Model.CommentItems) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.CommentId)
</td>
<td>
#Html.DisplayFor(modelItem => item.Nominative)
</td>
<td>
#Html.DisplayFor(modelItem => item.Email)
</td>
<td>
#Html.DisplayFor(modelItem => item.Content)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { #id=item.PrimaryKey }) |
#Html.ActionLink("Details", "Details", new { #id=item.PrimaryKey }) |
#Html.ActionLink("Delete", "Delete", new { #id=item.PrimaryKey })
</td>
</tr>
}
This is the best solution, I had checked almost all information and this is the one working!! Thanks
public ActionResult UploadFile(UploadFileViewModel model)
{
if (ModelState.IsValid)
{
var file = model.File;
var parsedContentDisposition =
ContentDispositionHeaderValue.Parse(file.ContentDisposition);
var filename = Path.Combine(_environment.WebRootPath,
"Uploads", parsedContentDisposition.FileName.Trim('"'));
file.SaveAsAsync(filename);
}
return View();
}

Resources