MVC - paging and sorting - asp.net-mvc

I am attempting to implement paging and sorting into my Index view. I am following the example at http://www.codeguru.com/csharp/.net/net_asp/mvc/implementing-sorting-and-paging-in-asp.net-mvc.html however my work is neither paging or sorting. I am not sure where I went wrong.
My Index view is passed a parameter when accessed so I did modify it a little however it should not have cause it to do nothing.
My PagingInfo viewModel used for the paging and sorting is as followings.
public class PagingInfo
{
public string SortField { get; set; }
public string SortDirection { get; set; }
public int PageSize { get; set; }
public int PageCount { get; set; }
public int CurrentPageIndex { get; set; }
}
My controller has
public ActionResult Index(int id)
{
DeviceLogIndex vm = new DeviceLogIndex();
var devicelogs = db.DeviceLogs
.Include(d => d.Device)
.Include(d => d.DeviceLogType)
.Include(d => d.Device.ManufacturerModel)
.Where(d => d.DeviceID == id);
{
PagingInfo info = new PagingInfo();
info.SortField = "DeviceLog";
info.SortDirection = "ascending";
info.PageSize = 4;
info.PageCount = Convert.ToInt32(Math.Ceiling((double)(db.DeviceLogs.Count()/info.PageSize)));
// info.PageCount +=1;
info.CurrentPageIndex = 0;
var query = devicelogs.OrderBy(c => c.DeviceLogID).Take(info.PageSize);
ViewBag.PagingInfo = info;
vm.DeviceLogs = query.ToList();
Device model = db.Devices.Find(id);
model.DeviceID= id;
vm.MyDeviceID = id;
return View(vm);
}
}
[HttpPost]
public ActionResult Index(PagingInfo info, int id)
{
DeviceLogIndex vm = new DeviceLogIndex();
var devicelogs = db.DeviceLogs
.Include(d => d.Device)
.Include(d => d.DeviceLogType)
.Include(d => d.Device.ManufacturerModel)
.Where(d => d.DeviceID == id);
{
IQueryable<DeviceLog> query = null;
switch (info.SortField)
{
case "EntryDate":
query = (info.SortDirection == "ascending" ?
devicelogs.OrderBy(c => c.EntryDate) :
devicelogs.OrderByDescending(c => c.EntryDate));
break;
case "LogType":
query = (info.SortDirection == "ascending" ?
devicelogs.OrderBy(c => c.DeviceLogType) :
devicelogs.OrderByDescending(c => c.DeviceLogType));
break;
}
query = query.Skip(info.CurrentPageIndex * info.PageSize).Take(info.PageSize);
ViewBag.PagingInfo = info;
vm.MyDeviceID = id;
vm.DeviceLogs = query.ToList();
return View(vm);
}
}
And my View contains these parts
#model AQB_MON.ViewModels.DeviceLogIndex
<script>
$(document).ready(function () {
$(".header").click(function (evt) {
var sortfield = $(evt.target).data("sortfield");
if ($("#SortField").val() == sortfield) {
if ($("#SortDirection").val() == "ascending") {
$("#SortDirection").val("descending");
}
else {
$("#SortDirection").val("ascending");
}
}
else {
$("#SortField").val(sortfield);
$("#SortDirection").val("ascending");
}
evt.preventDefault();
$("form").submit();
});
$(".pager").click(function (evt) {
var pageindex = $(evt.target).data("pageindex");
$("#CurrentPageIndex").val(pageindex);
evt.preventDefault();
$("form").submit();
});
});
</script>
#{
ViewBag.Title = "Index";
}
#{
AQB_MON.ViewModels.PagingInfo info = ViewBag.PagingInfo;
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create", new { id = Model.MyDeviceID})
</p>
#using (Html.BeginForm("Index", "DeviceLog", FormMethod.Get))
{
#Html.Hidden("SortField", info.SortField)
#Html.Hidden("SortDirection", info.SortDirection)
#Html.Hidden("PageCount", info.PageCount)
#Html.Hidden("PageSize", info.PageSize)
#Html.Hidden("CurrentPageIndex", info.CurrentPageIndex)
to set the Headers that are sortable -
<th>
<a href="#" data-sortfield="LogType"
class="header">Device Log Type</a>
</th>
<th>
<a href="#" data-sortfield="EntryDate"
class="header">Entry Date</a>
</th>
for the paging -
<td>
#for (var i = 0; i < info.PageCount; i++)
{
if (i == info.CurrentPageIndex)
{
<span>#(i + 1)</span>
}
else
{
<a href="#" data-pageindex="#i"
class="pager">#(i + 1)</a>
}
}
</td>
It's a lot of code that does not seem to do anything. Just confused.

Related

Sorting and Paging on repository

I have a simple ASP.NET MVC application which has possibility to search, filter and page a list of vehicle makes. I implemented sorting, filtering and paging on controller (on "Index" action) following the tutorials from kudvenkat on youtube https://www.youtube.com/watch?v=srN56uxw76s
So, this is my "VehicleMakeController" and "Index" action:
public class VehicleMakeController : Controller
{
private readonly IVehicleRepository _vehicleRepository;
public VehicleMakeController()
{
_vehicleRepository = new VehicleRepository(new VehicleDbContext());
}
// GET: VehicleMake
public ActionResult Index(string search, int? page, string sort)
{
ViewBag.SortNameParameter = string.IsNullOrEmpty(sort) ? "Name desc" : "";
var makes = _vehicleRepository.AllMakes;
switch (sort)
{
case "Name desc":
makes = makes.OrderByDescending(x => x.Name);
break;
default:
makes = makes.OrderBy(x => x.Name);
break;
}
if (search == null)
{
return View(makes.ToList().ToPagedList(page ?? 1, 5));
}
return View(makes.Where(x => x.Name.ToLower().StartsWith(search)).ToList().ToPagedList(page ?? 1, 5));
}
and this is my "Index" view:
#using PagedList;
#using PagedList.Mvc;
#model IPagedList<Project.Service.Entities.VehicleMake>
#{
ViewBag.Title = "Vehicle Makes";
}
<h2>#ViewBag.Title</h2>
#Html.ActionLink("Create", "CreateVehicleMake")
<br/>
<br/>
#using (#Html.BeginForm("Index", "VehicleMake", FormMethod.Get))
{
<p>
#Html.TextBox("search") <input type="submit" value="Search"/>
</p>
}
<table class="table">
<thead>
<tr>
<th>#Html.ActionLink("Name", "Index", new { sort = ViewBag.SortNameParameter, search = Request.QueryString["search"] })</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var vehicleMake in Model)
{
<tr>
<td>#vehicleMake.Name</td>
<td>#Html.ActionLink("Edit", "EditVehicleMake", new {id = vehicleMake.Id})</td>
<td>#Html.ActionLink("Delete", "DeleteVehicleMake", new {id = vehicleMake.Id})</td>
</tr>
}
</tbody>
</table>
#Html.PagedListPager(Model, page => Url.Action("Index", new { page, search = Request.QueryString["search"], sort = Request["sort"]}),
new PagedListRenderOptions() { Display = PagedListDisplayMode.IfNeeded, DisplayPageCountAndCurrentLocation = true})
#if (!Model.Any())
{
<b>No rows match search criteria!</b>
}
In application I'm using repository pattern and I have "AllMakes" method to retrieve all vehicle makes from database. So, this is my "VehicleRepository":
public class VehicleRepository : IVehicleRepository
{
private readonly VehicleDbContext _context;
public VehicleRepository(VehicleDbContext context)
{
_context = context;
}
public IEnumerable<VehicleMake> AllMakes => _context.VehicleMakes;
}
and this is my "IVehicleRepository" interface:
public interface IVehicleRepository
{
IEnumerable<VehicleMake> AllMakes { get; }
}
My DbContext class is following:
public class VehicleDbContext : DbContext
{
public VehicleDbContext() : base("VehicleDbContext")
{
}
public DbSet<VehicleMake> VehicleMakes { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
This everything works OK, but now I want to implement sorting and paging in repository and remove it from controller. The parameters should be passed trough get/query method. I'm not sure how to do this and I would appreciate any help.
You can declare a function in IVehicleRepository and implement it.
public interface IVehicleRepository
{
IEnumerable<VehicleMake> AllMakes { get; }
List<VehicleMake> GetVehicleWithPagination(string search, int? page, string sort);
}
public class VehicleRepository : IVehicleRepository
{
// your old code
public List<VehicleMake> GetVehicleWithPagination(string search, int? page, string sort)
{
// this is your code from controller
switch (sort)
{
case "Name desc":
makes = AllMakes.OrderByDescending(x => x.Name);
break;
default:
makes = AllMakes.OrderBy(x => x.Name);
break;
}
if (search == null)
{
return AllMakes.ToList().ToPagedList(page ?? 1, 5);
}
}
}
And your controller:
public ActionResult Index(string search, int? page, string sort)
{
ViewBag.SortNameParameter = string.IsNullOrEmpty(sort) ? "Name desc" : "";
return View(_vehicleRepository.GetVehicleWithPagination(search, page, sort));
}

How do I change a partial view with a radio button click in .Net MVC and have some of the model state passed along to the partial view?

I'm trying to display a partial view in a div block named 'productButtonForm' based on a radio button click. The partial view appears to be called, but the passed model has null member variables. Can someone help me figure out where I've gone wrong? Below is what I've got:
Model
public class RetrieveAllModel
{
public Guid ConversationId { get; set; }
public List<RetrieveProductsModel> Products { get; set; }
public RetrieveOffersModel Offers { get; set; }
public int ProductType { get; set; }
}
View
#{
ViewBag.Title = "Easy Order";
int productCount = 0;
}
<legend>Offers/Products</legend>
#using (Html.BeginForm("ShowProductItems", "BrowseShopping"))
{
foreach (var type in Model.Products)
{
if (productCount > 0 && productCount % 5 == 0)
{
<br/>//break after every 5 products
}
#type.Name
#Html.RadioButtonFor(model => model.ProductType, type.ID, Model);
<label> </label>
productCount = productCount + 1;
}
<div class="col-lg-5 col-md-6 col-sm-12" id="productButtonForm">
</div>
}
Controller
public PartialViewResult ShowProductItems()
{
return PartialView("RetrieveProducts", new RetrieveAllModel() {Products = new List<RetrieveProductsModel>()});
}
[HttpPost]
public PartialViewResult ShowProductItems(RetrieveAllModel model)
{
//The passed model only has the ProductType set, every other
//member variable is null
return PartialView("RetrieveProducts", model);
}
Script file
$(function() {
$("[name=ProductType]").on('change',
function() {
var $radio = $(this);
var myurl = "ShowProductItems?ProductType=" + $radio.val();
console.log("We hit the script");
$.ajax({
url: myurl,
type: 'POST',
success: function(data) {
$("#productButtonForm").append(data);
}
});
});
});
I had a few issues going. Aside from what Stephen mentioned above, I had two data models that needed to be represented in the same button group. To address that, I had to use Html.RadioButton instead of RadionButtonFor. Also, I needed to access the controller's established conversation with the client to access the model state of the current view. Once I got those in place, the partial view changes as desired. Below are the changes I made to fix my triggering problem.
Model
public class RetrieveAllModel
{
public Guid ConversationId { get; set; }
public List<RetrieveProductsModel> Products { get; set; }
public RetrieveOffersModel Offers { get; set; }
public string ProductType { get; set; }
}
public class RetrieveCatalogModel
{
public List<BrowseDataItemModel> AvailableBrowseItems { get; set; }
}
public class RetrieveOffersModel : RetrieveCatalogModel
{
public List<int> SelectedServiceIds { get; set; }
}
public class RetrieveProductsModel : RetrieveCatalogModel
{
public int ID { get; set; }
public string Name { get; set; }
public int Count { get; set; }
}
View
#model OrderServiceClient.Models.RetrieveAllModel
#{
ViewBag.Title = "Easy Order";
int productCount = 1;
string offers = "Offers";
}
#using (Html.BeginForm("ShowCatalog", "BrowseShopping"))
{
//since offers are not part of the dynamic product list, they need to be specifically identified
#offers<label> </label>
#Html.RadioButton("catalogName", "Offers", true, new { catalogName = "Offers", conversationid = Model.ConversationId })
<label> </label>
foreach (var type in Model.Products)
{
if (productCount > 0 && productCount % 5 == 0)
{
<br/>//break after every 5 products
}
#type.Name<label> </label>
#Html.RadioButton("catalogName", type.Name, new { catalogName = type.Name, conversationid = Model.ConversationId })
<label> </label>
productCount = productCount + 1;
}
}
...
<div class="row">
#{Html.RenderPartial("RetrieveCatalogs", Model.Offers.AvailableBrowseItems);}
</div>
Partial View
#model List<OrderServiceClient.Models.BrowseDataItemModel>
#if (Model != null)
{
<div class="col-lg-7 col-md-6 col-sm-12 offers-container" id="shoppingcatalog">
<table class="table table-striped">
<tr>
<th>Data Type</th>
<th>Name</th>
<th>Price</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr class="offerList">
<td>#item.DataType</td>
<td>#item.Name</td>
<td>#string.Format($"{item.Amount,0:C2}")</td>
<td><a class="addService" dataType="#item.DataType" serviceId="#item.ServiceId" serviceName="#item.Name" amount="#item.Amount">Add</a></td>
</tr>
}
</table>
</div>
}
Controller
public PartialViewResult ShowCatalog()
{
RetrieveCatalogModel rcm = new RetrieveCatalogModel();
rcm.AvailableBrowseItems = new List<BrowseDataItemModel>();
return PartialView("RetrieveCatalogs", rcm.AvailableBrowseItems);
}
[HttpPost]
public PartialViewResult ShowCatalog(string catalogName, Guid conversationid)
{
if (catalogName.Equals("Offers"))
{
RetrieveOffersModel offers = new RetrieveOffersModel();
var response = BrowseShoppingHelper.RetrieveOffers(conversationid, _client);
offers.AvailableBrowseItems = BuildOffersBrowseDataItemsModel(response).ToList();
return PartialView("RetrieveCatalogs", offers.AvailableBrowseItems);
}
else
{
var prodctFolderResponse = BrowseShoppingHelper.RetrieveProductFolders(conversationid, _client);
var output = (RetrieveProductFoldersCommandOutput) prodctFolderResponse.Body.Output;
RetrieveProductsModel rpm = new RetrieveProductsModel{Name = catalogName, AvailableBrowseItems = new List<BrowseDataItemModel>()};
foreach (var folder in output.Folders)
{
if (!catalogName.Equals(folder.Name)) continue;
var items = BuildProductBrowseItemsModel(
(RetrieveProductsInGroupCommandOutput) BrowseShoppingHelper
.RetrieveProductItems(conversationid, _client, folder).Body.Output);
rpm.AvailableBrowseItems.AddRange(items);
break;
}
return PartialView("RetrieveCatalogs", rpm.AvailableBrowseItems);
}
}
Script file
$(function() {
$("[name=catalogName]").on('change',
function () {
var $radio = $(this);
var myurl = "ShowCatalog?catalogName=" + $radio.val() + "&conversationid=" + $(this).attr('conversationid');
console.log("Catalog item is: " + $radio.val() + " and id is: " + $(this).attr('conversationid'));
$.ajax({
url: myurl,
type: 'POST',
success: function (data) {
$("#shoppingcatalog").html(data);
}
});
});
});

