Ajax Request in MVC3 - asp.net-mvc-3

I am new to Ajax, I am trying to fetch data from database with an ajax call using jquery.
I have a list of country tabs and I am trying to display data when there is an user action
Here is my code sample, at the moment it is saying there is a null system reference.
public ActionResult Details(int id, string searchTerm)
{
// Do we have a search term
if (!String.IsNullOrEmpty(searchTerm))
{
// decode the searchTerm as we dont want to search for encoded bits
searchTerm = Decode(searchTerm);
}
var a = _mRepository.GetMyId(id);
if (a == null)
{
return View("NotFound");
}
// Here we need to get list of countries for the selected manufacturer
var c = _mwRepository.Getcountries(id);
ViewData["Countries"] = c.ToArray();
// Now we need list of products for the manufacturer countries and this is an Ajax call to database so that it fetches data only when there is a user action
foreach (var country in c)
{
var p = _productRepository.GetAllCurrentProductsForManufacturerCountry(id,
country.Id);
}
if(Request.IsAjaxRequest())
{
ViewData["ManufacturerCountryProducts"] =
p.ToArray();
}

public class CountryProducts
{
public Country Country { get; set; }
public List<Product> ProductsList { get; set; }
}
[HttpPost]
public ActionResult Details( int id, string searchTerm )
{
// Do we have a search term
if ( !String.IsNullOrEmpty( searchTerm ) )
{
// decode the searchTerm as we dont want to search for encoded bits
searchTerm = Decode( searchTerm );
}
var a = _mRepository.GetMyId( id );
if ( a == null )
{
return View( "NotFound" );
}
// Here we need to get list of countries for the selected manufacturer
List<Country> countriesList = _mwRepository.Getcountries( id );
var data = new List<CountryProducts>();
if ( countriesList != null )
{
foreach (var country in countriesList)
{
List<Product> products = _productRepository.GetAllCurrentProductsForManufacturerCountry(id,
country.Id);
data.Add(new CountryProducts() {Country = country, ProductsList = products});
}
}
if (Request.IsAjaxRequest())
{
ViewData["CountryProducts"] = data.ToArray();
}
}
But i'm use two different methods for ajax, such as:
public ActionResult Details( int id )
{
...
return View(model);
}
//for ajax request:
[HttpGet]
public JsonResult Details( int id, string searchTerm )
{
return new JsonResult()
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = GetFilteredDetailsData(id, searchTerm)
};
}

Related

How to load and search data using edmx

I am trying to load the data into a dropdownlist in a nested master page but the Model in View is always null. How can I do this?
In model
public class AllInOneModel
{
public string City { get; set; }
public IEnumerable<City> cities { get; set; }
}
In controller
public ActionResult Add()
{
return View(new AllInOneModel());
}
In View
#model IBilik.Models.AllInOneModel
#Html.DropDownListFor(model => model.City,(SelectList)Model.cities)
Personally I would skip the "AllInOneModel" and stick to sending the single city to the view.
The controller action could look somewhat like this.
public ActionResult Index()
{
//TODO: get current cities from database
List<City> cities = new List<City>
{
new City { CityID = 1, CityName = "City1" },
new City { CityID = 2, CityName = "City2" },
new City { CityID = 3, CityName = "City3" }
};
// Create the list of selectlistitems to populate the dropdown
List<SelectListItem> listItems = new List<SelectListItem>();
foreach(var c in cities)
{
listItems.Add(new SelectListItem { Value = c.CityID.ToString(), Text = c.CityName });
}
//Throw them into viewbag
ViewBag.ListItems = listItems;
//TODO get some city (perhaps from db) to send to view
var city = new City { CityID = 1, CityName = "City1" };
return View(city);
}
And then you would render the view in this way.
#model IBilik.Models.City
#Html.DropDownListFor(model => model.CityID, ViewBag.ListItems as List<SelectListItem>)

Load data in Telerik grid by dropdownlist selected value

