I am trying to add a grid to a table of data in my MVC application but keep getting the following error message:
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[AssociateTracker.Models.Associate]', but this dictionary requires a model item of type 'PagedList.IPagedList`1[AssociateTracker.Models.Associate]'.
View:
#model PagedList.IPagedList<AssociateTracker.Models.Associate>
#{
ViewBag.Title = "ViewAll";
}
<h2>View all</h2>
<table>
<tr>
<th>First name</th>
<th>#Html.ActionLink("Last Name", "ViewAll", new { sortOrder=ViewBag.NameSortParm, currentFilter=ViewBag.CurrentFilter })</th>
<th>Email address</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>#item.FirstName</td>
<td>#item.LastName</td>
<td>#item.Email</td>
<td>
#Html.ActionLink("Details", "Details", new { id = item.AssociateId }) |
#Html.ActionLink("Edit", "Edit", new { id = item.AssociateId }) |
#Html.ActionLink("Delete", "Delete", new { id=item.AssociateId })
</td>
</tr>
}
</table>
<div>
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber)
of #Model.PageCount
#if (Model.HasPreviousPage)
{
#Html.ActionLink("<<", "ViewAll", new { page = 1, sortOrder = ViewBag.CurrentSort, currentFilter=ViewBag.CurrentFilter })
#Html.Raw(" ");
#Html.ActionLink("< Prev", "ViewAll", new { page = Model.PageNumber - 1, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter })
}
else
{
#:<<
#Html.Raw(" ");
#:< Prev
}
#if (Model.HasNextPage)
{
#Html.ActionLink("Next >", "ViewAll", new { page = Model.PageNumber + 1, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter })
#Html.Raw(" ");
#Html.ActionLink(">>", "ViewAll", new { page = Model.PageCount, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter })
}
else
{
#:Next >
#Html.Raw(" ")
#:>>
}
</div>
I have checked against Microsoft's Contosos University example but can't spot any differences. Can anyone else see what the issue might be?
The error message seems pretty self explanatory. Your view expects an IPagedList<Associate> instance but you are passing a List<Associate> from your controller action.
So inside your controller action you need to provide the proper model to the view:
public ActionResult Index(int? page)
{
List<Associate> associates = GetAssociates();
IPagedList<Associate> model = associates.ToPagedList(page ?? 1, 10);
return View(model);
}
I used the extension method from here. The IPagedList<T> is not a standard type built in ASP.NET MVC so you will have to reference the proper assemblies.
Related
I am having partial success searching / grouping data through a viewmodel:
Partial Success:
URL Value
If I search on "B"
https://localhost:7207/Class01Name/Index2?String02NameSelected=B&SearchString=
Problem:
Not filtering data...simply changes pull down menu back to "All," displaying all data. Data not filtered.
**Question:
**
What in the code has to be changed to have the data filtered successfully?
Question is based on Tutorial at:
https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/search?view=aspnetcore-6.0
Model
using System.ComponentModel.DataAnnotations; // Date Format
namespace Project01Name.Models
{
public class Class01Name
{
public int Id { get; set; }
public string? String01Name { get; set; }
public string? String02Name { get; set; }
public int? Int01Name { get; set; }
public bool? Bool01Name { get; set; }
[DataType(DataType.Date)]
public DateTime? DateTime01Name { get; set; }
}
}
**
View Model
**
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace Project01Name.Models.ViewModelsName
{
public class SearchByGroupName
{
public List<Class01Name>? Class01NameList { get; set; } // A list of movies.
public SelectList? String02NameSelection { get; set; } // A SelectList containing the list of genres. This allows the user to select a genre from the list.
public string? String02NameSelected { get; set; } // MovieGenre, which contains the selected genre.
public string? SearchString { get; set; } // SearchString, which contains the text users enter in the search text box.
}
}
Controller Action Method
// GET: String01Names
public async Task<IActionResult> Index2(string class01NameGroup, string searchString)
{
// Use LINQ to get list of genres.
IQueryable<string> string02NameQuery = from m in _context.Class01Name
orderby m.String02Name
select m.String02Name;
var selectVariable = from m in _context.Class01Name
select m;
if (!string.IsNullOrEmpty(searchString))
{
selectVariable = selectVariable.Where(s => s.String01Name!.Contains(searchString));
}
if (!string.IsNullOrEmpty(class01NameGroup))
{
selectVariable = selectVariable.Where(x => x.String02Name == class01NameGroup);
}
var string02NameVM = new SearchByGroupName
{
String02NameSelection = new SelectList(await string02NameQuery.Distinct().ToListAsync()),
Class01NameList = await selectVariable.ToListAsync()
};
return View(string02NameVM);
}
View
#model Project01Name.Models.ViewModelsName.SearchByGroupName
#{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-action="Index2" method="get">
<div class="form-actions no-color">
<p>
<select asp-for="String02NameSelected" asp-items="Model.String02NameSelection"> <option value="">All</option></select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" value="Filter" />
#*<input type="submit" value="Search" class="btn btn-default" /> |
<a asp-action="Index">Back to Full List</a> *#
</p>
</div>
</form>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].String01Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].String02Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].Int01Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].DateTime01Name)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Class01NameList)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.String01Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.String02Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Int01Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.DateTime01Name)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="#item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Partial Success:
URL Value
If I search on "B"
https://localhost:7207/Class01Name/Index2?String02NameSelected=B&SearchString=
Problem:
Not filtering data...simply changes pull down menu back to "All," displaying all data. Data not filtered.
**Question:
**
What in the code has to be changed to have the data filtered successfully?
Question is based on Tutorial at:
https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/search?view=aspnetcore-6.0
Not filtering data...simply changes pull down menu back to "All,"
displaying all data. Data not filtered.
**Question: ** What in the code has to be changed to have the data filtered successfully?
Well, seems you wanted to implement searching functionality in way, so that you can filter with the dropdown and search box and finally if you select All as dropdown value you want to load all the list without any filter and shorting means the full list which comes at first view.
If so, you need to use javascript for your dropdown change event as cshtml doesn't deal with change event. In addition, as you are using asp.net core MVC which would return HTML View altough, we need json data for Ajax reponse but we are would bee getting HTML View. So Ajax success Function will through an error where we would use filter with All parameter.
Modification Required:
Javascript:
#section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
$("#allId").change(function () {
alert("Click");
var allId = $('#allId').val();
console.log(allId);
if (allId == "All") {
alert("Alert");
$.ajax({
url: 'http://localhost:5094/Search/Index2',
type: 'GET',
dataType: 'json',
data: { String02NameSelected: "All", searchString: "" },
success: function (response) {
},
error: function () {
window.location.href = "#Url.Action("Index2", "Search")?String02NameSelected=All&SearchString=";
}
});
}
});
});
</script>
}
Note:
As you can see, in success function we are doing nothing, because it will always throuh an error because we are not returning json. Thus, we will work in error section. indow.location.href = "#Url.Action("Index2", "Search")?String02NameSelected=All&SearchString=";. Here, for your understanding, we will call this function when we select All as our dropdown value in that scenario, we will pass All and nothing , nothing will convert into null and all will be our search key.
Modify Your Existing View:
In your existing view, replace blow dropdown code snippet , means the select items
<select asp-for="String02NameSelected" id="allId" asp-items="Model.String02NameSelection"> <option value="All">All</option></select>
Note: If you notice I hav introduced a id id="allId" which will be using on dropdown change event.
Controller:
public async Task<IActionResult> Index2(string String02NameSelected, string searchString)
{
if (String02NameSelected == "All" && searchString == null)
{
var dataWithoutfileter = new SearchByGroupName();
dataWithoutfileter.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
dataWithoutfileter.Class01NameList = listOfClass01Name;
return View(dataWithoutfileter);
}
if (!String.IsNullOrEmpty(String02NameSelected) && String02NameSelected !="All")
{
var objOfClass = new SearchByGroupName();
var string02NameQuery = listOfClass01Name.Where(m => m.String01Name.ToLower().Contains(String02NameSelected.ToLower()) || m.String02Name.ToLower().Contains(String02NameSelected.ToLower()));
objOfClass.Class01NameList = string02NameQuery.ToList();
objOfClass.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
return View(objOfClass);
}
if (!String.IsNullOrEmpty(searchString))
{
var objOfClass = new SearchByGroupName();
var string02NameQuery = listOfClass01Name.Where(m => m.String01Name.ToLower().Contains(searchString.ToLower()) || m.String02Name.ToLower().Contains(searchString.ToLower()));
objOfClass.Class01NameList = string02NameQuery.ToList();
objOfClass.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
return View(objOfClass);
}
//First loading
var objSearchByGroupName = new SearchByGroupName();
objSearchByGroupName.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
objSearchByGroupName.Class01NameList = listOfClass01Name;
return View(objSearchByGroupName);
}
}
Complete Demo:
Full Controller With Seed Model Class Value:
public class SearchController : Controller
{
public static List<Class01Name> listOfClass01Name = new List<Class01Name>()
{
new Class01Name() { Id =101, String01Name ="Titanic",String02Name = "Romantic", Int01Name =01, Bool01Name = false, DateTime01Name = new DateTime(2023-01-15) },
new Class01Name() { Id =102, String01Name ="Forest gump",String02Name = "Motivational", Int01Name =02, Bool01Name = true, DateTime01Name = new DateTime(2023-01-12) },
new Class01Name() { Id =103, String01Name ="Spider Man",String02Name = "Action", Int01Name =03, Bool01Name = false, DateTime01Name = new DateTime(2023-01-10) },
new Class01Name() { Id =104, String01Name ="Harry Potter",String02Name = "Suspense", Int01Name =04, Bool01Name = true, DateTime01Name = new DateTime(2023-01-13)},
};
public List<SelectListItem> String02NameSelectionList = new List<SelectListItem>()
{
new SelectListItem { Text = "Motivational", Value = "Motivational" },
new SelectListItem { Text = "Romantic", Value = "Romantic" },
new SelectListItem { Text = "Action", Value = "Action" },
new SelectListItem { Text = "Comedy", Value = "Comedy" }
};
public async Task<IActionResult> Index2(string String02NameSelected, string searchString)
{
if (String02NameSelected == "All" && searchString == null)
{
var dataWithoutfileter = new SearchByGroupName();
dataWithoutfileter.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
dataWithoutfileter.Class01NameList = listOfClass01Name;
return View(dataWithoutfileter);
}
if (!String.IsNullOrEmpty(String02NameSelected) && String02NameSelected !="All")
{
var objOfClass = new SearchByGroupName();
var string02NameQuery = listOfClass01Name.Where(m => m.String01Name.ToLower().Contains(String02NameSelected.ToLower()) || m.String02Name.ToLower().Contains(String02NameSelected.ToLower()));
objOfClass.Class01NameList = string02NameQuery.ToList();
objOfClass.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
return View(objOfClass);
}
if (!String.IsNullOrEmpty(searchString))
{
var objOfClass = new SearchByGroupName();
var string02NameQuery = listOfClass01Name.Where(m => m.String01Name.ToLower().Contains(searchString.ToLower()) || m.String02Name.ToLower().Contains(searchString.ToLower()));
objOfClass.Class01NameList = string02NameQuery.ToList();
objOfClass.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
return View(objOfClass);
}
//First loading
var objSearchByGroupName = new SearchByGroupName();
objSearchByGroupName.String02NameSelection = new SelectList(String02NameSelectionList, "Text", "Value");
objSearchByGroupName.Class01NameList = listOfClass01Name;
return View(objSearchByGroupName);
}
}
Full View:
#model DotNet6MVCWebApp.Controllers.SearchByGroupName
#{
ViewData["Title"] = "Index";
}
<form asp-action="Index2" method="get">
<div class="form-actions no-color">
<p>
<select asp-for="String02NameSelected" id="allId" asp-items="Model.String02NameSelection"> <option value="All">All</option></select>
Title: <input type="text" asp-for="SearchString" />
<input type="submit" name="searchString" />
</p>
</div>
</form>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].String01Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].String02Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].Int01Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Class01NameList[0].DateTime01Name)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Class01NameList)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.String01Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.String02Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Int01Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.DateTime01Name)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="#item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
#section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
$("#allId").change(function () {
alert("Click");
var allId = $('#allId').val();
console.log(allId);
if (allId == "All") {
alert("Alert");
$.ajax({
url: 'http://localhost:5094/Search/Index2',
type: 'GET',
dataType: 'json',
data: { String02NameSelected: "All", searchString: "" },
success: function (response) {
},
error: function () {
window.location.href = "#Url.Action("Index2", "Search")?String02NameSelected=All&SearchString=";
}
});
}
});
});
</script>
}
Output:
I have been using Ajax to show partial pages in my application.
I would like to ask if it's possible to set the display to none when the user click again the link generated by #Ajax.ActionLink()?
Here's my code:
#model IEnumerable<RMSystem.Models.rms_referred_vw>
<table id="example">
<tbody>
#foreach(var rfp in Model){
<tr>
<td>
#Ajax.ActionLink(Convert.ToString(rfp.rf_id), "Edit_Ref", new { rf_id = rfp.rf_id },
new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.InsertBefore,
UpdateTargetId = "target6",
}, new {#style="color:darkblue", title = "Edit Referred Person"})
</td>
<td>#Html.DisplayFor(model => rfp.rf_badgeno)</td>
// more table cells
<td>
#Ajax.ActionLink("Details", "Details", new { rf_id = rfp.rf_id },
new AjaxOptions
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "show",
}, new {#style="color:darkblue", title = "Show More Details"})
</td>
</tr>
}
</tbody>
</table>
<div id="target6"></div>
<div id="show" style="width:250px;height:200px;margin-left:1000px;"></div>
That's my code Sir.
Controller:
public ActionResult Details(int rf_id = 0)
{
var check = db.rms_approval_route_vw.Where(s => s.rf_id == rf_id).FirstOrDefault();
try
{
if (check != null)
{
return PartialView(check);
}
}
catch (Exception) {
throw;
}
return Content("<script type='text/javascript'>alert('Waiting for regularization.');</script>");
}
Remove your #Html.ActionLink() and replace with (note the code below is for the 2nd link)
<td>Details<td>
and add a script
var details = $('#show');
$('.details').click(function() {
var self = $(this);
// Check if we have already loaded it
if (self.data('loaded'))
{
details.empty(); // clear contents
self.removeData('loaded'); // signal is no longer loaded
} else {
$.get('#Url.Action("Details")', { rf_id: $(this).data('id') }, function(data) {
details.html(data); // update the DOM
self.data('loaded', true); // signal its been loaded
});
}
});
i am new to mvc.. i have a task that, i have to bind data from existing table in sql using asp.net mvc3(Razor) Web Grid .. now i have to edit the data in webGrid.. i dont know how the edit operation is going to made... Plzz Help me out...
i have given my bind data.. plz let me know how to edit it...
Controller:
public ActionResult Index()
{
var list = GetList();
return View(list);
}
public List<Teacher> GetList()
{
var modelList = new List<Teacher>();
using (SqlConnection conn = new SqlConnection(#"Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Demo;Data Source=CIPL41\SQLEXPRESS"))
{
conn.Open();
SqlCommand dCmd = new SqlCommand("Select T_Id,T_Name,T_Address,Sub_Id from teacher", conn);
SqlDataAdapter da = new SqlDataAdapter(dCmd);
DataSet ds = new DataSet();
da.Fill(ds);
conn.Close();
for (int i = 0; i <= ds.Tables[0].Rows.Count - 1; i++)
{
var model = new Teacher();
model.T_Id = Convert.ToInt32(ds.Tables[0].Rows[i]["T_Id"]);
model.T_Name = ds.Tables[0].Rows[i]["T_Name"].ToString();
model.T_Address = ds.Tables[0].Rows[i]["T_Address"].ToString();
model.Sub_Id = ds.Tables[0].Rows[i]["Sub_Id"].ToString();
modelList.Add(model);
}
}
return modelList;
}
//
Index.cshtml
#model IEnumerable<MvcApplication1.Models.Teacher>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm("Index", "Teacher"))
{
<table>
<tr>
<th></th>
<th>
T_Id
</th>
<th>
T_Name
</th>
<th>
T_Address
</th>
<th>
Sub_Id
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.T_Id }) |
#* #Html.ActionLink("Details", "Details", new { id=item.T_Id }) |*#
#Html.ActionLink("Delete", "Delete", new { id=item.T_Id })
</td>
<td>
#Html.TextBox("T_Id", item.T_Id , new { #style = "width:100px;" })
</td>
<td>
#Html.TextBox("T_Name", item.T_Name , new { #style = "width:100px;" })
</td>
<td>
#Html.TextBox("T_Address", item.T_Address , new { #style = "width:100px;" })
</td>
<td>
#Html.TextBox("Sub_Id",item.Sub_Id,new { #style = "width:100px;"})
</td>
</tr>
}
</table>
Plz help me out....
Have a look at this tutorial http://www.asp.net/mvc/tutorials/getting-started-with-aspnet-mvc3/cs/examining-the-edit-methods-and-edit-view
I think it explains exactly what you're trying to do.
Why is it it gives error in return View(contacts.ToPagedList(pageNumber, pageSize)); statement the error in the Index method :
The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PhoneBook.Models;
using PagedList;
namespace PhoneBook.Controllers
{
public class ContactsController : Controller
{
private PhoneDBContext db = new PhoneDBContext();
//
// GET: /Contacts/
public ViewResult Index(string searchString, string sortOrder, Contact model, string currentFilter, int? page)
{
ViewBag.CurrentSort = sortOrder;
ViewBag.FNameSortParm = sortOrder == "FName asc"? "FName desc" : "FName asc";
ViewBag.DateSortParm = sortOrder == "Date asc" ? "Date desc" : "Date asc";
ViewBag.LNameSortParm = sortOrder == "LName asc" ? "LName desc" : "LName asc";
ViewBag.CompSortParm = sortOrder == "Company asc" ? "Company desc" : "Company asc";
ViewBag.MobSortParm = sortOrder == "Mob asc" ? "Mob desc" : "Mob asc";
ViewBag.TelSortParm = sortOrder == "Tel asc" ? "Tel desc" : "Tel asc";
if (Request.HttpMethod == "GET") { searchString = currentFilter; }
else {page = 1;}
ViewBag.CurrentFilter = searchString;
var contacts = from m in db.Contacts
select m;
switch (sortOrder)
{
case "FName desc":
contacts = contacts.OrderByDescending(s => s.FirstName);
break;
case "FName asc":
contacts = contacts.OrderBy(s => s.FirstName);
break;
case "LName desc":
contacts = contacts.OrderByDescending(s => s.LastName);
break;
case "LName asc":
contacts = contacts.OrderBy(s => s.LastName);
break;
case "Company desc":
contacts = contacts.OrderByDescending(s => s.Company);
break;
case "Company asc":
contacts = contacts.OrderBy(s => s.Company);
break;
case "Date desc":
contacts = contacts.OrderByDescending(s => s.DateAdded);
break;
case "Date asc":
contacts = contacts.OrderBy(s => s.DateAdded);
break;
case "Mob desc":
contacts = contacts.OrderByDescending(s => s.MobileNumber);
break;
case "Mob asc":
contacts = contacts.OrderBy(s => s.MobileNumber);
break;
case "Tel desc":
contacts = contacts.OrderByDescending(s => s.TelephoneNumber);
break;
case "Tel asc":
contacts = contacts.OrderBy(s => s.TelephoneNumber);
break;
}
if (!String.IsNullOrEmpty(searchString))
{
contacts = contacts.Where(s => s.LastName.ToUpper().Contains(searchString)||s.FirstName.ToUpper().Contains(searchString)||s.Company.ToUpper().Contains(searchString));
}
int pageSize = 3;
int pageNumber = (page ?? 1);
return View(contacts.ToPagedList(pageNumber, pageSize));
}
//
// GET: /Contacts/Details/5
public ViewResult Details(int id)
{
Contact contact = db.Contacts.Find(id);
return View(contact);
}
//
// GET: /Contacts/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Contacts/Create
[HttpPost]
public ActionResult Create(Contact contact)
{
if (ModelState.IsValid)
{
db.Contacts.Add(contact);
contact.DateAdded = DateTime.Now;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(contact);
}
//
// GET: /Contacts/Edit/5
public ActionResult Edit(int id=0)
{
Contact contact = db.Contacts.Find(id);
if (contact == null) { return HttpNotFound(); } // returns blank page if id is not valid
return View(contact);
}
//
// POST: /Contacts/Edit/5
[HttpPost]
public ActionResult Edit(Contact contact)
{
if (ModelState.IsValid)
{
db.Entry(contact).State = EntityState.Modified;
contact.DateAdded = DateTime.Now;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(contact);
}
//
// GET: /Contacts/Delete/5
public ActionResult Delete(int id)
{
Contact contact = db.Contacts.Find(id);
if (contact == null) { return HttpNotFound(); }
return View(contact);
}
//
// POST: /Contacts/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
Contact contact = db.Contacts.Find(id);
if (contact == null) { return HttpNotFound(); }
db.Contacts.Remove(contact);
db.SaveChanges();
return RedirectToAction("Index");
}
public ActionResult SearchIndex(string searchString)
{
var contacts = from m in db.Contacts
select m;
if (!String.IsNullOrEmpty(searchString))
{
contacts = contacts.Where(s => s.LastName.Contains(searchString));
}
return View(contacts);
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
below is the Index.cshtml code:
#model PagedList.IPagedList<PhoneBook.Models.Contact>
#{
ViewBag.Title = "Phone Book";
}
<p>
#using (Html.BeginForm()){
<p> Search: #Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
<input type="submit" value="Go" /></p>
}
</p>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
#Html.ActionLink("First Name", "Index", new { sortOrder=ViewBag.FNameSortParm, currentFilter=ViewBag.CurrentFilter })
</th>
<th>
#Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.LNameSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.ActionLink("Mobile Num", "Index", new { sortOrder = ViewBag.MobSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.ActionLink("Tel Num", "Index", new { sortOrder = ViewBag.TelSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.ActionLink("Company", "Index", new { sortOrder = ViewBag.CompSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.ActionLink("Date Added/Updated", "Index", new { sortOrder = ViewBag.DateSortParm, currentFilter = ViewBag.CurrentFilter })
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.MobileNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.TelephoneNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.Company)
</td>
<td>
#Html.DisplayFor(modelItem => item.DateAdded)
</td>
<td>
#Html.ActionLink("Details", "Details", new { id=item.ID })
#Html.ActionLink("Edit", "Edit", new { id=item.ID })
#Html.ActionLink("Delete", "Delete", new { id=item.ID })
</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>
Try the following three changes.
Put this code before the switch statement:
if (!String.IsNullOrEmpty(searchString))
{
contacts = contacts.Where(s => s.LastName.ToUpper().Contains(searchString)||s.FirstName.ToUpper().Contains(searchString)||s.Company.ToUpper().Contains(searchString));
}
Add a default case in your switch statement, and make it throw.
switch (sortOrder) {
case ...:
...
default:
throw new ArgumentException("Bad sort order specified", "sortOrder");
}
Use the type IOrderedQueryable<T>.
IOrderedQueryable<T> orderedContacts;
switch (sortOrder)
{
case "FName desc":
orderedContacts = contacts.OrderByDescending(s => s.FirstName);
break;
...
}
...
return View(orderedContacts.ToPagedList(pageNumber, pageSize));
return View(orderedContacts.ToList().ToPagedList(pageNumber, pageSize));
I'm implementing Troy Goode's PagedList in one of my views (ASP.NET MVC 3 Razor). The challenge I'm having is when I click on a page number link, the request is routed to my HttpGet method, which just returns the empty page (ready for input).
My View Model:
public class SearchViewModel
{
public SelectList IndustrySelectList { get; set; }
public IPagedList<KeyValuePair<string, SearchResult>> SearchResults { get; set; }
public PagingInfo PagingInfo { get; set; }
}
Controller:
[HttpGet]
public ViewResult Search(string searchTerm = "")
{
SearchViewModel vm = new SearchViewModel
{
IndustrySelectList = new SelectList(_Industries.AsEnumerable(), "IndustryId", "IndustryName"),
PagingInfo = new PagingInfo
{
CurrentPage = 1,
ItemsPerPage = 25,
TotalItems = 0
}
};
return View(vm);
}
[HttpPost]
public ActionResult Search(string[] industries, string searchTerm = "", int page = 1)
{
SearchViewModel vm = null;
_url = "http://localhost/MasterNode/masternode.cgi?zoom_query={" + searchTerm + "}&zoom_xml=1&zoom_page={startPage?}&zoom_per_page=1000";
StringBuilder sb = new StringBuilder();
int pageSize = 5;
if (string.IsNullOrEmpty(searchTerm))
{
vm = new SearchViewModel
{
IndustrySelectList = new SelectList(_Industries.AsEnumerable(), "IndustryId", "IndustryName")
};
}
else
{
_request = new SearchRequest(SearchRequest.EnvironmentTypes.Development, "", _url, searchTerm, SearchRequest.SearchType.AllWords, 1000);
sb.Append(GetResults(_url));
_results = new Dictionary<string, SearchResult>();
ParseResults(sb);
GetDetailInformationForResults(searchTerm);
vm = new SearchViewModel
{
IndustrySelectList = new SelectList(_Industries.AsEnumerable(), "IndustryId", "IndustryName"),
SearchResults = _results.ToList<KeyValuePair<string, SearchResult>>().ToPagedList(1, 25),
PagingInfo = new PagingInfo
{
CurrentPage = page,
ItemsPerPage = pageSize,
TotalItems = _results.Count()
}
};
}
return View(vm);
}
View:
#model MultiView.OmniGuide.ViewModels.SearchViewModel
#using MultiView.OmniGuide.HtmlHelpers
#using PagedList
#using PagedList.Mvc
#{
ViewBag.Title = "Search";
}
<link href="/Content/PagedList.css" rel="stylesheet" type="text/css" />
#using (Html.BeginForm("Search", "Home"))
{
#Html.HiddenFor(c => c.IndustrySelectList)
#Html.HiddenFor(c => c.PagingInfo)
#Html.HiddenFor(c => c.SearchResults)
<table width="70%">
<tr>
<td colspan="2" style="background: #fff">
<input id="searchTerm" name="searchTerm" type="text" class="SearchBox" style="width: 450px" />
<input type="submit" class="SearchButton" value=" " />
</td>
</tr>
<tr align="left">
<td align="left" style="background: #fff">
#Html.ActionLink("MultiView corporate site", "Search")
</td>
</tr>
<tr>
<td colspan="1" align="center" style="width: 450px">
#{
Html.Telerik().PanelBar()
.Name("searchPanel")
.Items(title =>
{
title.Add()
.Text("Filter by Industry")
.Content(() =>
{
#Html.RenderPartial("_Industry", #Model);
});
})
.Render();
}
</td>
</tr>
<tr><td colspan="2"></td></tr>
</table>
<br />
if (Model.SearchResults != null)
{
<table width="70%">
<tr>
<th>
Company Image
</th>
<th class="tableHeader">
Company Name Here
</th>
<th class="tableHeader">
Website
</th>
</tr>
#foreach (KeyValuePair<string, MultiView.OmniGuide.Models.SearchResult> itm in Model.SearchResults)
{
<tr>
<td align="left" style="width: 15%">
#itm.Value.DetailedInfo.LogoURL
</td>
<td align="left" style="width: 60%">
<p style="text-align: left">
#itm.Value.DetailedInfo.DescriptionAbbreviated
<br />
</p>
#Html.AnchorLink(itm.Value.FoundURL, itm.Value.FoundURL)
</td>
<td style="width: 25%">
#itm.Value.FoundURL
</td>
</tr>
}
</table>
#Html.PagedListPager((IPagedList)Model.SearchResults, page => Url.Action("Search", "Home", new { page }))
}
}
When text is supplied in the input box and the button is clicked, the requested is routed to the HttpPost method. In looking at the request.form values, all expected data but paging information is present.
?HttpContext.Request.Form.AllKeys
{string[5]}
[0]: "IndustrySelectList"
[1]: "PagingInfo"
[2]: "SearchResults"
[3]: "searchTerm"
[4]: "industries"
Any help with this would be very much appreciated!
By clicking the button you are submitting the form which is why it is doing the httppost. The next page link is hitting the httpget correctly but you are not passing it any information to so that it knows what to get. The get needs other information, like what page you are wanting.
The page number links fire a GET request, so you'll need to make sure that your GET action can handle the full search as well, so will need to get the page number and industries array - using defaults for when those parameters aren't available.
e.g.
[HttpGet]
public ViewResult Search(string searchTerm = "", int page = 1,
string industries = "")
{
//.....
}
You'll need to modify the pager link like this to pass industries to the get action.
#Html.PagedListPager((IPagedList)Model.SearchResults, page => Url.Action("Search", "Home", new { page, industries = string.Join(",", Model.IndustrySelectList.Where( x => x.Selected).Select( x => x.Text)) }))
It's not clear to me from your code where the post action is getting string[] industries from, or what it is doing with it, but you will need some way of passing this same this to your get action, probably as a single string that is comma separated. The example I've provided assumed you are taken it from the select list on the viewmodel