#Html.DropDownListFor and #HtmlPagedListPager

I've created an MVC website using VS2013. My view contains a a dropdownlist for "Import Status" and a paging control as shown below:
My view is as follows:
#model PagedList.IPagedList<ESBAMPortal.Models.SupplierStockUpdateViewModel>
#using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet"
type="text/css" />
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
SelectList itemsPerPageList = ESBAMPortal.Helpers.DefaultValues.ItemsPerPageList;
}
<h2>Stock Updates</h2>
<div class="container-fluid">
<div class="row">
<div id="instruction" class="col-md-6 pull-left">
<h5>Click the 'Process Start' datetime to see a copy of the file received</h5>
</div>
</div>
<div class="row" id="filters">
<div id="filtersDropdown" class="col-md-6 pull-right">
#using (Html.BeginForm("Index", "SupplierStockUpdate", FormMethod.Get, new { #class = "pull-right" }))
{
{
<span>
#Html.Label("Import Status:")
#Html.DropDownListFor(m => m.FirstOrDefault().SelectedStatusId, Model.FirstOrDefault().StatusItems)
</span>
<span>
#Html.Label("Items per page:")
#Html.DropDownList("ItemsPerPage", itemsPerPageList,
new { #id = "ItemsPerPageList" })
</span>
}
<input type="submit" value="Refresh" />
}
</div>
</div>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>#Html.DisplayNameFor(model => model.FirstOrDefault().ReceivedFilename)</th>
<th>#Html.ActionLink("Proces Start", "Index", new { sortOrder = ViewBag.TimeReceivedSort, itemsPerPage = itemsPerPageList.SelectedValue })</th>
<th>#Html.DisplayNameFor(model => model.FirstOrDefault().TimeProductLookupResponse)</th>
<th>#Html.DisplayNameFor(model => model.FirstOrDefault().TimeInsertResponse)</th>
<th>#Html.DisplayNameFor(model => model.FirstOrDefault().ImportStatus)</th>
<th>#Html.DisplayNameFor(model => model.FirstOrDefault().ImportErrors)</th>
<th>#Html.ActionLink("Supplier", "Index", new { sortOrder = ViewBag.SupplierSort })</th>
<th>#Html.DisplayNameFor(model => model.FirstOrDefault().RowsInserted)</th>
<th>#Html.DisplayNameFor(model => model.FirstOrDefault().TimeOfExceptionString)</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(model => item.ReceivedFilename)</td>
<td>
#Html.ActionLink(item.TimeReceived.ToString(), "Index", "ArchivedMsg",
new { interchangeId = item.InterchangeId }, null)
</td>
<td>#Html.DisplayFor(model => item.TimeProductLookupResponse)</td>
<td>#Html.DisplayFor(model => item.TimeInsertResponse)</td>
<td>#Html.DisplayFor(model => item.ImportStatus)</td>
<td>#Html.DisplayFor(model => item.ImportErrors)</td>
<td>#Html.DisplayFor(model => item.SupplierCode)</td>
<td>#Html.DisplayFor(model => item.RowsInserted)</td>
#{
if (item.TimeOfExceptionString.IsDateTime())
{
<td>#Html.ActionLink(item.TimeOfExceptionString, "IndexForInterchangeId", "Fault", new { interchangeId = item.InterchangeId }, null) </td>
}
else
{
<td>NA</td>
}
}
</tr>
}
</tbody>
</table>
<div id="pageControllFooter" class="container-fluid">
<div class="row">
<div id="pageButtons" class="col-md-2">
#Html.PagedListPager(Model, page => Url.Action("Index", new { page, itemsPerPage = ViewBag.CurrentItemsPerPage }))
</div>
</div>
<div class="row">
<div id="pageDesc" class="col-md-2">
#if (Model != null
&& Model.PageCount > 0)
{
<div>
Page #(Model.PageCount < Model.PageNumber
? 0 : Model.PageNumber)
of #Model.PageCount
</div>
}
</div>
</div>
</div>
Model:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace ESBAMPortal.Models
{
public class SupplierStockUpdateViewModel
{
public string ActivityID { get; set; }
public string InterchangeId { get; set; }
[DisplayName("Received")]
public DateTime? TimeReceived { get; set; }
[DisplayName("DW Product Requested")]
public DateTime? TimeProductLookupRequested { get; set; }
[DisplayName("DW Product Response")]
public DateTime? TimeProductLookupResponse { get; set; }
[DisplayName("CIMS Insert Requested")]
public DateTime? TimeInsertRequested { get; set; }
[DisplayName("CIMS Insert Response")]
public DateTime? TimeInsertResponse { get; set; }
[DisplayName("Supplier Code")]
public string SupplierCode { get; set; }
[DisplayName("CIMS Records Updated")]
public int? RowsInserted { get; set; }
public string ReceivedFilename { get; set; }
public DateTime? TimeOfException { get; set; }
public string TimeOfExceptionString { get; set; }
public double TotalDuration { get; set; }
public string ImportStatus { get; set; }
public int? ImportErrors { get; set; }
public DateTime LastModified { get; set; }
//constructor
public SupplierStockUpdateViewModel()
{
_statuses = new List<Status>();
_statuses.Add(new Status()
{
Id = 1,
Name = "All"
});
_statuses.Add(new Status()
{
Id = 2,
Name = "Pending"
});
_statuses.Add(new Status()
{
Id = 3,
Name = "Complete"
});
}
private readonly List<Status> _statuses;
public class Status
{
public int Id { get; set; }
public string Name { get; set; }
}
[Display(Name = "Status")]
public int SelectedStatusId { get; set; }
//our VM has a select list
public IEnumerable<SelectListItem> StatusItems
{
get { return new SelectList(_statuses, "Id", "Name"); }
}
}
}
Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ESBAMPortal.DataLayer;
using ESBAMPortal.Models;
using PagedList;
using ESBAMPortal.DomainClasses.BAM;
using System.IO;
namespace ESBAMPortal.Controllers
{
public class SupplierStockUpdateController : Controller
{
private IRepository<SupplierStockUpdate> SupplierStockUpdateRepository;
public SupplierStockUpdateController(BAMContext context)
{
this.SupplierStockUpdateRepository = new EFRepository<SupplierStockUpdate>(context);
}
private string TranslateStatusFilter(int status)
{
string ret = "";
switch (status)
{
case 2:
ret = "Pending";
break;
case 3:
ret = "Complete";
break;
}
return ret;
}
// GET: /SupplierStock/
public ActionResult Index(string sortOrder, int? page, int? itemsPerPage, SupplierStockUpdateViewModel vm)
{
string statusFilter = TranslateStatusFilter(vm.SelectedStatusId);
ViewBag.CurrentItemsPerPage = itemsPerPage;
ViewBag.TimeReceivedSort = String.IsNullOrEmpty(sortOrder) ? "timeReceived" : "";
ViewBag.SupplierSort = sortOrder == "supplier" ? "supplier_desc" : "supplier";
var query = this.SupplierStockUpdateRepository.GetAll();
switch (sortOrder)
{
case "timeReceived":
query = query.OrderBy(f => f.TimeReceived);
break;
case "supplier":
query = query.OrderBy(f => f.SupplierCode);
break;
case "supplier_desc":
query = query.OrderByDescending(f => f.SupplierCode);
break;
default:
query = query.OrderByDescending(f => f.TimeReceived);
break;
}
if (statusFilter == "Pending" || statusFilter == "Complete")
{
query = query.Where(x => x.ImportStatus == statusFilter);
}
//shove results into view model
List<SupplierStockUpdateViewModel> SupplierStockUpdatesVM = new List<SupplierStockUpdateViewModel>();
DateTime start = new DateTime();
DateTime end = new DateTime();
foreach (var item in query.ToList())
{
SupplierStockUpdateViewModel SupplierStockUpdateVM = new SupplierStockUpdateViewModel();
SupplierStockUpdateVM.ActivityID = item.ActivityID;
SupplierStockUpdateVM.InterchangeId = item.InterchangeId;
SupplierStockUpdateVM.TimeReceived = item.TimeReceived;
SupplierStockUpdateVM.TimeProductLookupRequested = item.TimeProductLookupRequested;
SupplierStockUpdateVM.TimeProductLookupResponse = item.TimeProductLookupResponse;
SupplierStockUpdateVM.TimeInsertRequested = item.TimeInsertRequested;
SupplierStockUpdateVM.TimeInsertResponse = item.TimeInsertResponse;
SupplierStockUpdateVM.SupplierCode = item.SupplierCode;
SupplierStockUpdateVM.RowsInserted = item.RowsInserted;
SupplierStockUpdateVM.TimeOfException = item.TimeOfException;
SupplierStockUpdateVM.ReceivedFilename = item.ReceivedFilename;
SupplierStockUpdateVM.ImportStatus = item.ImportStatus;
SupplierStockUpdateVM.ImportErrors = item.ImportErrors;
start = (item.TimeReceived == null) ? DateTime.MinValue : (System.DateTime)item.TimeReceived;
if (item.TimeOfException == null)
{
SupplierStockUpdateVM.TimeOfExceptionString = "NA";
if (item.TimeInsertResponse != null)
{
end = (System.DateTime)item.TimeInsertResponse;
}
else
{
//no exception but process still running so give a duration of 0
end = start;
}
}
else
{
SupplierStockUpdateVM.TimeOfExceptionString = item.TimeOfException.ToString();
end = (System.DateTime)item.TimeOfException;
}
if (start == DateTime.MinValue)
{
SupplierStockUpdateVM.TotalDuration = 0;
}
else
{
SupplierStockUpdateVM.TotalDuration = (end - start).TotalSeconds;
}
SupplierStockUpdatesVM.Add(SupplierStockUpdateVM);
}
int pageSize = (itemsPerPage ?? 10);
int pageNumber = (page ?? 1);
return View(SupplierStockUpdatesVM.ToPagedList(pageNumber, pageSize));
}
}
}
On clicking the "Refesh" button all works ok, the filtered Import Status is passed to the controller. My problem is, when paging by clicking the boxes of the page controls, the value 0 is always passed in the VM.SelectedStatusId field.
I've tried changing the view's call to explicitly pass the SelectedStatusId as follows:
#Html.PagedListPager(Model, page => Url.Action("Index", new { page, itemsPerPage = ViewBag.CurrentItemsPerPage, Model.FirstOrDefault().SelectedStatusId }))
...and adding a corrsponding int param on the controller action but still this was coming through as 0.
Could anyone let me know where I'm going wrong? Thanks.
Upon first look, it seems you have coded the following line wrong.
#Html.PagedListPager(Model, page => Url.Action("Index", new { page, itemsPerPage = ViewBag.CurrentItemsPerPage, Model.FirstOrDefault().SelectedStatusId }))
You have forgotten the return parameter for the last parameter in you expression. Try the following
#Html.PagedListPager(Model, page => Url.Action("Index", new { page, itemsPerPage = ViewBag.CurrentItemsPerPage, vm = Model.FirstOrDefault().SelectedStatusId }))
note the "vm = "
Let me know if that works!
The vm.SelectedStatusId is passed into the action when the user clicks the "Refresh" button on the view.
I assign the selected status to a viewbag property in the Index action of the controller:
ViewBag.StatusId = vm.SelectedStatusId;
When the user later pages through the results, I pass in the previously selected status filter, from the viewbag:
#Html.PagedListPager(Model, page => Url.Action("Index", new { page, itemsPerPage = ViewBag.CurrentItemsPerPage, selectedStatusId = ViewBag.StatusId }))

