Error When Submitting Asp.Net MVC Form - asp.net-mvc

ISSUE
I am trying to submit an asp.net mvc form and I get the following error. When the page initially loads it hits the GridData method successfully. If I click the Submit button in the view below, I get the following error.
ERROR
The parameters dictionary contains a null entry for parameter 'page' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.JsonResult GridData(System.String, System.String, Int32, Int32)' in 'HunterEdge.Web.Controllers.DataController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters
PARTIAL VIEW: This is the view data I'm trying to submit
#model HunterEdge.Web.Models.HarvestDataFilter
#using (Html.BeginForm("GridData", "Data"))
{
<div style=" width:300px; height:550px; float:left">
html removed for brevity
<input type="submit" value="Search" style=" margin-left:110px" />
</div>
}
CONTROLER ACTION METHOD I'M TRYING TO GET FORM DATA TO
public JsonResult GridData(string sidx, string sord, int page, int rows, HarvestDataFilter filter)
{
var results = (from a in db.t_harvest_statistics_elk
where a.year == "2008" && a.unit_number == 1
orderby a.id
select new { a.id, a.year, a.unit_number, a.total_hunters, a.bulls, a.cows }).ToList();
int pageIndex = Convert.ToInt32(page) - 1;
int pageSize = rows;
int totalRecords = results.Count();
int totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);
var pageResults = results.Skip(pageIndex * pageSize).Take(pageSize);
var jsonData = new
{
total = totalPages,
page,
records = totalRecords,
rows = (
from pageResult in pageResults
select new
{
id = pageResult.id,
cell = new[] {
pageResult.year.ToString(),
"Add",
pageResult.unit_number.ToString(),
pageResult.total_hunters.ToString(),
pageResult.bulls.ToString(),
"add",
pageResult.cows.ToString(),
"add",
"add",
"add"
}
}).ToArray()
};
return Json(jsonData, JsonRequestBehavior.AllowGet);

You should filter the grid data in another way. The usage of Html.BeginForm is the wrong way. Look at the answer and use either the filter toolbar or advanced searching. If you do decide to use you custom <input> field you should use postData with the property defined as function (see here) and use .trigger("reloadGrid", [{page: 1}]) to send the searching request to the controller. In the case you should add new parameter which corresponds the property name in the postData to the list of parameters of GridData.

Related

How should I pass my query from controller using ToPagedList

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)

PagedList in MVC3 showing Error Object reference not set to an instance of an object

