Partial View error object reference not set don't understand why - c#

I got this error after I hit the Delete from Cart, Object reference not set to an instance of an object. This is happening in my partial View. Any idea on how to resolve this ?
TableContent.cshtml (partial view) from Panier
#model Tp1WebStore3.ViewModels.ShoppingCartViewModel
#{
ViewBag.Title = "Table Content";
}
<a href="#" class="TableContent">
<table>
<tr>
<th>
Produit
</th>
<th>
Prix (unitaire)
</th>
<th>
Quantite
</th>
<th></th>
</tr>
#foreach (var item in Model.CartItems) <=== error is happening here
{
<tr id="row-#item.ProduitId">
<td>
#Html.ActionLink(item.Produit.Description, "Details", "Produit", new { id =
item.ProduitId }, null)
</td>
<td>
#item.Produit.Prix
</td>
<td id="item-count-#item.PanierId">
#item.Quantite
</td>
<td>
<a href="#" class="RemoveLink" data-id="#item.PanierId"> Enlever du panier
</a>
</td>
</tr>
}
<tr>
<td>
Total
</td>
<td></td>
<td></td>
<td id="cart-total">
#Model.CartTotal
</td>
</tr>
</table>
</a>
Index.cshtml from Panier
#model Tp1WebStore3.ViewModels.ShoppingCartViewModel
#{
ViewBag.Title = "Shopping Cart";
}
<script src="/Scripts/jquery-1.8.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
$('.RemoveLink').click(function () {
$.ajax({
url: '/Panier/RemoveFromCart',
data: { id: $(this).data('id') },
type: 'POST',
cache: false,
success: function (result) {
$('#row-' + result.DeleteId).remove();
$('#row-' + result.DeleteId).fadeOut('slow');
$('#cart-status').text('Cart (' + result.CartCount + ')');
$('#update-message').text(result.Message);
$('#cart-total').text(result.CartTotal);
$.get('#Url.Action("TableContent", "Panier")')
$("#TableContent").html(data); });
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("Status: " + textStatus); alert("Error: " + errorThrown);
}
});
return false;
});
});
</script>
<h3>
<em>Details</em> du panier:
</h3>
<p class="button">
#Html.ActionLink("Checkout >>", "AddressAndPayment", "Checkout")
</p>
<div id="update-message">
</div>
<div id="table-content">
#Html.Partial("TableContent") <=== partial view call
</div>
PanierController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Tp1WebStore3.Models;
using Tp1WebStore3.ViewModels;
namespace Tp1WebStore3.Controllers
{
public class PanierController : Controller
{
//
// GET: /Panier/
Tp1WebStoreDBEntities dbProduit = new Tp1WebStoreDBEntities();
//
// GET: /ShoppingCart/
public ActionResult Index()
{
var cart = ShoppingCart.GetCart(this.HttpContext);
// Set up our ViewModel
var viewModel = new ShoppingCartViewModel
{
CartItems = cart.GetCartItems(),
CartTotal = cart.GetTotal()
};
// Return the view
return View(viewModel);
}
//
// GET: /Store/AddToCart/5
public ActionResult AddToCart(int id)
{
// Retrieve the album from the database
var addedProduit = dbProduit.Produits
.Single(produit => produit.ProduitId == id);
// Add it to the shopping cart
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.AddToCart(addedProduit);
// Go back to the main store page for more shopping
return RedirectToAction("Index");
}
//
// AJAX: /ShoppingCart/RemoveFromCart/5
[HttpPost]
public ActionResult RemoveFromCart(int id)
{
// Remove the item from the cart
var cart = ShoppingCart.GetCart(this.HttpContext);
// Get the name of the album to display confirmation
string produitDescription = dbProduit.Paniers
.Single(item => item.PanierId == id).Produit.Description;
// Remove from cart
int itemCount = cart.RemoveFromCart(id);
// Display the confirmation message
var results = new ShoppingCartRemoveViewModel
{
Message = Server.HtmlEncode(produitDescription) +
" has been removed from your shopping cart.",
CartTotal = cart.GetTotal(),
CartCount = cart.GetCount(),
ItemCount = itemCount,
DeleteId = id
};
return Json(results);
/* return View("CartSummary"); */
}
//
// GET: /ShoppingCart/CartSummary
[ChildActionOnly]
public ActionResult CartSummary()
{
var cart = ShoppingCart.GetCart(this.HttpContext);
ViewData["CartCount"] = cart.GetCount();
return PartialView("CartSummary");
}
public ActionResult TableContent()
{
return PartialView("TableContent");
}
}
}