I want to fill city dropdown automatically from database according to state dropdown in ASP.NET MVC and Ajax

I want to get city list from database and store selected city's id into database. I have used Ajax to call function of member class. But it is not working, please help me to sort this out.
Here is my Model:
[Required]
[Display(Name = "State")]
public int stateid { get; set; }
public string stateName { get; set; }
public List<SelectListItem> stateList = new List<SelectListItem>();
[Required]
[Display(Name = "City")]
public int Cityid { get; set; }
public string CityName { get; set; }
public List<SelectListItem> CityList = new List<SelectListItem>();
clubDataContext cd = new clubDataContext();
public void insertmember(M_Reg m)
{
M_Registarion m1 = new M_Registarion();
m1.M_StatteId = m.stateid;
m1.M_CityId = 1; //temporary storing 1
cd.M_Registarions.InsertOnSubmit(m1);
cd.SubmitChanges();
}
Here is my controller:
[HttpGet]
public ActionResult Registration()
{
var model = new M_Reg();
using (var db = new clubDataContext())
{
model.stateList = content2.Select(c2 => new SelectListItem
{
Text = c2.S_Name,
Value = c2.S_ID.ToString()
}).ToList();
}
return View(model);
}
[HttpGet]
public SelectList getCity(int stateId, int selectCityId)
{
var db = new clubDataContext();
var model = new M_Reg();
var content = from p in db.CityInfos where p.S_ID == stateId
select new { p.C_ID, p.C_Name };
model.CityList = content.Select(c => new SelectListItem
{
Text = c.C_Name,
Value = c.C_ID.ToString()
}).ToList();
return new SelectList(model.CityList, "Value", "Text", selectCityId);
}
View:
Razor code:
<div class="editor-label">
#Html.LabelFor(m=> m.stateid)
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.stateid,Model.stateList)
#Html.ValidationMessageFor(m => m.stateid)
</div>
<div class="editor-label">
#Html.LabelFor(m=> m.Cityid)
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.Cityid, Model.CityList)
#Html.ValidationMessageFor(m => m.Cityid, Model.c)
</div>
Ajax code:
$("#stateid").change(function () {
$.ajax({
type: "POST",
url: '#Url.Action("Member", "getCity")',
data: { stateId: $("#stateid > option:selected").attr("value") },
success: function (data) {
var items = [];
items.push("<option>--Choose Your City--</option>");
$.each(data, function () {
items.push("<option value=" + this.Value + ">" + this.Text + "</option>");
});
$("#Cityid").html(items.join(' '));
}
})
});
Try Like This
Here Controller :
public JsonResult functionname(){
List<string> City = new List<string>();
var DBcity = yourDBentity.TableName.Where(x=>x.columnname==condition).select(x=>x.city);
foreach(var i in DBcity){
City.Add(i);
}
return Json(City, JsonRequestBehavior.AllowGet);
}
Jquery:
$(document).ready(function (result) {
$.post('/yourcontorller/functionname', {parameter : parameter }, function (result) {
$.each(result, function (key, value) {
$('#yourDropdownId').append($("<option></option>").html(value).val(value));
});
},"json");
});
Finally, this code works...
Model Class:
clubDataContext _db = new clubDataContext();
[Required]
[Display(Name="City")]
public virtual string icityid { get; set; }
public List<SelectListItem> cityList = new List<SelectListItem>();
[Required]
[Display(Name = "State")]
public virtual string istateid { get; set; }
public SelectList getState()
{
IEnumerable<SelectListItem> stateList = (from m in _db.StateInfos select m).AsEnumerable().Select(m => new SelectListItem() { Text = m.S_Name, Value = m.S_ID.ToString() });
return new SelectList(stateList, "Value", "Text", istateid);
}
View :
<div class="editor-label">
#Html.LabelFor(m=> m.istateid)
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.istateid,Model.getState(),"--Choose your State--")
#Html.ValidationMessageFor(m => m.istateid)
</div>
<div class="editor-label">
#Html.LabelFor(m=> m.icityid)
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.icityid,Model.cityList,"--Choose your City--")
#Html.ValidationMessageFor(m => m.icityid)
</div>
Ajax:
$('#istateid').change(function(){
$.ajax({
type:"POST",
url:'#Url.Action("getCityJson","Member")',
data: { stateId : $("#istateid > option:selected").attr("value")},
success: function (data){
var items= [];
$.each(data,function(){
items.push("<option value=" + this.Value + ">" + this.Text + "</option>");
});
$("#icityid").html(items.join(' '));
}
})
});
And Controller:
[HttpPost]
public JsonResult getCityJson(string stateId, string selectCityId=null)
{
return Json(getCity(stateId, selectCityId));
}
public SelectList getCity(string stateId, string selectCityId = null)
{
var db = new clubDataContext();
IEnumerable<SelectListItem> cityList = new List<SelectListItem>();
if (!string.IsNullOrEmpty(stateId))
{
int _stateId = Convert.ToInt32(stateId);
cityList = (from m in db.CityInfos where m.S_ID == _stateId select m).AsEnumerable().Select(m => new SelectListItem() { Text = m.C_Name, Value = m.C_ID.ToString() });
}
return new SelectList(cityList, "Value", "Text", selectCityId);
}