This is My View
#using(#Html.BeginForm("CrmBlogGroupType","knowledge",FormMethod.Get)){
#Html.TextBox("search")
#Html.Hidden("type", (string)ViewBag.type)
#Html.DropDownList("PageSize",
new List<SelectListItem>()
{
new SelectListItem ()
{
Text="--Select Page Size--" ,Value="10",Selected=true
},
new SelectListItem ()
{
Text="View 20 records" ,Value="20"
},
new SelectListItem ()
{
Text="View 50 records" ,Value="50"
},
new SelectListItem ()
{
Text="View 100 records" ,Value="100"
},
})
<input type="submit" value="search" id="Searchbtn" />
<br />
#Html.CheckBox("Name")<text>Author Name</text>
#Html.CheckBox("AuthorTitle")<text>Title</text>
#Html.CheckBox("Description")<text>Description</text>
}
Here is the PagedList Code
#Html.PagedListPager(Model, page => Url.Action("CrmBlogGroupType",
new {page,Name=Request.QueryString["Name"].ToLower().Contains("true"),
AuthorTitle=Request.QueryString["AuthorTitle"].ToLower().Contains("true"),
Description=Request.QueryString["Description"].ToLower().Contains("true"), search=Request.QueryString["search"],PageSize=Request.QueryString["PageSize"],type=Request.QueryStrin g["type"]}),new PagedListRenderOptions()
{
DisplayLinkToFirstPage=true,DisplayLinkToLastPage=true,DisplayPageCountAndCurrentLocation=true,Displa yItemSliceAndTotal=true
,DisplayEllipsesWhenNotShowingAllPageNumbers=true,MaximumPageNumbersToDisplay=10
})
Controller Code
public ActionResult CrmBlogGroupType(int? page, bool? Name, bool? AuthorTitle, bool?Description, string search, int? PageSize, string type)
{
if (type==null)
{
//setting the Value in the initial call
//If the SP has changed then make the type parameter as the INT
type = "A";
}
IEnumerable<Usp_getBlogSetPosts_Result> _objBlogSet = _dataLayer.GetBlogSet(type).ToList().ToPagedList(page ?? 1, PageSize ?? 10);
return View(_objBlogSet);
}
Getting an ERROR :
Object reference not set to an instance of an object.
Line 202: #if (ViewBag.Search!=null && ViewBag.Search!=string.Empty)
Line 203:{
Line 204:#Html.PagedListPager(Model, page => Url.Action("CrmBlogGroupType", new { page,
Line 205:Name=Request.QueryString["Name"].ToLower().Contains("true"),AuthorTitle=Request.QueryString["Auth orTitle"].ToLower().Contains("true"),
Line 206:Description=Request.QueryString["Description"].ToLower().Contains("true"),
I've gone through some links by which i could make up the code like this, at last got stuck here
Any help on this is highly appreciated..
Use the ViewBag for passing the various parameters to the PagedListPager. Calculate the values in the controller and don't have complex logic in a view. Pulling parameters from querystring, when the controller has strongly typed values for those, is an unnecessary duplication of effort.
public ActionResult CrmBlogGroupType(int? page, bool? Name, bool? AuthorTitle, bool?Description, string search, int? PageSize, string type)
{
// Get the current values (or defaults == false) for the sorting
ViewBag.Name = Name.GetValueOrDefault();
ViewBag.AuthorTitle = AuthorTitle.GetValueOrDefault();
ViewBag.Description= Description.GetValueOrDefault();
and use them in the view like this:
#Html.PagedListPager(Model, page => Url.Action("CrmBlogGroupType",
new {page, Name=ViewBag.Name, AuthorTitle=ViewBag.AuthorTitle, Description=ViewBag.Description
etc
Update: 10,000 records is currently slow
From the comments below the current paging is slow. That is because the ToList() in the following line causes all records to be returned before any paging is applied to the LINQ query.
IEnumerable<Usp_getBlogSetPosts_Result> _objBlogSet =
_dataLayer.GetBlogSet(type)
.ToList() // <<<< THIS IS THE CULPRIT
.ToPagedList(page ?? 1, PageSize ?? 10);
ToPagedList is designed to work an an IQueryable so that when it adds Skip(n) and Take(n) to the query it will efficiently return just the page worth of records. Simply remove the ToList():
IEnumerable<Usp_getBlogSetPosts_Result> _objBlogSet =
_dataLayer.GetBlogSet(type)
.ToPagedList(page ?? 1, PageSize ?? 10);

mvc controlling two dropdownlist to filter data

hello everyone I want to ask a question abuout mvc dropdownlist. I am trying to filter the datas to their places or their codes while dropdowns selected index changed. I can do it when I use one dropdown but when I use more than one dropdown I cannot get the results separately.
As you see in the picture I have two dropdownlist.
public ActionResult Index(int? id,int? ddwList)
{
Repository<Order> _ro = new Repository<Order>();
IEnumerable<SelectListItem> _orderSelectListItem = _ro.All().AsEnumerable().Select(s => new SelectListItem
{
Text = s.code,
Value = s.id.ToString()
});
ViewData["ddOrder"] = _orderSelectListItem;
Repository<Workshop> _rw = new Repository<Workshop>();
IEnumerable<SelectListItem> _workshopSelectListItem = _rw.All().AsEnumerable().Select(s => new SelectListItem
{
Text = s.name,
Value = s.id.ToString()
});
ViewData["ddwList"] = _workshopSelectListItem;
Repository<ClothShipment> _rcs = new Repository<ClothShipment>();
IEnumerable<MyClothShipment> _myClothShipment = null;
if (id != null)
{
int? idOrd = _rcs.Find(w => w.orderId == id).orderId;
//int? idWork = _rcs.Find(w => w.workshopId == id).workshopId;
if (idOrd != null)
{
_myClothShipment = _rcs.All().Where(w => w.orderId == id).Select(s => new MyClothShipment
{
id = s.id,
amount = s.amount,
orderName = s.order.code,
clothName = s.clothList.name,
workshopName = s.workshop.name,
shipDate = s.shipDate
});
}
//else if(idWork != null){
// _myClothShipment = _rcs.All().Where(w => w.workshopId == id).Select(s => new MyClothShipment
// {
// id = s.id,
// amount = s.amount,
// orderName = s.order.code,
// clothName = s.clothList.name,
// workshopName = s.workshop.name,
// shipDate = s.shipDate
// });
//}
}
else {
_myClothShipment = _rcs.All().Select(s => new MyClothShipment
{
id = s.id,
amount = s.amount,
orderName = s.order.code,
clothName = s.clothList.name,
workshopName = s.workshop.name,
shipDate = s.shipDate
});
}
return View(_myClothShipment);
}
my view is here
<div id="sample_editable_2_length" class="dataTables_length">
<label>
#Html.DropDownList("ddwList",(IEnumerable<SelectListItem>)ViewData["ddwList"],"Atölye Seçiniz",new {#id="StateDropDown1", #class = "span15 chosen"})
</label>
</div>
my view is here
<div id="sample_editable_2_length" class="dataTables_length">
<label>
#Html.DropDownList("ddwList",(IEnumerable<SelectListItem>)ViewData["ddwList"],"Atölye Seçiniz",new {#id="StateDropDown1", #class = "span15 chosen"})
</label>
</div>
<div id="sample_editable_1_length" class="dataTables_length">
<label>
#*<select class="m-wrap small" name="sample_editable_1_length" size="1" aria-controls="sample_editable_1">
</select>*#
#Html.DropDownList("ddOrder",(IEnumerable<SelectListItem>)ViewData["ddOrder"],"Sipariş Kodu Seçiniz",new {#id="StateDropDown", #class = "span15 chosen"})
</label>
</div>
and here is my script code
$("#StateDropDown").change(function (e) {
var controllerName = '#ViewContext.RouteData.Values["Controller"].ToString()';
var actionName = '#ViewContext.RouteData.Values["Action"].ToString()';
var _id = $("#StateDropDown").val();
var _url = "/" + controllerName + "/" + actionName + "/" + _id;
window.location.href =_url
});
$("#StateDropDown1").change(function (e) {
var controllerName = '#ViewContext.RouteData.Values["Controller"].ToString()';
var actionName = '#ViewContext.RouteData.Values["Action"].ToString()';
var _id = $("#StateDropDown1").val();
var _url = "/" + controllerName + "/" + actionName + "/" + _id;
window.location.href = _url
});
I am filling the dropdowns when on page load from database and getting all the data to show with dropdowns I want to filter the data that shown... And with this code one of my dropdown works I am taking the id of selected item (Index(int? id)) in here but when I try to use both of them separately it doesnt work how can I make both of them work. What should I do ? The second parameter always comes null or if I use different parameter except "id" it is again coming null ? and also I tried to take parameter as string but it also came null... Thank you for your helps.
To explain what your code is doing:
When your select a value from your first select, you are passing its value to the Index method (e.g. /Index/1) so the value of parameter id is 1 but no value has been passed to parameter ddwList so it is null. When you select a value from the second select you are passing its value to the index method (e.d. /Index/5) so the value of parameter id is 5 but no value has been passed to parameter ddwList so again it is null.
Assuming you want to display a table based on the selections of both selects, then you need to construct the url as /Index?id=1&ddwList=5. Therefore, remove the change events from your selects and add a button that constructs the query in its click event. However, the way you are doing this is reloading the whole page each time. I suggest you consider loading the table from a partial view using a jQuery.get() method to avoid a complete page load each time. For example
public ActionResult Index()
{
// Build the 2 select lists only
return View();
}
Index view
// Add the two #Html.DropdownFor()...
<button id="LoadTable">Load Table</button>
<div id="TablePlaceholder"></div>
and the script
$('#LoadTable').click(function() {
var id1 = // the value of the first select
var id2 = // the value of your second select
$.get('#Url.Action("Table")', { id: id1, ddwList: id2 }, function(data) {
$('#TablePlaceHolder').html(data);
});
}
and the partial result
public ActionResult Table(int? id, int? ddwList)
{
// Build your table view based on values of id and ddwList
return PartialView();
}
If I understand this, you are able to use one of the drop downs at a time and that drop down successfully sends it's value to your controller while the other drop down always sends null. If that's the case, that is working correctly with the way you made your dropdownlists with an option label.
As explained in the msdn documentation:http://msdn.microsoft.com/en-us/library/dd492256(v=vs.118).aspx
optionLabel Type: System.String The text for a default empty item.
This parameter can be null.
So if you want both of the drop down lists to be usable at the same time, you'll need to remove the events for .change and add a form with those dropdowns AND a submit button within to use both values at the same time.
OR
Do not use an option label meaning the first option of the dropDownList will be used as it's initial/default value. Here is a link to the msdn docs showing the different ways to format the Html.DropDownList helper: http://msdn.microsoft.com/en-us/library/system.web.mvc.html.selectextensions.dropdownlist(v=vs.118).aspx
I hope I understood you correctly!

Exception when try to modify my model

when I try to add in my model some note appear Exception
Here is my CompetitionRepository where I implement method
public void AddCompetition(Competition competition)
{
if (competition.ID == 0)
_context.Competitions.Add(competition);
else
_context.Entry(competition).State = EntityState.Modified;
_context.SaveChanges();
}
Controller
[HttpPost]
public ActionResult AdminPCreate(string compName, int quantity, DateTime starTime)
{
if(ModelState.IsValid)
_dataManager.Competitions.AddCompetition(
new Competition
{
ID = 1,
Quantity = quantity,
StartTime = starTime,
});
return View("Competitions",GetCompetitions());
}
And cshtml Page, maybe I'm doing something wrong
#using (Html.BeginForm("AdminPCreate", "Home"))
{
#Html.TextBox("compName",null ,new {#placeholder = "Competition Name"})
#Html.TextBox("quantity", null, new {#placeholder = "Amount players"})
#Html.TextBox("starTime", null, new {#placeholder = "Enter beginnig of the match like dd\\mm\\yyyy"})
<input type="submit" value="Create" class="btn btn-success"/>
I also tried using a lot of solutions including here on that site, such as that
because when i try to use that (ObjectStateManager.GetObjectStateEntry(entity)`
because my field methods have type different from object
public void AddCompetition(Competition competition)
In the method AdminPCreate of your controller, you have new Competition { ID = 1, [..] }.
That ID valueof 1 makes your repository think it's an existing item, so Entity Framework tries to update the Competition record where ID = 1. That doesn't exist, so your database returns "0 rows affected" and the error is thrown.
I suspect that when you set the ID to 0 instead of 1 in your controller it'll work.

How to get the current item of a List using AJAX?

Maybe the title is not so clear.
Imagine that I have two columns in the razor view.
One of the columns, show the following list.
#for (int i = 0; i < questions.Length; i++) {
<tr>
<td><span>#i</span>.</td>
<td class="questionText">#Html.ActionLink(questions[i].QuestionText, "AddItemToAssignmentContent", new { itemId = "Q" + questions[i].Id })
</tr>
}
As you can see, each one has a url.
Then, the second column is called SelectedItems, the purpuse of this is when you clic in a link of the first column, add the item to the second column.
I would like to do this using Ajax, but until now I don't know how to implemented with it.
Here is the action.
public ActionResult AddItemToAssignmentContent(string itemId)
{
var list = Session["SelectedItems"] as List<CreateAssignmentSelectedItem>;
CreateAssignmentSelectedItem item = new CreateAssignmentSelectedItem();
item.Id = itemId;
item.Display = itemId;
item.Quantity = 5;
list.Add(item);
return PartialView("_SelectedAssignmentContent", list);
}
What am I missing, or what am I supposed to do to add items to second column using AJAX?
One way of doing this is by defining a javascript function which would get called on the execution of the click event of the link. The function will send the request async via ajax to the controller action, get the results (partial view) and populate the div
Mocked up function
function addQuestionToList(questionId){
var linkToControllerAction = ‘#Url.Content(….)’
$.ajax({
url: linkToControllerAction,
type: ‘post’,
data: { ‘itemId’: questionId }
}).done(function(partialViewResult){
$(‘#divHostingThePartialView’).html(partialViewResult);
});
}
And hook this function to the click event of each tr, that rendres the name of the question, replacing your action link

Resources