did you make sure Model.CartItems is not null?
try this :
#if (Model.CartItems != null) { <=== add breakpoint here
foreach (var item in Model.CartItems) <=== error is happening here
{
...
}
}
and add a breakpoint on the if and check if the value is null ;-)
edited:
in the ajax responce, you can reload the partialview ...
success: function (result) {
$('#yourPartialViewContainerId').load('/Action/PartialView');
...
but be sure your foreach items is not null inside your partialView ...

Related

not refreshing data in angular js

I write a web in mvc framework with angular js.
my application is:
var app = angular.module("AngularApp", []);
and my controller is:
app.controller("EmpCtrl", function ($scope, EmployeeService) {
GetAllEmployee();
function GetAllEmployee() {
var getAllEmployee = EmployeeService.getEmployee();
getAllEmployee.then(function (emp) {
$scope.employees = emp.data;
}, function () {
alert('data not found');
});
}
$scope.deleteEmployee = function (id) {
var getData = EmployeeService.DeleteEmp(id);
getData.then(function (msg) {
GetAllEmployee();
alert('Employee Deleted...');
$scope.h1message = true;
$scope.message = "ED";
}, function () {
$scope.h1message = true;
$scope.message = "Error in Deleting Record";
});
}
});
and my service is:
app.service("EmployeeService", function ($http) {
this.getEmployee = function () {
debugger;
return $http.get("/EmployeeModels/GetAllEmployee");
};
//Delete Employee
this.DeleteEmp = function (employeeId) {
var response = $http({
method: "post",
url: "/EmployeeModels/deleteEmployee",
params: {
employeeId: JSON.stringify(employeeId)
}
});
return response;
}
});
and my mvc action is :
private ApplicationDbContext db = new ApplicationDbContext();
public JsonResult GetAllEmployee()
{
using (ApplicationDbContext db = new ApplicationDbContext())
{
var employeeList = db.EmployeeModels.ToList();
return Json(employeeList, JsonRequestBehavior.AllowGet);
}
}
//DeleteEmployee
public string DeleteEmployee(string employeeId)
{
if (employeeId != null)
{
int no = Convert.ToInt32(employeeId);
var employeeList = db.EmployeeModels.Find(no);
db.EmployeeModels.Remove(employeeList);
db.SaveChanges();
return "Employee Deleted";
}
else { return "Invalid Employee"; }
}
and html file is:
<div ng-app="AngularApp" ng-init="name='hn';backGroundColor='red';
person={firstname:'jo',lastname:'hary'}">
<div ng-controller="EmpCtrl">
<table border="1" width="100%">
<tr>
<th ng-click="orderByMe('emp.EmployeeId')">employee id</th>
<th ng-click="orderByMe('Address')">addres</th>
<th ng-click="orderByMe('EmailId')">email id</th>
<th ng-click="orderByMe('EmployeeName')">employee name</th>
</tr>
<tr ng-repeat="emp in employees|orderBy:orderByMe">
<td> {{emp.EmployeeId}}</td>
<td> {{emp.Address}}</td>
<td>{{emp.EmailId}}</td>
<td>{{emp.EmployeeName}}</td>
<td><a data-ng-click="deleteEmployee(emp.EmployeeId)" style="cursor:pointer;">delete</a></td>
</tr>
</table>
</div>
the view of data is ok. but when I add record to table of database, view not refresh data?
Your view not refresh data because, your method GetAllEmployee() is called once, at the loading of page. you need to refresh your page.

Add jquery datatable filter to mvc.net page

How can I add jquery dataTable to this mvc page to implement filter? I don't know which parameters to use to initialize dataTable to use data from model, and how to do search on keyup on search grid.
<p>
#Html.ActionLink("Create New", "LandingCreate")
</p>
<table class="table" id="contentTable">
<tr>
<th>
#Html.DisplayNameFor(model => model.URL)
</th>
<th>
#Html.DisplayNameFor(model => model.HTMLText)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.URL)
</td>
<td>
#Html.DisplayFor(modelItem => item.HTMLText)
</td>
<td>
#Html.ActionLink("Edit", "LandingEdit", new { id = item.Id }) |
#Html.ActionLink("Delete","LandingDelete",
new { id = item.Id },
new { onclick = "return confirm('Are you sure you wish to delete this page?');" })
</td>
</tr>
}
</table>
EDIT
This is my script section:
#section Scripts
{
<script>
var settings = {
baseParameters: {
itemsPerPage: pageSettingStorage.defaultItemsPerPage,
hideColumns: []
},
parameters: {
start: 0,
search: '',
firstDate: firstDate,
lastDate: lastDate,
status: 'new',
order: [[0, "asc"]],
}
};
$(document).ready(function () {
$("#contentTable").DataTable({
paging: false,
"ajax": {
"url": "/Admin/LoadLanding",
"type": "GET",
"datatype":"json"
},
"columns": {
"data": "URL",
"data":"HTMLText"
}
});
});
LoadLanding method
public ActionResult LoadLanding()
{
var model = RepositoryManager.Instanse.LandingContentRepository.SelectAll();
return Json(new { data = model }, JsonRequestBehavior.AllowGet);
}
Change the return to this:
public ActionResult LoadLanding()
{
var model = RepositoryManager.Instanse.LandingContentRepository.SelectAll();
return Json(new { aaData = model.Select(x => new String[] {
x.URL,
x.HTMLText
})}, JsonRequestBehavior.AllowGet);
}

better way to load 2 dropdown in mvc

This is how i am loading on page load state and city dropdown:
My Controller method:
This is the first method which is calling when page is loaded.
public ActionResult Index()
{
var states = GetStates();
var cities = Enumerable.Empty<SelectListItem>();
ViewBag.States = states;
ViewBag.Cities = cities;
}
private IEnumerable<SelectListItem> GetStates()
{
using (var db = new DataEntities())
{
return db.States.Select(d => new SelectListItem { Text = d.StateName, Value =d.Id.ToString() });
}
}
[HttpGet]
public ActionResult GetCities(int id)
{
using (var db = new DataEntities())
{
var data = db.Cities.Where(d=>d.StateId==id).Select(d => new { Text = d.CityName, Value = d.Id }).ToList();
return Json(data, JsonRequestBehavior.AllowGet);
}
}
My View:
IEnumerable<SelectListItem> States = ViewBag.States;
IEnumerable<SelectListItem> Cities = ViewBag.Cities;
#Html.DropDownList("State", States, "Select State", new { onchange="loadCities(this)"})
#Html.DropDownListFor(m => m.CityId, Cities, "Select City", new { id="ddlCity"})
function loadCities(obj) {
$.ajax({
url: "/Home/GetCities",
data: { id: $(obj).val() },
contentType:"application/json",
success:function(responce){
var html = '<option value="0">Select City</option>';
$(responce).each(function () {
html += '<option value="'+this.Value+'">'+this.Text+'</option>'
});
$("#ddlCity").html(html);
}
});
}
Any better way then this to load state and city dropdown?
public class HomeController : Controller
{
public ActionResult Index(int id=0)
{
Person model = null;
var states = GetStates().ToList();
var cities = Enumerable.Empty<SelectListItem>();
if (id > 0)
{
using (var db = new DataEntities())
{
model = db.People.Include("City").FirstOrDefault(d => d.Id == id);
if (model == null)
model = new Person();
else
{
states.First(d => d.Value == model.City.StateId.ToString()).Selected = true;
cities = db.Cities.Where(d => d.StateId == model.City.StateId).ToList().Select(d => new SelectListItem { Text = d.CityName,Value=d.Id.ToString(),Selected=d.Id==model.CityId });
}
}
}
else
{
model = new Person();
}
ViewBag.States = states;
ViewBag.Cities = cities;
ViewBag.Persons = GetPersons();
return View(model);
}
[HttpGet]
public ActionResult GetCities(int id)
{
using (var db = new DataEntities())
{
var data = db.Cities.Where(d=>d.StateId==id).Select(d => new { Text = d.CityName, Value = d.Id }).ToList();
return Json(data, JsonRequestBehavior.AllowGet);
}
}
public ActionResult SavePersonDetail([Bind(Exclude = "Id")] Person model)
{
// var employeeDal= new Emploee();
//employee.firstname=model.
if (ModelState.IsValid)
{
var Id = model.Id;
int.TryParse(Request["Id"], out Id);
using (var db = new DataEntities())
{
if (Id > 0)
{
var person = db.People.FirstOrDefault(d => d.Id == Id);
if (person != null)
{
model.Id = Id;
db.People.ApplyCurrentValues(model);
}
}
else
{
db.People.AddObject(model);
}
db.SaveChanges();
}
}
if (!Request.IsAjaxRequest())
{
ViewBag.States = GetStates();
ViewBag.Persons = GetPersons();
ViewBag.Cities = Enumerable.Empty<SelectListItem>();
return View("Index");
}
else
{
return PartialView("_personDetail",GetPersons());
}
}
public ActionResult Delete(int id)
{
using (var db = new DataEntities())
{
var model = db.People.FirstOrDefault(d => d.Id == id);
if (model != null)
{
db.People.DeleteObject(model);
db.SaveChanges();
}
}
if (Request.IsAjaxRequest())
{
return Content(id.ToString());
}
else
{
ViewBag.States = GetStates();
ViewBag.Persons = GetPersons();
ViewBag.Cities = Enumerable.Empty<SelectListItem>();
return View("Index");
}
}
private IEnumerable<SelectListItem> GetStates()
{
using (var db = new DataEntities())
{
return db.States.ToList().Select(d => new SelectListItem { Text = d.StateName, Value =d.Id.ToString() });
}
}
private IEnumerable<Person> GetPersons()
{
using (var db = new DataEntities())
{
return db.People.Include("City").Include("City.State").ToList();
}
}
public ActionResult HomeAjax()
{
ViewBag.States = GetStates();
ViewBag.Cities = Enumerable.Empty<SelectListItem>();
using (var db = new DataEntities())
{
var data = db.States.Include("Cities").Select(d => new { Id = d.Id, Name = d.StateName, Cities = d.Cities.Select(x => new { Id=x.Id,Name=x.CityName}) }).ToList();
ViewBag.CityStateJson = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(data);
}
ViewBag.Persons = GetPersons();
return View();
}
}
#model IEnumerable<Person>
<div>
<table>
<tr>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Email
</th>
<th>
City
</th>
<th>
State
</th>
<th>
Edit
</th>
</tr>
#if (Model.Count() == 0)
{
<tr>
<td colspan="6">
<h3>No data available</h3>
</td>
</tr>
}
else {
foreach (var item in Model) {
<tr data-id="#item.Id">
<td data-id="fn">#item.FirstName</td>
<td data-id="ln">#item.LastName</td>
<td data-id="email">#item.Email</td>
<td data-id="cn">#item.CityName<input type="hidden" value="#item.CityId" /></td>
<td>#item.StateName</td>
<td>
#if (ViewBag.Title == "Home Ajax" || Request.IsAjaxRequest())
{
Update
<span>#Ajax.ActionLink("Delete", "Delete", new { id = item.Id }, new AjaxOptions {OnSuccess="deleteSuccess",OnBegin="showLoader",OnComplete="hideLoader" })</span>
}
else {
<span>#Html.ActionLink("Update", "Index", new { id = item.Id })</span>
<span>#Html.ActionLink("Delete", "Delete", new { id = item.Id })</span>
}
</td>
</tr>
}
}
</table>
</div>
#model Person
#{
ViewBag.Title = "Home Ajax";
IEnumerable<Person> persons = ViewBag.Persons;
IEnumerable<SelectListItem> States = ViewBag.States;
IEnumerable<SelectListItem> Cities = ViewBag.Cities;
IEnumerable<State> fullStates=ViewBag.CityStates;
}
#section featured {
<section class="featured">
<div class="content-wrapper">
<hgroup class="title">
<h1>#ViewBag.Title.</h1>
</hgroup>
</div>
</section>
}
#section styles{
<style type="text/css">
td,th {
border:1px solid;
padding:5px 10px;
}
select {
padding:5px 2px;
width:310px;
font-size:16px;
}
</style>
}
#section scripts{
#Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
var jsonArray = #Html.Raw(ViewBag.CityStateJson)
function clearValues() {
$("input[type='text'],select").val('');
$("input[type='hidden'][name='Id']").val(0);
}
function loadCities(obj) {
for (var i = 0; i < jsonArray.length; i++) {
if (jsonArray[i].Id == parseInt($(obj).val())) {
fillCity(jsonArray[i].Cities);
break;
}
}
}
function Edit(obj, Id) {
// alert("hi")
$("input[type='hidden'][name='Id']").val(Id);
var tr = $(obj).closest("tr");
$("#txtfirstName").val($("td[data-id='fn']", tr).text().trim());
$("#txtlastName").val($("td[data-id='ln']", tr).text().trim());
$("#txtemail").val($("td[data-id='email']", tr).text().trim());
var city = $("td[data-id='cn'] input[type='hidden']", tr).val();
var state;
for (var i = 0; i < jsonArray.length; i++) {
for (var j = 0; j < jsonArray[i].Cities.length; j++) {
if (jsonArray[i].Cities[j].Id == parseInt(city)) {
state = jsonArray[i].Id;
break;
}
}
if (state) {
fillCity(jsonArray[i].Cities);
break;
}
}
$("#ddlState").val(state);
$("#ddlCity").val(city);
}
function fillCity(obj) {
var html = '<option value="0">Select City</option>';
$(obj).each(function () {
html += '<option value="' + this.Id + '">' + this.Name + '</option>'
});
$("#ddlCity").html(html);
}
function deleteSuccess(responce) {
alert("record deleted successfully");
$("tr[data-id='" + responce + "']").remove();
}
function insertSuccess() {
alert("Record saved successfully");
clearValues();
}
function showLoader() {
$("#overlay").show();
}
function hideLoader() {
$("#overlay").hide();
}
</script>
}
<h3>Add Personal Detail</h3>
#using (Ajax.BeginForm("SavePersonDetail", "Home", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "personList" ,OnSuccess="insertSuccess",OnBegin="showLoader",OnComplete="hideLoader"}))
{
#Html.HiddenFor(m => m.Id);
<ol class="round">
<li>
#Html.LabelFor(m => m.FirstName)
#Html.TextBoxFor(m => m.FirstName, new { id = "txtfirstName" })
#Html.ValidationMessageFor(m => m.FirstName)
</li>
<li>
#Html.LabelFor(m => m.LastName)
#Html.TextBoxFor(m => m.LastName, new { id = "txtlastName" })
#Html.ValidationMessageFor(m => m.LastName)
</li>
<li>
#Html.LabelFor(m => m.Email)
#Html.TextBoxFor(m => m.Email, new { id = "txtemail" })
#Html.ValidationMessageFor(m => m.Email)
</li>
<li>
#Html.Label("State")
#Html.DropDownList("State", States, "Select State", new { onchange = "loadCities(this)", id = "ddlState" })
</li>
<li>
#Html.LabelFor(m => m.CityId)
#Html.DropDownListFor(m => m.CityId, Cities, "Select City", new { id = "ddlCity" })
#Html.ValidationMessageFor(m => m.CityId)
</li>
</ol>
<input type="submit" value="Save" />
<input type="button" value="Cancel" onclick="clearValues();"/>
}
<h2>
Person List
</h2>
<div style="position:fixed;text-align:center;top:0;bottom:0;left:0;right:0;z-index:10;background-color:black;opacity:0.6;display:none;" id="overlay">
<img style="position:relative;top:370px" src="~/Images/ajax-loader.gif" />
</div>
<div id="personList">
#Html.Partial("_personDetail", persons)
</div>
You approach using ajax is fine although I would recommend a few better practices including using a view model with properties for StateID, CityID StateList and CityList, and using Unobtrusive JavaScript rather than polluting you markup with behavior, and generating the first ("please select") option with a null value rather than 0 so it can be used with the [Required] attribute
HTML
#Html.DropDownList(m => m.StateID, States, "Select State") // remove the onchange
#Html.DropDownListFor(m => m.CityID, Cities, "Select City") // why change the default ID?
SCRIPT
var url = '#Url.Action("GetCities", "Home")'; // use the helper (dont hard code)
var cities = $('#CityID'); // cache the element
$('#StateID').change(function() {
$.getJSON(url, { id: $(this).val() }, function(response) {
// clear and add default (null) option
cities.empty().append($('<option></option>').val('').text('Please select'));
$.each(response, function(index, item) {
cities.append($('<option></option>').val(item.Value).text(item.Text));
});
});
});
If you were rendering multiple items (say you were asking the user to select their last 10 cities they visited), you can cache the result of the first call to avoid repeated calls where their selections may include cities from the same state.
var cache = {};
$('#StateID').change(function() {
var selectedState = $(this).val();
if (cache[selectedState]) {
// render the options from the cache
} else {
$.getJSON(url, { id: selectedState }, function(response) {
// add to cache
cache[selectedState] = response;
.....
});
}
});
Finally, in response to your comments regarding doing it without ajax, you can pass all the cities to the view and assign them to a javascript array. I would only recommend this if you have a few countries, each with a few cities. Its a matter of balancing the slight extra initial load time vs the slight delay in making the ajax call.
In the controller
model.CityList = db.Cities.Select(d => new { City = d.CountryID, Text = d.CityName, Value = d.Id }).ToList();
In the view (script)
// assign all cities to javascript array
var allCities= JSON.parse('#Html.Raw(Json.Encode(Model.CityList))');
$('#StateID').change(function() {
var selectedState = $(this).val();
var cities = $.grep(allCities, function(item, index) {
return item.CountryID == selectedState;
});
// build options based on value of cities
});
This is a correct approach, but you can simplify your javascript:
function loadCities(obj) {
$.getJSON("/Home/GetCities", function (data) {
var html = '<option value="0">Select City</option>';
$(data).each(function () {
html += '<option value="'+this.Value+'">'+this.Text+'</option>'
});
$("#ddlCity").html(html);
});
}
Further possible simplification:
Add the default item (Select City) server-side, so your javascript will be smaller.
Here's how I'd do it without the page refresh, assuming the list of cities isn't too long.
I'm assuming you can create a GetStatesAndCities method to return a Dictionary.
public ActionResult Index()
{
Dictionary<string, List<String>> statesAndCities = GetStatesAndCities();
ViewBag.StatesAndCities = Json(statesAndCities);
}
Then in the view:
var states = JSON.parse(#ViewBag.StatesAndCities);
function loadCities(obj) {
var cities = states[$(obj).val()];
var html = '<option value="0">Select City</option>';
$(cities).each(function () {
html += '<option value="'+this.Value+'">'+this.Text+'</option>'
});
$("#ddlCity").html(html);
}
This way when the state is changed the cities field with update immediately with no need for callback.
disclaimer: This is not a code answer, there are plenty other answers.
I think best way to keep yourself happy to seperate UI pages from data => turn them into API calls:
/GetCities
/GetStates
Now you can simply leave the select's empty on Razor rendering the page. And use a Jquery/Bootstrap plugin to create an AJAX select box.
This way when the user stops typing his search, this search string can than be send with the AJAX call (eg: /GetStates?search=test) and then a small result set can be send back to the website.
This gives:
Better separation in serveside code
Better User eXperience.
Smaller page loads (since you no longer send all the options to user when he requests the page, only when he opens the select box).
How about using Knockout?
Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model
You have to use ajax for your cities. But with knockout you dont need to write
var html = '<option value="0">Select City</option>';
$(responce).each(function () {
html += '<option value="'+this.Value+'">'+this.Text+'</option>'});
$("#ddlCity").html(html);
in your javascript.Knockout makes it simple.
You can simply write:
function CityModel() {
var self = this; // that means this CityModel
self.cities = ko.observableArray([]);
self.getCities = function () {
$.ajax({
url: "/Home/GetCities",
data: { id: $(obj).val() },
contentType: "application/json",
success: self.cities
});
}
}
ko.applyBindings(new CityModel());
thats all. But you have to bind your data into html elements.
Instead of using :
#Html.DropDownListFor(m => m.CityId, Cities, "Select City", new { id="ddlCity"})
You can use:
<select data-bind="options:cities,optionsValue:"Id",optionsText:"CityName",optionsCaption:"Select City""></select>
or you can mix razor and knockout:
#Html.DropDownListFor(m => m.CityId, Cities, "Select City", new { id="ddlCity",data_bind:"options:cities,optionsValue:\"Id\",optionsText:\"CityName\""})
One more thing you have to call GetCities when State changes, you can :
#Html.DropDownList("State", States, "Select State", new {data_bind:"event:\"change\":\"$root.GetCities\""})
Dont be scare with \"\" things this because " is an escape character and we have to say to razor i want to use " by using \ before it.
You can find more info about knockout :Knockout
And mixing with razor: Razor and Knockout
Ps: yes using knockout is suspend us from Razor and Mvc. You have to write another ViewModel . But like this situations ko is helpful. Mixing razor and knockout is another option for you.

how can I show the user that the data is gone when he trying to edit a field?

so when the user click the edit link to edit one of the client (field) and another user have erase already that client how can show to the user that the client (field) is gone?
so I'am using TempData is another way to do it? i think jquery but i don't know how to use it properly
public ActionResult Edit (int id)
{
client cliente = db.Clients.Find(id);
if (cliente != null)
{
return View(cliente);
}
TempData["message"] = string.Format("this client have be erase for other user");
return RedirectToAction("Index");
}
edit:
and view is this
<table class="widgets">
<tr>
<th></th>
<th>
#Html.ActionLink("Nombre", "Index", new { ordenacion = ViewBag.NameSortParm, filtro = ViewBag.filtro })
</th>
</tr>
#foreach (var item in Model) {
<tr id="widget-id-#item.id">
<td>
#Html.ActionLink("Editar", "Edit", new { id=item.id }) |
#Ajax.ActionLink("Eliminar", "Eliminar", "Cliente",
new {item.id },
new AjaxOptions {
HttpMethod = "POST",
Confirm = string.Format("Esta Seguro que quiere eliminar '{0}'?", item.descripcion),
OnSuccess = "deleteConfirmation"
})
</td>
<td>
#Html.DisplayFor(modelItem => item.descripcion)
</td>
</tr>
}
</table>
i guees the script will be this? so i have to make my edit link like i did for the delete (eliminar) link using #Ajax.ActionLink right?
<script type="text/javascript">
var validateForEdit = function (id) {
var validateCallbackFunction = function (result) {
if (result) {
window.location = '/Client/Editar/' + id;
}
else {
window.Alert('this client have be erase for other user');
}
};
$.post('/Client/ValidateForEdit/', { id: id }, validateCallbackFunction, 'json');
}
</script>
Hi you can use following code to validate data before user can edit that
var validateForEdit = function (id) {
var validateCallbackFunction = function (result) {
if (result) {
window.location = '/Client/Edit/' + id;
}
else {
Alert('this client have be erase for other user');
}
};
$.post('/Client/ValidateForEdit/', { id: id }, validateCallbackFunction, 'json');
}
And your Action :
[HttpPost]
public JsonResult ValidateForEdit(int id)
{
var cliente = db.Clients.Find(id);
return cliente != null ? Json(true) : Json(false);
}
Edit : And you have to replace your following code
#Html.ActionLink("Editar", "Edit", new { id=item.id })
with this code :
<input class="button" type="button" value="Edit" onclick="validateForEdit(item.id)" />
Hope this help.

