I want to implement Pagination in my ASP.NET MVC project.When i put #model PagedList.IPagedList<TestProject.Models.Test> in my Index page then the following error appears.
Compiler Error Message: CS1061: 'IPagedList' does not contain a definition for 'FName' and no extension method 'FName' accepting a first argument of type 'IPagedList' could be found
And When I put #model IEnumerable<TestProject.Models.Test> then it gives following error:
Argument 2: cannot convert from 'System.Collections.Generic.IEnumerable<TestProject.Models.Test>' to 'PagedList.IPagedList'
#Html.PagedListPager(Model, pageNumber => Url.Action("Index", new { pageNumber })
My Home Controller returns the following:
public ActionResult Index(int? pageNumber)
{
TestHandle testHandle = new TestHandle();
ModelState.Clear();
return View(testHandle.GetAll().ToList().ToPagedList(pageNumber ?? 1, 3));
}
My GetAll function retruns list:
public List<Test> GetAll()
{
clsUtilities cUtils = new clsUtilities();
DataSet ds;
List<Test> studentlist = new List<Test>();
string sSQL;
sSQL = "exec AllPhone";
ds=cUtils.GetDataSet(sSQL);
DataTable dt = ds.Tables[0];
foreach (DataRow dr in dt.Rows)
{
studentlist.Add(
new Test
{
Id = Convert.ToInt32(dr["Id"]),
FName = Convert.ToString(dr["FName"]),
LName = Convert.ToString(dr["LName"]),
Address = Convert.ToString(dr["Address"])
});
}
return studentlist;
}
Please guide me. I did so much of research but no luck. So I am posting this error. Please suggest me where i am going wrong. Any help is highly appreciated.
DisplayNameFor() only accepts IEnumerable<T> when using it for a collection property. If your model is IPagedList<T>, then you can use
#Html.DisplayNameFor(m => m.FirstOrDefault().FName)
Note this will work even if the collection is empty.
As a side note, calling ModelState.Clear(); in your GET method is pointless and can be removed.
Related
Actually i want to integrate paging in my view page and for that I am retrieving data from below code and I am passing this code from controller to view but any how I am facing issue as
var model = (from sr in db.StudentRequests
join c in db.Classes
on sr.ClassId equals c.ClassId
select new { sr.StudentRequestId,c.ClassName,sr.CreatedOn,sr.Location,sr.PaymentMethod }).ToList().ToPagedList(page ?? 1, 1);
return View(model);
and I am getting issue as
Type : InvalidOperationException
Message : The model item passed into the dictionary is of type 'PagedList.PagedList`1[<>f__AnonymousType3`5[System.Int32,System.String,System.Nullable`1[System.DateTime],System.String,System.String]]', but this dictionary requires a model item of type 'PagedList.IPagedList`1[Student_Tutor.Models.StudentRequest]'.
Source : System.Web.Mvc
My view side is as
#using PagedList;
#using PagedList.Mvc;
#model IPagedList<Student_Tutor.Models.StudentRequest>
#if (ViewBag.StudentRequest != null)
{
var StudentRequestId = (int)Model.First().StudentRequestId;// Here I am able to get the StudentRequestId
var StudentRequestTimecount = StudentRequestTime.Where(d => d.StudentRequestId == StudentRequestId).ToList();
var TutorStudentRequestcount = TutorStudentRequest.Where(d => d.StudentRequestId == StudentRequestId).ToList();
#Html.Displayfor(model => model.First().StudentRequestId)// here only text is displaying as StudentRequestId
#Html.Displayfor(Model => Model.First().CreatedOn)//here only text is diplaying as created on
}
please expalin why I am getting this error?
Update 1
var model = (from sr in db.StudentRequests
join c in db.Classes
on sr.ClassId equals c.ClassId
select new Studentvm{ StudentRequestId = sr.StudentRequestId,ClassName= c.ClassName,
CreatedOn =Convert.ToDateTime(sr.CreatedOn),Location= sr.Location,PaymentMethod= sr.PaymentMethod })
.ToList().ToPagedList(page ?? 1, 1);
return View(model);
but I am getting error as
An exception of type 'System.NotSupportedException' occurred in Student_Tutor.dll but was not handled in user code
Additional information: LINQ to Entities does not recognize the method 'System.DateTime ToDateTime(System.Object)' method, and this method cannot be translated into a store expression.
This part of your LINQ code
select new { sr.StudentRequestId,c.ClassName,sr.CreatedOn,sr.Location,sr.PaymentMethod }
That is creating an annonymous object for each item in the result collection you get from your LINQ query and you are creating a PagedList from that. But your view is strongly typed to PagedList<StudentRequest>
The ideal solution is to create a viewmodel to represent the data needed for this view and use that in the projection part of your LINQ query
public class StudentVm
{
public int StudentRequestId { set;get;}
public string ClassName { set;get;}
public DateTime CreatedOn { set;get;}
public string Location { set;get;}
}
Now use this view model for your projection
select new StudentVm { StudentRequestId = sr.StudentRequestId,
ClassName= c.ClassName,
Location = sr.Location,
CreatedOn = sr.CreatedOn }
And make sure your view is not strongly typed to PagedList<StudentVm>
#using PagedList;
#model PagedList<YourNamespace.StudentVm>
<table>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(a=> item.ClassName)</td>
<td>#Html.DisplayFor(a=> item.Location)</td>
<td>#Html.DisplayFor(a=> item.StudentRequestId)</td>
<td>#Html.DisplayFor(a=> item.CreatedOn)</td>
</tr>
}
</table>
Also, from your question, you are not really using the PagedList. To pass just a list of items, you do not need to convert that to PagedList<T> . You can simply send a List<StudentVm> from action method and change your view to be strongly typed to do that. Use PagedList if you are really using it (for paging)
can someone tell me what I'm doing wrong? :-)
I have this simple query:
var sample = from training in _db.Trainings
where training.InstructorID == 10
select new { Something = training.Instructor.UserName };
And I pass this to ViewBag.
ViewBag.Sample = sample;
Then I want to access it in my view like this:
#foreach (var item in ViewBag.Sample) {
#item.Something
}
And I get error message 'object' does not contain a definition for 'Something'. If I put there just #item, I get result { Something = SomeUserName }
Thanks for help.
This cannot be done. ViewBag is dynamic and the problem is that the anonymous type is generated as internal. I would recommend you using a view model:
public class Instructor
{
public string Name { get; set; }
}
and then:
public ActionResult Index()
{
var mdoel = from training in _db.Trainings
where training.InstructorID == 10
select new Instructor {
Name = training.Instructor.UserName
};
return View(model);
}
and in the view:
#model IEnumerable<Instructor>
#foreach (var item in ViewBag.Sample) {
#item.Something
}
If you want to send in ViewData For example and don't want to send in model
you could use the same could as in the upper answer
and in the Controller
enter code here
ViewData[Instractor] = from training in _db.Trainings
where training.InstructorID == 10
select new Instructor {
Name = training.Instructor.UserName
};
and in the view you need to cast this to
`IEnumerable<Instructor>`
but to do this you should use
#model IEnumerable<Instructor>
Then you could do something like this
IEnumerable<instructors> Instructors =(IEnumerable<Instructor>)ViewData[Instractor];
then go with foreach
#foreach (var item in Instructors ) {
#item.Something
}
Can someone help me to resolve the issue of filling Kendo UI Grid in mvc on IE platform?
The following are technologies used:
1) Telerik Kendo UI version 2015.1.408.545
2) MVC 5.0, razor view
3) .Net Framework 4.5
In Chrome whenever MVC View page loads it calls read action method twice. First call is for getting scema to be bind to the Kendo UI Grid. Second time is for getting data to fill Kendo UI Grid. All this requests from Controller to View and vice versa works fine in Chrome.
But when I run this application in IE (11.0), then first time it displays all the data properly. But when the request posted for another data it does not call the action method twice. Therefore the previous data is being displayed on Grid. Thats the issue.
View
#model CustomReportResultsViewModel
#(Html.Phoenix().Grid<DataTable, DataTable>()
.DataSourceReadController("CustomReport", "Reports")
.KeyName("ID")
.RecordName(Model.RecordName)
.CacheEditorTemplate(false)
.Columns(columns => { foreach (DataColumn c in Model.DataTable.Columns) { }})
)
Controller
public ActionResult ResultsGrid(int id, string recordName) {
return PartialView("ResultsGrid", new CustomReportResultsViewModel { DataTable = GetData(id, true), RecordName = recordName });
}
// List
public JsonResult Read([DataSourceRequest] DataSourceRequest request)
{
var table = GetData();
var result = table.ToDataSourceResult(request);
return Json(result, JsonRequestBehavior.AllowGet, 3);
}
private string GetDataSource(StringBuilder columnSchema, StringBuilder aggregates, StringBuilder group, string primaryKey, string read) {
var dataSource = new StringBuilder();
dataSource.Append("{transport:{"); dataSource.Append("read:{type:\"GET\",url:\"" + read + "\"}"); dataSource.Append("},");
dataSource.Append("type:\"aspnetmvc-ajax\",");
}
How do you request the data? AJAX call? Would be better if you added the grid datasource code / controller methods. Narrow the question, please.
This grid/controller signatures always worked for me on IE.
Controller:
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult GetData([DataSourceRequest] DataSourceRequest request)
{
//whatever it takes to get that data, like
var data = repository.GetAll<Model>();
return Json(data.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
View:
#using Entites.Model
#(Html.Kendo().Grid<Model>()
.Name("grid")
.DataSource(dataSource =>
{
dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("GetData", "Home"));
})
)
Thanks for your quick reply.
We are following the below code:
public ActionResult ResultsGrid(int id, string recordName)
{
return PartialView("ResultsGrid", new CustomReportResultsViewModel { DataTable = GetData(id, true), RecordName = recordName });
}
// List
public JsonResult Read([DataSourceRequest] DataSourceRequest request)
{
var table = GetData();
var result = table.ToDataSourceResult(request);
return Json(result, JsonRequestBehavior.AllowGet, 3);
}
private string GetDataSource(StringBuilder columnSchema, StringBuilder aggregates, StringBuilder group, string primaryKey, string read)
{
var dataSource = new StringBuilder();
dataSource.Append("{transport:{");
dataSource.Append("read:{type:\"GET\",url:\"" + read + "\"}");
dataSource.Append("},");
dataSource.Append("type:\"aspnetmvc-ajax\",");
}
I'm trying to use a dropdown in an MVC4 view and came accross Html.DropdownList different Behaviour which led me to try using #Html.DropDownListFor(m => m.SelectedProdType, (IEnumerable)ViewBag.ProdTypes, "Select Product Type", new { #class="form-control"}) in my view - which worked after I changed the SelectedProdType to IEnumerable in the Model - (wouldn't work if SelectedProdType was either a String or an Integer). The various Product Types are correctly listed and can be selected in the View and everything seems to work without any errors - except the ProdTypeID which I need to be returned when a selection is made defaults to 0 instead of the ID of the selected Product Type. I tried assigning the SelectedProdType to the ProdTypeID (after converting it to Int) in the Controller - but this obviously didn't work. HOW do I get the ID no. of the selected Product Type to get returned to be included amongst the various other Product fields that are saved to the DB when this CREATE form is submitted, please? I'm using a Stored Procedure with a DB (and I'm NOT using the Entity Framework, although that shouldn't matter - so, examples with just text lists - which seems to be all that I can find - don't help me).
Limited extracted bits from my code (hope this is sufficient)?
In the Model:
[Display(Name = "Select Product Type")]
public int ProdTypeID { get; set; }
public IEnumerable<SelectListItem> SelectedProdType { get; set; }
and
public DataSet GetProductsByTypes()
{
SqlConnection cn = new SqlConnection(#"Data Source=DHQWDBST101;User ID=wswebuser;Password=WSDBReader10!;Initial Catalog=WSTechnology");
SqlCommand cmd = new SqlCommand("sp_GetProductsByTypes", cn);
cn.Open();
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
DataSet dst = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dst);
cn.Close();
return dst;
}
and
public int CreateProduct(int _OrganisationID, int _ProdTypeID, string _ProductName, string _ProductDescription, string _ProductComments, string _ProductProfileLocation, string _ProductProfileName, string _ProductMIMEType, string _ProductSerialNumber, int _CreatedBy, bool _MarkedDelete, int _NewProductID)
{
SqlConnection cn = new SqlConnection(#"Data Source=DHQWDBST101;User ID=wswebuser;Password=WSDBReader10!;Initial Catalog=WSTechnology");
SqlCommand cmd = new SqlCommand("sp_AddProduct", cn);
cn.Open();
cmd.CommandType = CommandType.StoredProcedure;
//cmd.Parameters.AddWithValue("#ProductTypeID", 1);
cmd.Parameters.AddWithValue("#OrganisationID", _OrganisationID);
cmd.Parameters.AddWithValue("#ProdTypeID", _ProdTypeID);
cmd.Parameters.AddWithValue("#ProductName", _ProductName);
cmd.Parameters.AddWithValue("#ProductDescription", _ProductDescription);
cmd.Parameters.AddWithValue("#ProductComments", _ProductComments);
cmd.Parameters.AddWithValue("#ProductProfileLocation", _ProductProfileLocation);
cmd.Parameters.AddWithValue("#ProductMIMEType", _ProductMIMEType);
cmd.Parameters.AddWithValue("#ProductProfileName", _ProductProfileName);
cmd.Parameters.AddWithValue("#ProductSerialNumber", _ProductSerialNumber);
cmd.Parameters.AddWithValue("#CreatedBy", _CreatedBy);
cmd.Parameters.AddWithValue("#MarkedDelete", _MarkedDelete);
cmd.Parameters.AddWithValue("#NewProductID", 0);
return cmd.ExecuteNonQuery(); ;
}
In the Controller GET:
// GET: /Products/Create
[Authorize]
public ActionResult Create(CreateProductModel createproductmodel)
{
DataSet dst = createproductmodel.GetProductsByTypes();
ViewBag.ProdTypes = dst.Tables[0];
List<SelectListItem> items = new List<SelectListItem>();
foreach (System.Data.DataRow dr in ViewBag.ProdTypes.Rows)
{
items.Add(new SelectListItem { Text = #dr["Descr"].ToString(), Value = #dr["ProdTypeID"].ToString() });
}
ViewBag.ProdTypes = items;
return View();
and the POST in the Controller:
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public ActionResult Create(OrganisationNames organisationnames, CreateProductModel createproductmodel, FormCollection selection, HttpPostedFileBase file)
{
skipped a lot of (hopefully) unimportant code and
createproductmodel.ProdTypeID = Convert.ToInt32(createproductmodel.SelectedProdType);
int _records = createproductmodel.CreateProduct(createproductmodel.OrganisationID, createproductmodel.ProdTypeID, createproductmodel.ProductName, createproductmodel.ProductDescription, createproductmodel.ProductComments, ViewBag.FileURL, ViewBag.MIMEType, ViewBag.FileName, createproductmodel.ProductSerialNumber, createproductmodel.CreatedBy, createproductmodel.MarkedDelete, createproductmodel.NewProductID);
return RedirectToAction("Index", "Products");
In the View:
<div class="editor-label">
#Html.LabelFor(model => model.ProdTypeID)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.SelectedProdType, (IEnumerable<SelectListItem>)ViewBag.ProdTypes, "Select Product Type", new { #class="form-control"})
#Html.ValidationMessageFor(model => model.ProdTypeID)
</div>
Strangely, DropDownListFor isn't covered in the 2 MVC4 books I have and I haven't been able to Google anything remotely near what I'm trying to do and nothing useful turned up in a search of StackOverflow, so, I'm hoping some expert has a simple solution for this clueless newbie? (And everyone else trying to use DropDownListFor in MVC for the first time).
We'll really appreciate your explanation of what exactly to do to get the selected ID returned, please.
I apply .Net MVC structure with C#. In the controller, I want to distinct specific column (IndustryName), and return the result to Html.DropDownListFor in view. But I get a running time error at view:
System.Web.HttpException: DataBinding: 'System.String' not include
'IndustryName' property.
Is there any one meet such problem, and how to solve it?
Thank you very much for your helping.
Controller:
public ActionResult Create()
{
var industrys = this._pmCustomerService.GetAll().Select (x => x.IndustryName).Distinct();
ViewBag.Industrys = new SelectList(industrys, "IndustryName", "IndustryName", null);
return View();
}
View:
#Html.DropDownListFor(model => model.IndustryName, (SelectList)ViewBag.Industrys)
Your query is returning IEnumerable<string> (you select only the IndustryName property in the .Select() clause. string does not contain an property named IndustryName so you get this error. Just change the SelectList to
ViewBag.Industrys = new SelectList(industrys);
This will bind the options value and display text to the value of IndustryName
The following sample implementation may help you fix the problem:
var industries= this._pmCustomerService.GetAll()
.GroupBy(ind => new { ind.IndustryName})
.Select(group => new SelectListItem
{
Text = group.First().Name,
Value = group .First().Name
}
);
ViewBag.Industries= industries;
You can find more about the 'GroupBy & Select' approach instead of using linq's Distinct(), here
View
#Html.DropDownList("ddlIndustries",(#ViewBag.Industries) as IEnumerable<SelectListItem>)
If you like to use DropDownListFor helper instead then modify view code as follows:
#{
var industries = ViewBag.Industriesas IEnumerable<SelectListItem>;
}
#Html.DropDownListFor(m=> industries , industries )
You get this error because you create SelectList with wrong collection. This should work i think.
var industrys = this._pmCustomerService.GetAll().Select(x => new SelectListItem
{
Value = x.IndustryName,
Text = x.IndustryName
}).Distinct();
ViewBag.Industrys = new SelectList(industrys);
return View();
You are only Selecting IndustryName which is obviously of type String, use DistinctBy() from MoreLinq by Jon Skeet, here is the reference SO post:
public ActionResult Create()
{
var industrys = this._pmCustomerService.GetAll().DistinctBy(x => x.IndustryName);
ViewBag.Industrys = new SelectList(industrys, "IndustryName", "IndustryName", null);
return View();
}