How do I sort a list of entities using ViewModel instead of ViewBag?

I am using ViewBag to help me sort a list of students found within a list of classes. I have read that ViewBag is something that should be avoided at all costs attempting to build a proper MVC project.
When viewing the page that the below code generates, one is able to sort through a list of students in a variety of ways (First Name by alpha, Last name by alpha, date enrolled, etc), and view only a limited number of students per page.
I do not know exactly how to translate my code to use a ViewModel in place of my current design.
I am using the following code:
Model (Student):
public class Student
{
public int StudentID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public string Email { get; set; }
public DateTime EnrollmentDate { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
Model (Enrollment):
public class Enrollment
{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public string Grade { get; set; } // pass, fail, incomplete
public virtual Course Course { get; set; }
public virtual Student Student { get; set; }
}
(I also have a Course model, but it is not referenced directly by the controller below, so I will omit it here - if it is necessary to show its details, please let me know.)
Controller:
public class StudentController : Controller
{
private SchoolContext db = new SchoolContext();
//
// GET: /Student/
public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page)
{
ViewBag.CurrentSort = sortOrder;
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "Name desc" : "";
ViewBag.DateSortParm = sortOrder == "Date" ? "Date desc" : "Date";
ViewBag.FNameSortParm = sortOrder == "FName" ? "FName desc" : "FName";
ViewBag.EmailSortParm = sortOrder == "Email" ? "Email desc" : "Email";
if (Request.HttpMethod == "GET")
{
searchString = currentFilter;
}
else
{
page = 1;
}
ViewBag.CurrentFilter = searchString;
var students = from s in db.Students
select s;
if (!String.IsNullOrEmpty(searchString))
{
students = students.Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper())
|| s.FirstMidName.ToUpper().Contains(searchString.ToUpper()));
}
switch (sortOrder)
{
case "Name desc":
students = students.OrderByDescending(s => s.LastName);
break;
case "Date":
students = students.OrderBy(s => s.EnrollmentDate);
break;
case "Date desc":
students = students.OrderByDescending(s => s.EnrollmentDate);
break;
case "FName":
students = students.OrderBy(s => s.FirstMidName);
break;
case "FName desc":
students = students.OrderByDescending(s => s.FirstMidName);
break;
case "Email":
students = students.OrderBy(s => s.Email);
break;
case "Email desc":
students = students.OrderByDescending(s => s.Email);
break;
default:
students = students.OrderBy(s => s.LastName);
break;
}
int pageSize = 4;
int pageNumber = (page ?? 1);
return View(students.ToPagedList(pageNumber, pageSize));
}
And my view:
#model PagedList.IPagedList<MVCAppName.Models.Student>
#{
ViewBag.Title = "Students";
}
<h2>Students</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
#using (Html.BeginForm())
{
<p>
Find by name: #Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
<input type="submit" value="Search" /></p>
}
<table>
<tr>
<th></th>
<th>
#Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.ActionLink("First Name", "Index", new { sortOrder = ViewBag.FNameSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.ActionLink("Email", "Index", new { sortOrder = ViewBag.EmailSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.ActionLink("Enrollment Date", "Index", new { sortOrder = ViewBag.DateSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.StudentID }) |
#Html.ActionLink("Details", "Details", new { id=item.StudentID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.StudentID })
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Email)
</td>
<td>
#Html.DisplayFor(modelItem => item.EnrollmentDate)
</td>
</tr>
}
</table>
<div>
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber)
of #Model.PageCount
#if (Model.HasPreviousPage)
{
#Html.ActionLink("<<", "Index", new { page = 1, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter })
#Html.Raw(" ");
#Html.ActionLink("< Prev", "Index", new { page = Model.PageNumber - 1, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter })
}
else
{
#:<<
#Html.Raw(" ");
#:< Prev
}
#if (Model.HasNextPage)
{
#Html.ActionLink("Next >", "Index", new { page = Model.PageNumber + 1, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter })
#Html.Raw(" ");
#Html.ActionLink(">>", "Index", new { page = Model.PageCount, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter })
}
else
{
#:Next >
#Html.Raw(" ")
#:>>
}
</div>
The controller should handle the sorting, the view just displays the data. You already do that, so you need only to define the view model, which preivosuly you'd put in the ViewBag
public class ShowStudentsModel
{
public string CurrentSort {get;set;}
public string NameSortParm {get;set;}
//and so on... you create a property for each property set in the ViewBag
public IEnumerable<Student> Students {get;set;}
}
Then in the view
#model ShowStudentsModel
#foreach(var item in Model.Students)
{
//html code
}
I think the nicest would be to subclass the PagedList.IPagedList<T> which you are using and add sort order there. So at the end of your controller you'd have this:
return View(students.ToPagedList(pageNumber, pageSize, sortOrder));
But if you're not willing to do that, then you could simply create a new ViewModel class to hold the PagedList (your current model) as well as the supplemental data you need (i.e. your sort order).
return View(new SortedStudents
{
Students = students.ToPagedList(pageNumber, pageSize);
SortOrder = sortOrder
});
With the SortedStudents defined like this:
public class SortedStudents
{
public PagedList.IPagedList<MVCAppName.Models.Student> Students { get; set; }
public string SortOrder { get; set; }
}
You could make a wrapper around your Students class
public class StudentWrapper
{
List<Students> studentList { get; set; }
String currentSort { get; set; }
public StudentWrapper() {
studentlist = new List<Students>();
}
In your controller, you would create a new StudentWrapper
StudentWrapper sw = new StudentWrapper();
and set the list of students:
sw.studentList = db.Students.ToList();
and the sortOrder
sw.currentSort = SortOder;
You pass this model to your View
return View(sw);
in your View, you would use the StudentWrapper
#model List<MVCAppName.Models.StudentWrapper>
I dont know how your paging works, so you would have to figure this out.
But i dont see any problems in using the ViewBag either.

Resources