Add Sorting and Searching in Contact Management ASP.NET MVC Application

I have implemented the "Contact Management ASP.NET MVC Application" with Razor view.
http://www.asp.net/mvc/tutorials/iteration-7-add-ajax-functionality-cs
Now I want to add Sorting and Searching functionality.
And Paging too.
snapshot: ->
http://www.freeimagehosting.net/daf63
I want to display the sorted and searched results inside the "green box", by click of a sort links and search button.
What changes do I need to perform?
My current Index Controller:
public ActionResult Index(int? id, string sortorder, string searchstring)
{
ViewBag.CurrentSort = sortorder;
ViewBag.disp = n2;
ViewBag.NameSortParm = String.IsNullOrEmpty(sortorder) ? "Namedesc" : " ";
ViewBag.NameSortParma = String.IsNullOrEmpty(sortorder) ? "Nameasc" : " ";
ViewBag.NameSortParmb = String.IsNullOrEmpty(sortorder) ? "Namedescx" : " ";
ViewBag.NameSortParmc = String.IsNullOrEmpty(sortorder) ? "Nameascx" : " ";
if (sortorder != null || searchstring != null)
{
var matches = cmu.Contacts.Where(a => a.GroupId == (int)id);
var contacts = from s in matches
select s;
if (!String.IsNullOrEmpty(searchstring))
{
contacts = contacts.Where(s => s.FirstName.ToUpper().Contains(searchstring.ToUpper()) || s.LastName.ToUpper().Contains(searchstring.ToUpper()));
}
switch (sortorder)
{
case "Namedesc":
contacts = contacts.OrderByDescending(s => s.FirstName);
break;
case "Nameasc":
contacts = contacts.OrderBy(s => s.FirstName);
break;
case "Namedescx":
contacts = contacts.OrderByDescending(s => s.LastName);
break;
case "Nameascx":
contacts = contacts.OrderBy(s => s.LastName);
break;
}
return PartialView("SearchSort", contacts.ToList());
}
// Get selected group
var selectedGroup = _service.GetGroup(id);
if (selectedGroup == null)
return RedirectToAction("Index", "Group");
// Normal Request
if (!Request.IsAjaxRequest())
{
var model = new IndexModel
{
Groups = _service.ListGroups(),
SelectedGroup = selectedGroup
};
return View("Index", model);
}
return PartialView("ContactList", selectedGroup);
}
My Index View:
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#model New_Contact_Manager_with_Razor_View.Models.Validation.IndexModel
#using New_Contact_Manager_with_Razor_View.Helpers
<style type = "text/css">
#gallery {
border: 0.5px solid #1D0C16;
height: 150;
width: 150px;
display:inline-table;
border-spacing : 5px;
margin-bottom:5px;
border-style:outset;
}
</style>
<style type="text/css">
h1, h2, h3, h4, h5, h6, h7 {color:black}
</style>`
<script type="text/javascript">
function Showtdata(item) {
var elements = document.getElementsByClassName(item);
for (var i = 0, length = elements.length; i < length; i++) {
elements[i].style.visibility = "visible";
elements[i].style.display = "block";
}
}
function Cleartdata(item) {
var elements = document.getElementsByClassName(item);
for (var i = 0, length = elements.length; i < length; i++) {
elements[i].style.visibility = "hidden";
elements[i].style.display = "none";
}
}
</script>
<script type="text/javascript">
var _currentGroupId = -1;
Sys.Application.add_init(pageInit);
function pageInit() {
// Enable history
Sys.Application.set_enableHistory(true);
// Add Handler for history
Sys.Application.add_navigate(navigate);
}
function navigate(sender, e) {
// Get groupId from address bar
var groupId = e.get_state().groupId;
// If groupId != currentGroupId then navigate
if (groupId != _currentGroupId) {
_currentGroupId = groupId;
$("#divContactList").load("/Contact/Index/" + groupId);
selectGroup(groupId);
}
}
function selectGroup(groupId) {
$('#leftColumn li').removeClass('selected');
if (groupId)
$('a[groupid=' + groupId + ']').parent().addClass('selected');
else
$('#leftColumn li:first').addClass('selected');
}
function beginContactList(args) {
// Highlight selected group
_currentGroupId = this.getAttribute("groupid");
selectGroup(_currentGroupId);
// Add history point
Sys.Application.addHistoryPoint({ "groupId": _currentGroupId });
// Animate
$('#divContactList').fadeOut('normal');
}
function successContactList() {
// Animate
$('#divContactList').fadeIn('normal');
}
function failureContactList() {
alert("Could not retrieve contacts.");
}
</script>
#using New_Contact_Manager_with_Razor_View.Helpers
#{
ViewBag.Title = "Contacts";
}
<table>
<tr>
<td>
<h3>
<form>
<table>
<tr>
<td>
Display-> &nbsp &nbsp &nbsp
<input type = "radio" value = "Display " name = "display" onclick= Showtdata("HD") />
</td>
</tr>
<tr>
<td>
Not Display->
<input type = "radio" value = "Not Display " name= "display" onclick= Cleartdata("HD") />
</td>
</tr>
</table>
</form>
</h3>
</td>
<td>
&nbsp &nbsp &nbsp &nbsp
</td>
<td>
<b><strong>Sort :~> </strong></b>
<table>
<tr>
<td>
#Html.ActionLink("First Name Desc", "Index", new { sortorder = ViewBag.NameSortParm })
</td>
</tr>
<tr>
<td>
#Html.ActionLink("First Name", "Index", new { sortorder = ViewBag.NameSortParma })
</td>
</tr>
<tr>
<td>
#Html.ActionLink("Last Name desc", "Index", new { sortorder = ViewBag.NameSortParmb })
</td>
</tr>
<tr>
<td>
#Html.ActionLink("Last Name", "Index", new { sortorder = ViewBag.NameSortParmc })
</td>
</tr>
</table>
</td>
<td>
&nbsp &nbsp &nbsp
</td>
<td>
#using (Html.BeginForm())
{
<p>
<b>Find by name:</b> #Html.TextBox("searchstring")
<input type="submit" value = "search" />
</p>
}
</td>
</tr>
</table>
<ul id="leftColumn">
#foreach (var item in Model.Groups)
{
<li #Html.Selected(item.Id, Model.SelectedGroup.Id) >
#Ajax.ActionLink(item.Name, "Index", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divContactList", OnBegin = "beginContactList", OnSuccess = "successContactList", OnFailure = "failureContactList" }, new { groupid = item.Id })
</li>
}
</ul>
<div id="divContactList" >
#Html.Partial("ContactList", Model.SelectedGroup)
</div>
<div class="divContactList-bottom"> </div>
Is it possible to add sorting and searching functionality by AJAX or JavaScript?
Any help would be heartily appreciated.
Thank You.
While it's a different type of answer, I would have a look at jqGrid. It's a jquery plugin that will help you page, sort, and search through your tabular data.
http://www.trirand.com/blog/

Categories

Resources