I am a beginner in Telerik Grid in ASP.NET MVC3. I try to bind Grid with dropdownlist selected value. Please see my code below.
My web model class
public class CustomerEventRolesModels
{
public int Event { get; set; }
public IEnumerable<System.Web.Mvc.SelectListItem> Events { get; set; }
public Telerik.Web.Mvc.GridModel<CustomerEventRolesModel> GridData { get; set; }
}
public class CustomerEventRolesModel : BaseNopEntityModel
{
public string Customer { get; set; }
public bool Sponsor { get; set; }
public bool Speaker { get; set; }
}
My .cshtml
<table id="grdCustomerEventRoleData" class="adminContent" style="display: none">
<tr>
<td>
<p>
</p>
</td>
</tr>
<tr>
<td>
#(Html.Telerik().Grid<CustomerEventRolesModel>(Model.GridData.Data)
.Name("grdCustomerEventRoles")
.Columns(columns =>
{
columns.Bound(x => x.Customer);
columns.Bound(x => x.Speaker).Template(x => Html.CheckBox("spk", x.Speaker));
columns.Bound(x => x.Sponsor).Template(x => Html.CheckBox("spn", x.Sponsor));
}
) .Pageable(settings => settings.Total(Model.GridData.Total)
.PageSize(gridPageSize)
.Position(GridPagerPosition.Both))
.ClientEvents(events => events.OnDataBinding("onDataBinding"))
.DataBinding(dataBinding => dataBinding.Ajax().Select("FilterByDropdown", "Customer"))
.EnableCustomBinding(true))
) )
</td>
</tr>
<script type="text/javascript">
var initialLoad = true;
$("#select-event").change(function () {
if ($("#select-event option:selected").val() > 0) {
$("#grdCustomerEventRoleData").show();
$("#grdCustomerEventRoles").data("tGrid").rebind();
}
else {
$("#grdCustomerEventRoleData").show();
}
});
function onDataBinding(e) {
if (initialLoad == true) {
e.preventDefault();
initialLoad = false;
}
else {
var classificationId = $("#select-event option:selected").val();
if (classificationId != "")
e.data = $.extend(e.data, {
selEvent: classificationId
});
else {
e.preventDefault();
$("#grdCustomerEventRoleData").hide();
}
}
}
Actions in controller
public ActionResult FirstBind()
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageCustomers))
return AccessDeniedView();
var model = new CustomerEventRolesModels();
model.Event = 0;
List<Nop.Core.Domain.Catalog.Product> products = _productRepository.Table.Where(p => p.EventDate != null && p.EventDate >= DateTime.Now).ToList();
model.Events = products.Select(p => new System.Web.Mvc.SelectListItem
{
Text = p.Name,
Value = p.Id.ToString()
});
var grdmodel = new GridModel<CustomerEventRolesModel>
{
Data = null,
Total = 0
};
model.GridData = grdmodel;
return View(model);
}
[HttpPost, GridAction(EnableCustomBinding = true)]
public ActionResult FilterByDropdown(GridCommand command, int selEvent)
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageCustomers))
return AccessDeniedView();
if (selEvent == 0)
return View();
var model = new CustomerEventRolesModels();
model.Event = selEvent;
var roles = (from lst in _customerEventRoleRepository.Table
join cust in _customerRepository.Table on lst.CustomerId equals cust.Id
join product in _productRepository.Table on lst.EventId equals product.Id
join role in _customerRoleRepository.Table on lst.RoleId equals role.Id
orderby lst.Id descending
select new CustomerEventRolesModel
{
Id = lst.Id,
Customer = cust.Email,
Sponsor = (role.Name == "Sponsor") ? true : false,
Speaker = (role.Name == "Speaker") ? true : false
}).ToList();
var grdmodel = new GridModel<CustomerEventRolesModel>
{
Data = roles,
Total = roles.Count
};
model.GridData = grdmodel;
return new JsonResult
{
Data = model
};
}
FilterByDropdown action is works correctly but Grid is not binded.
I am clueless.
Please help.
If you want to add a dropdown to a Telerik MVC Grid when editing a row, you will need to follow next few steps (aside from making the grid ajax bound and the rows editable).
Let’s say we want the column representing a name (“Name” from the model) to be a dropdown, from which a name can be selected rather than typed. Add a folder named “EditorTemplates” to the folder containing the view that the grid is on. It will contain a separate partial view for each dropdown we want to show in the row that is being edited. Make a partial view (mentioned above), name it e.g. “ClientName.cshtml”, containing a Telerik DropDownList named “Name” and bound to required list of names.
#(Html.Telerik().DropDownList()
.Name("Name")
.BindTo(new SelectList((IEnumerable)ViewData["CustomerNames"], "Text", "Value"))
)
Add the following attribute to the “Name” property of the data type that the grid uses e.g. Grid uses “Customer” class, containing “string Name” field:
public class Customer{ [UIHint("ClientName"), Required] public string Name { get; set; } }
The UIHint property specifies which field template to use when a specific column is rendered.
Add the following java script to the page containing the grid function:
function onEditCustomerList(e) { if (e.dataItem != null) { $(e.form).find('#Name').data('tDropDownList').select(function (dataItem) { return dataItem.Text == e.dataItem['Name']; });
} }
This should do the trick.
You're returning the wrong model.
Try this in FilterByDropdown:
var grdmodel = new GridModel<CustomerEventRolesModel>
{
Data = roles,
Total = roles.Count
};
return new JsonResult
{
Data = grdmodel
};

