I have a problem with a project for my school.
I want to hide a button if the connectedUser had already vote for a post.
my fonctions on my controller is obviously not use (I tried to put a Console.Writeline("blabla") to try but no "blabla" on my console so I guess it's a problem with my root but I don't understand how to do it properly
this is my button in the html :
<button [hidden]="getVoteForPostConnectedUserPlus(post.id)" mat-icon-button>
<mat-icon (click)="down(post.id)">arrow_drop_down</mat-icon>
</button>
this is my fonction in the ts file:
getVoteForPostConnectedUserPlus(postId : number){
this.postService.getVoteForPostConnectedUserPlus(postId, this.getCurrentUserId);
}
this is my fonction in post.service.ts :
public getVoteForPostConnectedUserPlus(postId : number , userId : number){
return this.http.get<boolean>(`${this.baseUrl}api/posts/getVoteForPostConnectedUserPlus/${postId}/${userId}`)
}
and this is in my controller :
[HttpGet("getVoteForPostConnectedUserPlus/{postId}/{authorId}")]
public async Task<ActionResult<bool>> getVoteForPostConnectedUserPlus(int postId, int UserId)
{
Console.WriteLine("blabla");
Console.WriteLine("post id =" + postId + "userId =" + UserId + "");
var vote = await _context.Votes.SingleOrDefaultAsync(v => v.PostId == postId && v.AuthorId == UserId && v.UpDown == 1);
Console.WriteLine(vote.AuthorId);
if (vote != null)
{
return true;
}
else
{
return false;
}
}
I spend hours to find where is my problem and I become crazy ! I probably didn't understood something to make my root so if someone can help me it would be great !
thank you
edit : here is all my PostsController.cs (as asked in a comment) :
using System;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using prid1920_projet.Models;
using PRID_Framework;
using Microsoft.AspNetCore.Authorization;
namespace prid1920_projet.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class PostsController : ControllerBase
{
private readonly PridContext _context;
public PostsController(PridContext context)
{
_context = context;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<PostDTO>>> GetQuestions()
{
var questions = (from q in _context.Posts where q.ParentId == null select q);
return (await questions.ToListAsync()).ToDTO();
}
//[Authorized(Role.Admin)]
[HttpGet("{id}")]
public async Task<ActionResult<PostDTO>> GetById(int id)
{
var post = await _context.Posts.FindAsync(id);
if (post == null)
return NotFound();
return post.ToDTO();
}
[HttpPost]
public async Task<ActionResult<PostDTO>> PostPost(PostDTO data)
{
var userPseudo = User.Identity.Name;
var newPost = new Post()
{
Author = (from u in _context.Users where u.Pseudo == userPseudo select u).FirstOrDefault(),
Title = data.Title,
Body = data.Body,
Timestamp = DateTime.Now,
ParentId = data.parentId,
//postTags ??
};
_context.Posts.Add(newPost);
var res = await _context.SaveChangesAsyncWithValidation();
if (!res.IsEmpty)
return BadRequest(res);
return CreatedAtAction(nameof(GetById), new { id = newPost.Id }, newPost.ToDTO());
}
[AllowAnonymous]
[HttpPost("accept/{id}")]
public async Task<ActionResult<bool>> Accept(int id)
{
var post = await _context.Posts.FindAsync(id);
if (post == null)
return NotFound();
var postParent = await _context.Posts.FindAsync(post.ParentId);
if (postParent == null)
return NotFound();
postParent.AcceptedAnswerId = id;
var res = await _context.SaveChangesAsyncWithValidation();
if (!res.IsEmpty)
return false;
return true;
}
[AllowAnonymous]
[HttpPost("up/{postId}/{authorId}")]
public async Task<ActionResult<bool>> Up(int postId, int authorId)
{
var vote = await _context.Votes.SingleOrDefaultAsync(p => p.PostId == postId && p.AuthorId == authorId);
if (vote != null)
{
vote.UpDown = +1;
}
else
{
Vote newVote = new Vote()
{
UpDown = 1,
AuthorId = authorId,
PostId = postId
};
_context.Votes.Add(newVote);
}
var res = await _context.SaveChangesAsyncWithValidation();
if (!res.IsEmpty)
return false;
return true;
}
[AllowAnonymous]
[HttpPost("down/{postId}/{authorId}")]
public async Task<ActionResult<bool>> Down(int postId, int authorId)
{
var vote = await _context.Votes.SingleOrDefaultAsync(p => p.PostId == postId && p.AuthorId == authorId);
if (vote != null)
{
vote.UpDown = -1;
}
else
{
Vote newVote = new Vote()
{
UpDown = -1,
AuthorId = authorId,
PostId = postId
};
_context.Votes.Add(newVote);
}
var res = await _context.SaveChangesAsyncWithValidation();
if (!res.IsEmpty)
return false;
return true;
}
[AllowAnonymous]
[HttpPost("clear/{postId}/{authorId}")]
public async Task<ActionResult<bool>> Clear(int postId, int authorId)
{
var vote = await _context.Votes.SingleOrDefaultAsync(p => p.PostId == postId && p.AuthorId == authorId);
if (vote.UpDown == 1 || vote.UpDown == -1)
{
_context.Remove(vote);
}
var res = await _context.SaveChangesAsyncWithValidation();
if (!res.IsEmpty)
return false;
return true;
}
[HttpGet("getVoteForPostConnectedUserMinus/{postId}/{authorId}")]
public async Task<ActionResult<bool>> getVoteForPostConnectedUserMinus(int postId, int userId)
{
Console.WriteLine("prout");
Console.WriteLine("post id =" + postId + "userId =" + userId + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
var vote = await _context.Votes.SingleOrDefaultAsync(v => v.PostId == postId && v.AuthorId == userId && v.UpDown == -1);
Console.WriteLine(vote + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
if (vote != null)
{
return true;
}
else
{
return false;
}
}
[HttpGet("getVoteForPostConnectedUserPlus/{postId}/{authorId}")]
public async Task<ActionResult<bool>> getVoteForPostConnectedUserPlus(int postId, int UserId)
{
Console.WriteLine("blabla");
Console.WriteLine("post id =" + postId + "userId =" + UserId + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
var vote = await _context.Votes.SingleOrDefaultAsync(v => v.PostId == postId && v.AuthorId == UserId && v.UpDown == 1);
Console.WriteLine(vote.AuthorId + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
if (vote != null)
{
return true;
}
else
{
return false;
}
}
[HttpGet("{postId}/{authorId}")]
public async Task<ActionResult<bool>> getVoteForPostConnectedUser(int postId, int UserId)
{
Console.WriteLine("prout");
Console.WriteLine("post id =" + postId + "userId =" + UserId + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
var vote = await _context.Votes.SingleOrDefaultAsync(v => v.PostId == postId && v.AuthorId == UserId);
Console.WriteLine(vote.AuthorId + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
if (vote != null)
{
return true;
}
else
{
return false;
}
}
}
}
Here I think the basic idea is wrong. Agnular change detection will run on every event and will try to reeavluate your expression, and each time it will call you api. What you could do is
change HTML to a static varible
<button [hidden]="postIsHidden" mat-icon-button>
<mat-icon (click)="down(post.id)">arrow_drop_down</mat-icon>
</button>
and for the .ts file
postIsHidden:boolean=true
ngOnInit(){
this.getVoteForPostConnectedUserPlus(/*your post id*/)
}
getVoteForPostConnectedUserPlus(postId : number){
this.postService.getVoteForPostConnectedUserPlus(postId, this.getCurrentUserId)
.subscribe((result)=>this.postIsHidden);
}
Related
Problem arises in this snippet, but i dont really know why(code is from a tutorial
https://www.youtube.com/watch?v=b0CrSerID1A&list=PLjCTEYO9N-j0wMr_p9j92lfgbY4E9c_Ds&index=16
PICTURE of problem
public string GetCartId(HttpContext context)
{
if (context.Session[CartSessionKey] == null)
{
if (!string.IsNullOrWhiteSpace(context.User.Identity.Name))
{
context.Session[CartSessionKey] =
context.User.Identity.Name;
}
else
{
Guid tempCartId = Guid.NewGuid();
context.Session[CartSessionKey] = tempCartId.ToString();
}
}
return context.Session[CartSessionKey].ToString();
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNetCore.Http;
namespace DogSupreme.Models
{
public class ShoppingCart
{
private ContextClass accsess = new ContextClass();
string ShoppingCartId { get; set; }
public const string CartSessionKey = "CartId";
public static ShoppingCart GetCart(HttpContext context)
{
var cart = new ShoppingCart();
cart.ShoppingCartId = cart.GetCartId(context);
return cart;
}
// Helper method to simplify shopping cart calls
public static ShoppingCart GetCart(Microsoft.AspNetCore.Mvc.Controller controller)
{
return GetCart(controller.HttpContext);
}
public void AddToCart(Product item)
{
var cartItem = accsess.Carts.SingleOrDefault(
c => c.CartId == ShoppingCartId
&& c.ItemId == item.ProductId);
if (cartItem == null)
{
cartItem = new Cart
{
ItemId = item.ProductId,
CartId = ShoppingCartId,
Count = 1,
DateCreated = DateTime.Now
};
accsess.Carts.Add(cartItem);
}
else
{
cartItem.Count++;
}
accsess.SaveChanges();
}
public int RemoveFromCart(int id)
{
var cartItem = accsess.Carts.Single(
cart => cart.CartId == ShoppingCartId
&& cart.RecordId == id);
int itemCount = 0;
if (cartItem != null)
{
if (cartItem.Count > 1)
{
cartItem.Count--;
itemCount = cartItem.Count;
}
else
{
accsess.Carts.Remove(cartItem);
}
accsess.SaveChanges();
}
return itemCount;
}
public void EmptyCart()
{
var cartItems = accsess.Carts.Where(
cart => cart.CartId == ShoppingCartId);
foreach (var cartItem in cartItems)
{
accsess.Carts.Remove(cartItem);
}
accsess.SaveChanges();
}
public List<Cart> GetCartItems()
{
return accsess.Carts.Where(
cart => cart.CartId == ShoppingCartId).ToList();
}
public int GetCount()
{
int? count = (from cartItems in accsess.Carts
where cartItems.CartId == ShoppingCartId
select (int?)cartItems.Count).Sum();
return count ?? 0;
}
public decimal GetTotal()
{
decimal? total = (from cartItems in accsess.Carts
where cartItems.CartId == ShoppingCartId
select (int?)cartItems.Count *
cartItems.Product.Price).Sum();
return total ?? decimal.Zero;
}
public int CreateOrder(Order order)
{
decimal orderTotal = 0;
var cartItems = GetCartItems();
foreach (var item in cartItems)
{
var orderDetail = new OrderDetail
{
ItemId = item.ItemId,
OrderId = order.OrderId,
UnitPrice = item.Product.Price,
Quantity = item.Count
};
orderTotal += (item.Count * item.Product.Price);
accsess.OrderDetails.Add(orderDetail);
}
order.Total = orderTotal;
accsess.SaveChanges();
EmptyCart();
return order.OrderId;
}
public string GetCartId(HttpContext context)
{
if (context.Session[CartSessionKey] == null)
{
if (!string.IsNullOrWhiteSpace(context.User.Identity.Name))
{
context.Session[CartSessionKey] =
context.User.Identity.Name;
}
else
{
Guid tempCartId = Guid.NewGuid();
context.Session[CartSessionKey] = tempCartId.ToString();
}
}
return context.Session[CartSessionKey].ToString();
}
public void MigrateCart(string userName)
{
var shoppingCart = accsess.Carts.Where(
c => c.CartId == ShoppingCartId);
foreach (Cart item in shoppingCart)
{
item.CartId = userName;
}
accsess.SaveChanges();
}
}
}
You can use extension methods (Microsoft.AspNetCore.Http.Extensions) to get or set string session keys:
public string GetCartId(HttpContext context)
{
var session = context.Session;
if (!session.Keys.Contains(CartSessionKey))
{
var userName = context.User.Identity.Name;
if (!string.IsNullOrWhiteSpace(userName))
{
session.SetString(CartSessionKey, userName);
}
else
{
Guid tempCartId = Guid.NewGuid();
session.SetString(CartSessionKey, tempCartId.ToString())
}
}
return session.GetString(CartSessionKey);
}
Otherwise you should manually convert strings to and from byte array
Slightly refactored code to split cartId generation from working with session:
public string GetCartId(HttpContext context)
{
var cartId = context.Session.GetString(CartSessionKey);
if (cartId == null)
{
cartId = GetUserCartId(context.User.Identity.Name);
context.Session.SetString(CartSessionKey, cartId);
}
return cartId;
}
private void GetUserCartId(string userName)
{
if (!string.IsNullOrWhiteSpace(userName))
return userName;
var tempCartId = Guid.NewGuid();
return tempCartId.ToString();
}
This might be an obvious answer that I am overthinking but I need help retrieving values from a database that share a property.
My database:
This specific MenuItems database contains menu items and links to my restaurant database. There is a RestaurantID column that represents which restaurant the item belongs to.
Pretty simple but just for example: the chicken nuggets with ID 1 belongs to the Restaurant with ID 1.
I need to perform a query that will retrieve a list of menu items that share the same RestaurantID. So for example: since I am querying for items with the RestuarantID == 1, it will retrieve 9 items from the database. I'm having trouble singling out the common values in my function below:
public async Task<IActionResult> GetRestaurantOneVals()
{
int id = 1; //Restuarant one's ID is == 1
var menuItem = await _context.MenuItems
.Include(s => s.Restaurant)
.AsNoTracking()
.FirstOrDefaultAsync(nameof => nameof.Restaurant.ID == id);
var restaurantList = menuItem;
return View(menuItem);
}
Here is the full controller:
MenuItemsController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using EasyEats.Data;
using EasyEats.Models;
namespace EasyEats.Controllers
{
public class MenuItemsController : Controller
{
private readonly EasyEatsContext _context;
public MenuItemsController(EasyEatsContext context)
{
_context = context;
}
// GET: MenuItems
public async Task<IActionResult> Index()
{
var easyEatsContext = _context.MenuItems.Include(m => m.Restaurant);
return View(await easyEatsContext.ToListAsync());
}
// GET: MenuItems/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var menuItem = await _context.MenuItems
.Include(m => m.Restaurant)
.FirstOrDefaultAsync(m => m.ID == id);
if (menuItem == null)
{
return NotFound();
}
return View(menuItem);
}
public async Task<IActionResult> GetRestaurantOneVals()
{
int id = 1; //Restuarant one's ID is == 1
var pleaseGod = await _context.MenuItems
var menuItem = await _context.MenuItems
.Include(s => s.Restaurant)
.AsNoTracking()
.FirstOrDefaultAsync(nameof => nameof.Restaurant.ID == id);
var restaurantList = menuItem;
return View(menuItem);
}
// GET: MenuItems/Create
public IActionResult Create()
{
ViewData["RestaurantID"] = new SelectList(_context.Restaurants, "ID", "ID");
return View();
}
// POST: MenuItems/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ID,ItemName,ItemDescription,ItemImagePath,Price,RestaurantID")] MenuItem menuItem)
{
if (ModelState.IsValid)
{
_context.Add(menuItem);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["RestaurantID"] = new SelectList(_context.Restaurants, "ID", "ID", menuItem.RestaurantID);
return View(menuItem);
}
// GET: MenuItems/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var menuItem = await _context.MenuItems.FindAsync(id);
if (menuItem == null)
{
return NotFound();
}
ViewData["RestaurantID"] = new SelectList(_context.Restaurants, "ID", "ID", menuItem.RestaurantID);
return View(menuItem);
}
// POST: MenuItems/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,ItemName,ItemDescription,ItemImagePath,Price,RestaurantID")] MenuItem menuItem)
{
if (id != menuItem.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(menuItem);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MenuItemExists(menuItem.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
ViewData["RestaurantID"] = new SelectList(_context.Restaurants, "ID", "ID", menuItem.RestaurantID);
return View(menuItem);
}
// GET: MenuItems/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var menuItem = await _context.MenuItems
.Include(m => m.Restaurant)
.FirstOrDefaultAsync(m => m.ID == id);
if (menuItem == null)
{
return NotFound();
}
return View(menuItem);
}
// POST: MenuItems/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var menuItem = await _context.MenuItems.FindAsync(id);
_context.MenuItems.Remove(menuItem);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool MenuItemExists(int id)
{
return _context.MenuItems.Any(e => e.ID == id);
}
}
}
MenuItem.cs Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace EasyEats.Models
{
public class MenuItem
{
public int ID { get; set; }
[Display(Name = "Item Name")]
public string ItemName { get; set; }
[Display(Name = "Item Description")]
public string ItemDescription { get; set; }
public string ItemImagePath { get; set; }
public decimal Price { get; set; }
public int RestaurantID { get; set; }
public virtual Restaurant Restaurant { get; set; }
public virtual CartItem CartItem { get; set; }
}
}
You are using FirstOrDefaultAsync() which will retrieve the first element which matches the parameters given, but you want to return an entire list which match the parameters. Change:
var menuItem = await _context.MenuItems
.Include(s => s.Restaurant)
.AsNoTracking()
.FirstOrDefaultAsync(nameof => nameof.Restaurant.ID == id);
To this in you GetRestaurantOneVals() method:
var menuItems = await _context.MenuItems
.Include(s => s.Restaurant)
.AsNoTracking()
.Where(x => x.Restaurant.Id == id)
.ToListAsync();
.Where() will fetch all of the objects matching the given statements, and ToList() will create a List<T> out of the query.
Then simply return View(menuItems);.
I have some code that is checking for possible duplicate entries. What I'm struggling with is where and what to put to let the user know - probably a modal of some sort, displaying the message that a duplicate user already exists.
Model
public void SaveUser(SearchRolesViewModel objSearchRolesViewModel, string userID)
{
USERACCOUNT objUserAccount = new USERACCOUNT
{
HPID = Convert.ToInt32(objSearchRolesViewModel.NewUserHealthPlans),
DOMAIN = "Aeth",
NTUSERID = objSearchRolesViewModel.User_Id,
ROLEID = Convert.ToInt32(objSearchRolesViewModel.UserRole),
FIRSTNAME = objSearchRolesViewModel.FirstName,
LASTNAME = objSearchRolesViewModel.LastName,
EMAIL = objSearchRolesViewModel.Email,
ACTIVE = true/*Convert.ToBoolean(objSearchRolesViewModel.ActiveStatus)*/,
DEFAULTPLANID = Convert.ToInt32(objSearchRolesViewModel.NewUserPrimaryHealthPlan),
CREATEID = userID.Substring(5).ToUpper(),
CREATEDATE = DateTime.Now,
UPDATEID = userID.Substring(5).ToUpper(),
UPDATEDATE = DateTime.Now
};
if (CheckforDuplicate(objUserAccount.NTUSERID, objUserAccount.HPID).Count == 0)
{
_context.USERACCOUNTs.Add(objUserAccount);
_context.SaveChanges();
}
else
{
WHAT GOES HERE
}
}
Controller
[HttpPost]
public ActionResult Submit(SearchRolesViewModel searchRolesViewModel)
{
try
{
SearchRolesModel objUser = new SearchRolesModel();
if (searchRolesViewModel.User_Id != string.Empty && searchRolesViewModel.NewUserHealthPlans != string.Empty && searchRolesViewModel.UserRole != string.Empty && searchRolesViewModel.NewUserPrimaryHealthPlan != string.Empty)
{
objUser.SaveUser(searchRolesViewModel, System.Web.HttpContext.Current.Session["UserID"].ToString());
ModelState.Clear();
ViewBag.Message = "User added successfully";
}
return UserDetails();
}
else
{
OR SHOULD IT GO HERE
}
catch (Exception)
{
throw ;
}
}
The simplest solution is to add a return value.
public bool SaveUser(SearchRolesViewModel objSearchRolesViewModel, string userID)
{
/* Snip */
bool duplicate = CheckforDuplicate(objUserAccount.NTUSERID, objUserAccount.HPID).Count == 0;
if (duplicate) return false;
_context.USERACCOUNTs.Add(objUserAccount);
_context.SaveChanges();
return true;
}
Then check the return value in your controller:
var ok = objUser.SaveUser(searchRolesViewModel, System.Web.HttpContext.Current.Session["UserID"].ToString());
if (ok)
{
ModelState.Clear();
ViewBag.Message = "User added successfully";
}
else
{
ViewBag.Message = "User not added.";
}
You can create a repository base with a few generic queries. E.g Add, GetAll, Find, Exists, Count and others. For more details https://medium.com/falafel-software/implement-step-by-step-generic-repository-pattern-in-c-3422b6da43fd
https://medium.com/#marekzyla95/generic-repository-pattern-implemented-in-net-core-with-ef-core-c7e088c9c58
for example, a possible implementation for a generic Exists method:
public bool Exists(Expression<Func<TEntity, bool>> func)
{
return _context.Set<TEntity>()
.Where(func)
.Any();
}
where TEntity will to be the model USERACCOUNT
[HttpPost]
public ActionResult Submit(SearchRolesViewModel searchRolesViewModel)
{
try
{
SearchRolesModel objUser = new SearchRolesModel();
if (searchRolesViewModel.User_Id != string.Empty && searchRolesViewModel.NewUserHealthPlans != string.Empty && searchRolesViewModel.UserRole != string.Empty && searchRolesViewModel.NewUserPrimaryHealthPlan != string.Empty)
{
//here we call the Exists method from an user repository to check for duplicate entries
var isDuplicated = _userRepository.Exists(user => user.NTUSERID == objUser.NTUSERID && user.HPID == objUser.HPID);
if(isDuplicated)
{
ViewBag.Message = "User exists already!";
Return Foo(); // return for the more appropriate page
}
else
{
objUser.SaveUser(searchRolesViewModel, System.Web.HttpContext.Current.Session["UserID"].ToString());
ModelState.Clear();
ViewBag.Message = "User added successfully";
return UserDetails();
}
}
}
catch (Exception)
{
throw ;
}
}
I migrated my project from .net core 2.0 to .net core 2.1 , i changed the libraries according to the documentation. My whole project is working fine but only my question module is giving
this error.
my controller queries works fine when i debug it, i think there is an issue in paginatedList but i have no idea how to resolve it.
Here is my controller function that is being executed.
public async Task<IActionResult> Index(string sortOrder, string currentFilter, string searchString, int? page)
{
ViewData["CurrentSort"] = sortOrder;
ViewData["NameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
ViewData["DateSortParm"] = sortOrder == "Date" ? "date_desc" : "Date";
ViewData["CurrentFilter"] = searchString;
//Check User Profile is complete or not
var user = await _userManager.GetCurrentUser(HttpContext);
var userPersonalRow = _context.UserPersonalDetail.Where(a => a.UserId == user.Id).SingleOrDefault();
if (userPersonalRow == null)
{
return RedirectToAction("CompleteProfile", "Home");
}
var questionList = (from question in _context.UserQuestion
join personalInfo in _context.UserPersonalDetail on question.UserId equals personalInfo.UserId
select new NewQuestionVM
{
UserQuestionId = question.UserQuestionId,
Description = question.Description,
Title = question.Title,
Tags = question.Tag.Select(t => new QuestionTagViewModel
{
SkillName = t.SkillTag.SkillName,
SkillTagId = t.SkillTagId,
}).ToList(),
Voting = _context.UserQAVoting.Sum(x => x.Value),
Visitors = _context.QuestionVisitor.Where(av => av.QuestionId == question.UserQuestionId).Count(),
PostedBy = personalInfo.FirstName + " " + personalInfo.LastName,
UserPic = personalInfo.ProfileImage,
PostTime = question.PostTime,
HasVerifiedAns = question.HasVerifiedAns,
}).Take(10);
if (!String.IsNullOrEmpty(searchString))
{
questionList = questionList.Where(s => s.Description.Contains(searchString)
|| s.Title.Contains(searchString));
}
#ViewBag.UName = HttpContext.Session.GetString("Name");
int pageSize = 10;
return View(new QuestionListVM { Questions = await PaginatedList<NewQuestionVM>.CreateAsync(questionList.AsQueryable(), page ?? 1, pageSize) });
}
and here is the PaginatedList class.
public class PaginatedList<T> : List<T>
{
public int PageIndex { get; private set; }
public int TotalPages { get; private set; }
public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
{
PageIndex = pageIndex;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);
this.AddRange(items);
}
public bool HasPreviousPage
{
get
{
return (PageIndex > 1);
}
}
public bool HasNextPage
{
get
{
return (PageIndex < TotalPages);
}
}
public static async Task<PaginatedList<T>> CreateAsync(IQueryable<T> source, int pageIndex, int pageSize)
{
var count = await source.CountAsync();
var items = await source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
return new PaginatedList<T>(items, count, pageIndex, pageSize);
}
internal static Task<string> CreateAsync<TEntity>(IQueryable<TEntity> queryable, int v, int pageSize) where TEntity : class
{
throw new NotImplementedException();
}
}}
but i dont understand how is this giving such error. i would love to get some help.
Why wont my changes persist to db after I click save.
Product Repository:
public class ProductRepository
{
NorthwindDataContext context = new NorthwindDataContext();
public IList<EditableProduct> All()
{
return (from product in context.Products
select new EditableProduct {
ProductID = product.ProductID,
ProductName = product.ProductName,
UnitPrice = product.UnitPrice.HasValue ? product.UnitPrice.Value : default(decimal),
UnitsInStock = product.UnitsInStock.HasValue ? product.UnitsInStock.Value : default(int),
Discontinued = product.Discontinued,
LastSupply = DateTime.Today
}).ToList();
}
public EditableProduct One(Func<EditableProduct, bool> predicate)
{
return All().Where(predicate).FirstOrDefault();
}
public void Update(EditableProduct product)
{
EditableProduct target = One(p => p.ProductID == product.ProductID);
if (target != null)
{
target.ProductName = product.ProductName;
target.UnitPrice = product.UnitPrice;
target.UnitsInStock = product.UnitsInStock;
target.Discontinued = product.Discontinued;
target.LastSupply = product.LastSupply;
}
}
public void Insert(EditableProduct product)
{
product.ProductID = All().OrderByDescending(p => p.ProductID).First().ProductID + 1;
All().Insert(0, product);
}
public void Delete(EditableProduct product)
{
EditableProduct target = One(p => p.ProductID == product.ProductID);
if (target != null)
{
All().Remove(target);
}
}
}
Controller:
public partial class GridController : Controller
{
ProductRepository productRepository = new ProductRepository();
public ActionResult EditingBatch()
{
return View();
}
[HttpPost]
[GridAction]
public ActionResult _SelectBatchEditing()
{
return View(new GridModel(productRepository.All()));
}
[HttpPost]
[GridAction]
public ActionResult _SaveBatchEditing([Bind(Prefix = "inserted")]IEnumerable<EditableProduct> insertProducts,
[Bind(Prefix = "updated")]IEnumerable<EditableProduct> updatedProducts,
[Bind(Prefix = "deleted")]IEnumerable<EditableProduct> deletedProducts)
{
if (insertProducts != null)
{
foreach (var product in insertProducts)
{
productRepository.Insert(product);
}
}
if (updatedProducts != null)
{
foreach (var product in updatedProducts)
{
var target = productRepository.One(p => p.ProductID == product.ProductID);
if (target != null)
{
target.ProductName = product.ProductName;
target.UnitPrice = product.UnitPrice;
target.UnitsInStock = product.UnitsInStock;
target.LastSupply = product.LastSupply;
target.Discontinued = product.Discontinued;
productRepository.Update(target);
}
}
}
if (deletedProducts != null)
{
foreach (var product in deletedProducts)
{
productRepository.Delete(product);
}
}
return View(new GridModel(productRepository.All()));
}
}
You seem to be using the code from our sample application which indeed does not update the database. It merely updates the data in memory so every single user browsing the demos sees only his changes.
To make it work you need to update the database. The actual implementation depends on the framework you are using for data access. For example for Linq To SQL you should use the SubmitChanges method. You can check this code library project which updates the underlying database.