pagination on filtered data getting lost on when clicked on second page in webgrid

I've created a WebGrid in an MVC3 web application. In my application sorting,filtering and paging are enabled.
Problem : Whenever a filtering is performed on the webgrid, it populates the filtered data to Webgrid. But if i click on the second page to see the remaining data filtered by Webgrid on my searched text, it doesnot show the remaining filtered data instead it shows complete list of all items in the grid.
How can i get the data in the second page after filtering my data in webgrid.
I've seen a similar question in the site, even it doesnot solved my problem.
My view: I've created a partial view to populate grid, which is called by a normal view. I've followed this tutorial to do that.
Controller: for the first time, Webgrid loads data by using another method in model so as to populate all the data from the database
My Partial View Code:
#{
ViewBag.Title = "listStudents";
Layout = "~/Views/Shared/_Layout.cshtml";
WebGrid grid = new WebGrid(Model, canPage: true, canSort: true, rowsPerPage: 3);
}
#grid.Pager(WebGridPagerModes.NextPrevious)
#grid.GetHtml( //Error at this line
htmlAttributes: new { id = "grdListStudents" },
fillEmptyRows: true,
headerStyle: "tblHeader",
tableStyle: "tablestyle",
mode: WebGridPagerModes.All,
firstText: "<< First",
previousText: "< Previous", nextText: "Next >",
lastText: "Last >>",
columns: new[]{
grid.Column("intID","SId",canSort:true),
grid.Column("strFirstName","Name",canSort:true,format:(item)=>item.strFirstName+" "+item.strLastName),
grid.Column("strPhone","Phone",canSort:true),
grid.Column("strEmail","Email",canSort:true),
}
)
Here is my code in controller:
public readonly IStudentInfo _istudentrepository;
public studentController( IStudentInfo _iStudentRepository)
{
this._istudentrepository = _iStudentRepository;
}
//To filter according to Searched Text
[HttpPost]
public ActionResult studentController(string txtSearch,string ddlTitle,FormCollection collect)
{
IEnumerable<Students> sList;
sList = _istudentlistrepository.getAllStudentsList();
if (txtSearch != "")
{
switch (ddlTitle)
{
case "intId":
int sId = Convert.ToInt32(txtSearch);
sList = sList.Where(b => b.intId == sId).ToList();
break;
case "strFirstName":
sList = sList.Where(b => b.strFirstName.ToLower().Contains(txtSearch.ToLower())).ToList();
break;
case "strPhone":
sList = sList.Where(b => b.strPhone.ToLower().Contains(txtSearch.ToLower())).ToList();
break;
case "strEmail":
sList = sList.Where(b => b.strEmail.ToLower().Contains(txtSearch.ToLower())).ToList();
break;
}
}
return PartialView("_grdListStudents", sList);
}
public ActionResult studentController(string sort, string sortdir, int? page)
{
int startPage = 0;
IEnumerable<Students> sList;
if (page.HasValue && page.Value > 0)
{
startPage = page.Value;
}
sList = _istudentrepository.GetList(startPage, PageSize, sort, sortdir);
return View(sList);
}
Code in Interface IStudentInfo:
public interface IStudentInfo
{
IEnumerable<Students> GetList(int intPage, int intRecords, string strSort, string sortdir);
}
Code in Model:
private MyEntity _entity;
public StudentListRepository(MyEntity Ent)
{
this._entity = Ent;
}
public IEnumerable<Students> GetList(int intPage, int intRecords, string strSort, string sortdir)
{
var finalresult = new Students();
var bidList = (from userInfo in _entity.tbl_UserInf
join user in _entity.tbl_User on userInfo.UserId equals user.UserId
select new Students()
{
intID=user.UserId,
strFirstName = user.FirstName,
strEmail = userInfo.EmailId,
intPhone=userInfo.Phone
}).OrderByDescending(m => m.intID);
finalresult.TotalResult = bidList.Count();
switch (strSort)
{
case "intID":
if (sortdir == "ASC")
{
sList = sList.OrderBy(r => r.Id);
}
else
{
sList= sList.OrderByDescending(r => r.Id);
}
break;
case "strFirstName":
if (sortdir == "ASC")
{
sList = sList.OrderBy(r => r.strFirstName);
}
else
{
sList= sList.OrderByDescending(r => r.strFirstName);
}
break;
case "strEmail":
if (sortdir == "ASC")
{
sList = sList.OrderBy(r => r.strEmail);
}
else
{
sList= sList.OrderByDescending(r => r.strEmail);
}
break;
//repeat same for phone
}
finalresult.lstStudents = sList.Skip(intPage * intRecords).Take(intRecords).ToList();
return sList.ToArray();
}
Your viewmodel should contain the list of items and the values for searchtext, pagesize, current page and total record count. I use a generic base class with these properties:
public class PagedViewModel<T> {
public IList<T> Items { get; set; }
public int PageSize { get; set; }
public int RowCount { get; set; }
public int Page { get; set; }
public int PageCount { get; set; }
public string sort { get; set; }
public string sortdir { get; set; }
}
Then your concrete Viewmodel looks just like this:
public class StudentsListViewModel : PagedViewModel<Students> {
public string Search { get; set; }
}
From your comments i read, you want to Ajax.BeginForm to update your grid via ajax.
Then you need two actions: One for the whole page and one for the grid (partial).
The first action returns the whole page:
public ActionResult Index() {
StudentsListViewModel model = queryStudents(1, 10, null);
return View(model);
}
The second action returns the partial view for the grid:
public ActionResult UpdateStudentsGrid(StudentsListViewModel model) {
model.Items = queryStudents(model);
return Partial("StudentsGrid", model);
}
A helper method queries the data and returns the filtered list:
private StudentsListViewModel queryStudents(int page, int rowsPerPage,
string search) {
StudentsListViewModel = new StudentsListViewModel {
Page = page,
PageSize = rowsPerPage,
Items = db.Students.Where(s => s.Name == search || search == null)
... add paging...;
};
// ToDo: set additional properties on model
return model;
}
The main page view contains your ajax form. The list will be rendered by the partial view:
#model StudentsViewModel
#using (Ajax.BeginForm("UpdateStudentsGrid",
new AjaxOptions { UpdateTargetId = "grid" })) {
#Html.TextboxFor(m => m.Search)
<input type=submit" />
<div id="grid">
#Html.Partial("StudentsGrid", Model);
</div>
}
The partial view looks something like this and renders just the grid:
#{
var grid = new WebGrid(Model.Items, canPage: true, canSort: true,
rowsPerPage: Model.PageSize);
}
#grid.GetHtml(...)
I havn't tested or compiled the code: it will probably not work as it stands here but it should get you started.
EDIT: The forgotten pager
For getting the pager links to work with your form, you can simple change the form method from POST to GET according to this article: http://www.mikepope.com/blog/DisplayBlog.aspx?permalink=2377
But i'm not sure how that works with an ajax form.
Another approach would be to intercept the clicks on the pager links and submit the form with method POST instead: http://forums.asp.net/t/1703486.aspx/1

string array to be separated with comma

I had a string array which I want it to be returned in view separated by comma.
#Html.DisplayFor(m => name.studentName) <span>, </span>}
I'm using this way but the last string will ended with a comma also. Wondering how to avoid this?
I assume that you have a collection of students on your model each possessing a studentName property that you want to display:
public IEnumerable<Student> Students { get; set; }
And inside your view you are looping through this collection and displaying each student name individually.
Now instead of looping you could do the following:
#Html.Raw(
string.Join(
"<span>,<span>",
Model.Students.Select(x => Html.Encode(x.studentName))
)
)
or even better, externalize this logic into a reusable custom HTML helper:
public static class HtmlExtensions
{
public static IHtmlString FormatStudentNames(this HtmlHelper htmlHelper, IEnumerable<Student> students)
{
return new HtmlString(
string.Join(
"<span>,<span>",
students.Select(x => Html.Encode(x.studentName))
)
);
}
}
and then inside your view simply call this helper:
#Html.FormatStudentNames(Model.Students)
You no longer need to write any foreach or whatever loops you are writing.
Try
#string.Join(",", name.studentName);
And have a look at string.Join on MSDN.
$(".category").change(function () {
var value = $(this).val();
loadSubCategory(value)
});
function loadSubCategory(parentID) {
var $el = $("#SubCats");
$el.prop("disabled", true);
$el.empty();
$.ajax({
cache: false,
url: "/Category/loadSubCategory?id=" + parentID,
success: function (data) {
if (data != '' && data != null) {
if (data != 'error') {
var sch = JSON.parse(data);
if (sch.length > 0) {
$el.prop("disabled", false);
for (i = 0; i < sch.length; i++) {
$el.append($("<option></option>")
.attr("value", sch[i].ID).text(sch[i].Description));
}
}
}
}
}
});
}
public ActionResult loadSubCategory(string id)
{
string list = "";
try
{
list = Newtonsoft.Json.JsonConvert.SerializeObject(menu.SubCategory(id));
}
catch (Exception ex)
{
}
return Content(list);
}
public List<CategoryModel> SubCategory(string parentID){
List<CategoryModel> listCategory= new List<CategoryModel>();
string[] yourValues = parentID.Split(',');
foreach (var item in yourValues)
{
var Category = UowObj.CategoryRepository.Get(filter: c => c.ParentId.ToString() == item && c.IsActive == true).ToList();
if (Category != null)
{
var category= new CategoryModel();
foreach (var itemq in Category)
{
category.ID = itemq.ID;
category.Description = itemq.Description;
}
listCategory.Add(merchant);
}
}

How to get selected value and and id from dropdownlist in mvc3?

When I make my httppost call, i need to get the selected value and the id of a random number of dropdownlists in my view. The number of dropdownlists is random because they are created dynamically based on the selected value of another dropdownlist.
Example:
in dropdownlist 1 I select bmw. Then 3 dropdownlists are created, so the user can give each carmodel a rate value. Each dropdownlist has id= the model of the car and the options you can select is 1,2 and 3. If there was 4 carmodels of bmw, the options would then be 1,2,3 and 4 and so on...
When I make the httppost call, how do I in the controller run through all the dynammically created dropdownlist and check the value and id?
EDIT:
The controller of my index view:
public class BookingPensionController : Controller
{
private DbEntities db = new DbEntities();
EditBookingPensionViewModel objViewModel;
public ActionResult Index()
{
objViewModel = new EditBookingPensionViewModel
{
Booking = new Booking { BookingStartDate = DateTime.Today, BookingEndDate = DateTime.Today, DateOfBooking = DateTime.Now }
};
objViewModel.deliveryTypes = new List<string>();
int id = int.Parse(Session["id"].ToString());
SelectList list;
try
{
var deliverytypes = from d in db.DeliveryTypes
where d.Pension_ID == id
select d;
foreach (DeliveryType item in deliverytypes)
{
objViewModel.deliveryTypes.Add(item.Titel);
}
ViewData["DeliveryTypes"] = objViewModel.deliveryTypes;
objViewModel.customersToPension = new List<SelectListItem>();
objViewModel.customersToPension = GetCustomersToPension(id);
}
catch (Exception ex)
{
throw;
}
int PensionId = int.Parse(Session["id"].ToString());
objViewModel.CustomerValue = GetCustomersToPension(PensionId);
return View(objViewModel);
}
My Index view:
#model HundePensionBooking.ViewModels.EditBookingPensionViewModel
//Some code...
//And my script that retreives the customerinfo and creates the dropdownlists
$("#ddlCustomerId").change(function () {
var id = $("#ddlCustomerId").val();
getCustomerInfo(id);
$('#customerinfo').load("#Url.Action("CustomerInfo", "BookingPension")");
var ddlsource = "#ddlCustomerId";
var ddltarget = "#ddlDogId";
$.getJSON('#Url.Action("Dogs_SelectedCustomer")', { CustomerId: $(ddlsource).val() }, function (data) {
$(ddltarget).empty();
$("#tblRooms tr:gt(0)").remove();
$.each(data, function (index, optionData) {
createDynamicTable($("#tblRooms"), optionData.Text, data.length);
});
});
});
});
</script>
<script type="text/javascript">
function createDynamicTable(tbody, value, count) {
if (tbody == null || tbody.length < 1) return;
var trow = $("<tr>");
var cellText = value
var option;
$('<th scope="row" abbr="Model" class="spec">')
.addClass("tableCell")
.text(cellText)
.appendTo(trow);
var ddlselectroom = '<td class="spectd"><select class="selectbox" id=' + value + '>';
for (var d = 1; d <= count; d++) {
ddlselectroom += '<option value="' + d + '">Bur nr. ' + d + '</option>';
}
ddlselectroom += '</select></td>';
$(ddlselectroom).appendTo(trow);
trow.appendTo(tbody);
}
//Some more code...
//And then the table which gets populated with the random number of dropdownlists:
<table id="tblRooms" width="100%">
<tr>
</tr>
</table>
The Viewmodel looks like this:
public class EditBookingPensionViewModel
{
public Booking Booking { get; set; }
public IEnumerable<Customer> customerList { get; set; }
public List<string> deliveryTypes { get; set; }
public List<SelectListItem> customersToPension { get; set; }
public Customer customer { get; set; }
public CustomerInfoModel CustomerInfo { get; set; }
My partialview with the customerinfo looks like this:
#model HundePensionBooking.Models.Customer
So when I make the httppost call
<input type="submit" value="Create" />
I need to get all the data down to my database. Im not sure on how to do that but I assume I have to do it with my Create method in the controller class
[HttpPost]
public ActionResult Create(EditBookingPensionViewModel model)
{
//SaveCustomer... From the CustomerInfo partialview
//SaveBooking...From Index view
//Save all the data from all the dropdownlists... from index view
}
just add a hidden field of counter, when you submit, get value of counter then loop from 1 to value of counter and request optionname + counter. jquery should be used to set the value of counter.

Resources