MVC db.SaveChanges(); 2 Times Error: Object reference not set - asp.net-mvc

I'm getting the error of Object reference not set to an instance of an object. because of the Cart does not exist before it saves the db with the new changes.
I made some notes in my code explaining the problem. And I'm trying to get done
[Authorize]
public ActionResult AddToCart(int productid, string name, string description, decimal price)
{
var userID = User.Identity.GetUserId();
// List of Cart(s) that the current user own.
List<Cart> Carts = db.Carts.Where(x => x.UserId == userID).ToList();
// checks if the list above cotains no cart for the current logged in user.
if (Carts.Find(m => m.UserId == userID) == null) {
Cart cartmodel = new Cart { UserId = userID, CreatedDate = DateTime.Now};
db.Carts.Add(cartmodel);
db.SaveChanges();
}
// this action needs to be delayed til the upper action has been executed because: userCart.Id; has no value yet!
var userCart = Carts.Find(x => x.Id == x.Id);
var MyCartId = userCart.Id;
OrderItem model = new OrderItem { ProductId = productid, Name = name, Description = description, Price = price, CartId = MyCartId, Quantity = 1 };
db.OrderItems.Add(model);
db.SaveChanges();
return RedirectToAction("Cart");
}
Object reference not set
at
var MyCartId = userCart.Id;
The code works if the cart already exists. so after getting the error it does create the Cart for the user but it doesn't do the 2nd action which was to add product to the cart
i attempted to do this but now getting a new error:
[Authorize]
public ActionResult AddToCart(int productid, string name, string description, decimal price)
{
var userID = User.Identity.GetUserId();
// List of Cart(s) that the user owns should allways be 1 only ofc.
List<Cart> Carts = db.Carts.Where(x => x.UserId == userID).ToList();
// checks if the list above cotains no cart for the current logged in user.
if (Carts.Find(m => m.UserId == userID) == null) {
return RedirectToAction("AddNewCart");
}
// this action needs to be delayed til the upper action has been executed becasue: userCart.Id; has no value yet!
// make 2 action results and work with redirect
var userCart = Carts.Find(x => x.Id == x.Id);
var MyCartId = userCart.Id;
OrderItem model = new OrderItem { ProductId = productid, Name = name, Description = description, Price = price, CartId = MyCartId, Quantity = 1 };
db.OrderItems.Add(model);
db.SaveChanges();
return RedirectToAction("Cart");
}
public ActionResult AddNewCart()
{
var userID = User.Identity.GetUserId();
// List of Cart(s) that the user owns should allways be 1 only ofc.
List<Cart> Carts = db.Carts.Where(x => x.UserId == userID).ToList();
Cart cartmodel = new Cart { UserId = userID, CreatedDate = DateTime.Now };
db.Carts.Add(cartmodel);
db.SaveChanges();
return RedirectToAction("AddToCart");
}
the parameters dictionary contains a null entry for parameter 'productid' of non-nullable type 'System.Int32' for method
'System.Web.Mvc.ActionResult AddToCart(Int32, System.String,
System.String, System.Decimal)' in
'BlogMVC.Controllers.WebshopController'. An optional parameter must be
a reference type, a nullable type, or be declared as an optional
parameter.
Parameter name: parameters

I fixed it, but it isnt exacly a clean way of doing it any suggestion to make the code more clean and better would be greatly appciated
[Authorize]
public ActionResult AddToCart(int productid, string name, string description, decimal price)
{
var userID = User.Identity.GetUserId();
// List of Cart(s) that the user owns should allways be 1 only ofc.
List<Cart> Carts = db.Carts.Where(x => x.UserId == userID).ToList();
// checks if the list above cotains no cart for the current logged in user.
if (Carts.Find(m => m.UserId == userID) == null) {
return RedirectToAction("AddNewCart", new { name = name, productid = productid, description = description, price = price });
}
// this action needs to be delayed til the upper action has been executed becasue: userCart.Id; has no value yet!
// make 2 action results and work with redirect
var userCart = Carts.Find(x => x.Id == x.Id);
var MyCartId = userCart.Id;
OrderItem model = new OrderItem { ProductId = productid, Name = name, Description = description, Price = price, CartId = MyCartId, Quantity = 1 };
db.OrderItems.Add(model);
db.SaveChanges();
return RedirectToAction("Cart");
}
public ActionResult AddNewCart(int productid, string name, string description, decimal price)
{
var userID = User.Identity.GetUserId();
// List of Cart(s) that the user owns should allways be 1 only ofc.
List<Cart> Carts = db.Carts.Where(x => x.UserId == userID).ToList();
Cart cartmodel = new Cart { UserId = userID, CreatedDate = DateTime.Now };
db.Carts.Add(cartmodel);
db.SaveChanges();
return RedirectToAction("AddToCart", new { name = name, productid = productid, description = description, price = price });
}

Related

How To Filter The Data sent To The View According to the user login

This Is My Code
[Authorize(Roles = "Supplier")]
public ActionResult Orders()
{
if (!String.IsNullOrEmpty(TempData["error"] as string))
ViewBag.Error = TempData["error"] as string;
TempData.Clear();
if (User.IsInRole("Admin"))//when the user logs in as the admin
{
var orders = _uow.orderRepo.GetAll().ToList();
List<Models.Admin.OrderGridModel> model = null;
model = (from c in orders
select new Models.Admin.OrderGridModel()
{
OrderNumber = c.OrderNumber,
Date = c.Date,
Id = c.Id,
FullName = c.Person.FirstName + " " + c.Person.LastName,
PhoneNr = c.Person.Tel,
Email = c.Person.Email,
Price = BLL.PriceFormatter.FormatPrice(c.Price, c.Currency),
IsPaid = c.Zaplaceno,
Activities = (from a in c.OrderActivities
select new Models.Admin.OrderGridActivityModel()
{
Id = a.Id,
Time = a.Time,
Name = a.Activity.Name,
Date = a.Date,
Status = a.Status,
Supplier = a.Activity.Supplier != null ? a.Activity.Supplier.Name : "",
BookingRefNr = a.SupplierRefNr,
Hotel = c.Hotelname,
Price = BLL.PriceFormatter.FormatPrice(a.Price, a.Order.Currency),
PriceTypes = BLL.PriceFormatter.GetPriceTypesToString(a.OrderPrices),
voucher_ext = a.VoucherFileExtension,
voucher_name = a.VoucherFileName,
voucher_type = a.VoucherFileContentype,
}).ToList()
}).ToList();
return View(model);
}
if (User.IsInRole("Supplier"))// when the user logs in as the supplier
{
//code for filtering according to the supplier
}
return View();
}
I am getting the orders from the database but i want it to be filtered when the supplier logs in only those records can will be returned in which the supplier name is according to the login
In your repository, you have this
_uow.orderRepo.GetAll();
Create another one where you filter by supplier id
public IList<Order> GetSupplier(string id)
{
return context.Orders.Where(o => o.User.Id = id).ToList();
}
and then you can do this:
_uow.orderRepo.GetSupplier(User.Identity.GetUserId());
Where User.Identity.GetUserId() is the logged in user.

Count the No of Element of a column

public ActionResult NoOfLeaves()
{
string CurrentUserID = User.Identity.GetUserId();
var result = (from u in db.LeaveTypes
join s in db.LeaveDetails
on new { id = u.LeaveTypeID } equals new { id = s.LeaveTypeID}
join user in db.Users
on new { id = s.EmpID } equals new { id = user.Id }
where user.Id == CurrentUserID
select new noOfLeavesView
{
EmployeeID = user.Id,
EmployeeName = user.Name,
LeaveTypeName = u.LeaveTypeName,
Issued = u.NoOfLeaves
});
return View(result);
}
Leave type contains the type of Leaves Medical,etc.
Leave Detail contains the History of Leaves Applied by the User.
I want to know how many medical leaves were applied by a user.
public ActionResult NoOfLeaves()
{
var result = (from u in db.LeaveTypes
join s in db.LeaveDetails
on new { id = u.LeaveTypeID } equals new { id = s.LeaveTypeID }
select new noOfLeavesView
{
LeaveTypeName = LeaveTypeId.LeaveTypeName,
Issued = u.NoOfLeaves,
Availed = (db.LeaveDetails.Where(i=>i.LeaveTypeID.Equals(s.LeaveTypeID)).Count()),
}).Distinct();
return View(result);
}
from this way i get the required results...

Some errors in controller (asp.net mvc)

I am getting some errors in my controller.
At first, I got Suppliers List, then I got Id for all Suppliers, then I got all Users for every Supplier.
public ActionResult Grid(bool? active)
{
var suppliers = Context.Suppliers.AsNoTracking()
.WhereIf(active != null, e => e.Active == active)
.Select(e => new SupplierRow
{
Id = e.Id,
FullName = e.FullName,
Active = e.Active,
Visits = e.Visits,
})
.ToList();
List<int> supplierIds = new List<int>();
foreach (SupplierRow sr in suppliers)
{
supplierIds.Add(sr.Id);
}
var users = Context.Users.AsNoTracking()
.Where(e => supplierIds.Contains(e.SupplierId))
.Select(e => new UserRow
{
Id = e.Id,
FullName = e.FullName,
Email = e.Email,
Name = e.Name,
Status = e.Status,
Role = e.Role,
SupplierId = e.SupplierId
}).toList();
foreach (UserRow ur in users)
{
foreach (SupplierRow sr in supplier)
{
if (ur.SupplierId == sr.Id)
{
sr.Users.Add(ur);
}
}
}
return PartialView("_Grid", suppliers);
}
here
and here
What's wrong with my code? How to fix that?
The problem is that you are trying to add Guid object to a collection that only accepts int values. Your User.SupplierId is an object of type Guid? (or Nullable<Guid>), while Supplier.Id is Guid. Fix the collection by declaring it as:
List<Guid> supplierIds = new List<Guid>();
Then in you code use:
foreach(SupplierRow sr in suppliers)
{
supplierIds.Add(sr.Id);
}
Do the same thing for users except that you will have to use SupplierId.HasValue and SupplierId.Value to check whether it has a value and to read the value. This is because it is declared as nullable Guid.

Mixing local list operations with linq to entities database operations

I have 2 lists. A shopping cart list, which contains a objects with the properties; Quantity and ProductId. I then get all products from the repository (IQueryable) that has ProductId in the shopping cart list. This means that for every product, there is a shopping cart object with the Quantity related to it.
When doing the select, I want to assign this Quantity also, but the only way I know to do this is to query the cart again.
For egx.
model = (from p in productService.GetAllProducts()
where cart.Entries.Select(c => c.ProductId).Contains(p.ProductId)
select new CartViewItem
{
Price = p.Price,
ProductId = p.ProductId,
ProductName = p.ProductName,
Quantity = cart.Entries.FirstOrDefault(c => c.ProductId == p.ProductId).Quantity
}).ToList();
Model:
public class ShoppingCartEntry
{
public int ProductId { get; set; }
public int Quantity { get; set; }
}
cart.Entries is not coming from a repository. productService.GetAllProducts() returns an entityframework's IQueryable.
EDIT: My new code is:
model= (from p in productService.GetAllProducts()
from c in cart.Entries
where c.ProductId == p.ProductId
select new CartViewItem
{
Price = p.Price,
ProductId = p.ProductId,
ProductName = p.ProductName,
Quantity = c.Quantity
}).ToList();
This throws an error:
Unable to create a constant value of type 'SampleApp.WebUI.Models.ShoppingCartEntry'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
i think this should work...
var model = (from c in cart.Entires // The small local cart collection
let cpid = cart.Entires.Select(c2 => c2.ProjectId) //
from p in productService.GetAllProducts() // Query all Products used in cart
.Where(queryp => cpid.Contains(queryp.ProjectId)).ToList()
where p.ProductId == c.ProductId
select new CartViewItem {
p.Price,
p.ProductId,
p.Brand,
p.ProductName,
Discount = p.DiscountPercent * c.Quantity}).ToList();

Seat Reserving system

the Image shows how my tables are setup
Update
I have a working reserve seat and add to booking table now.
//
// POST: /Home/CreateBooking
public ActionResult CreateBooking(String id, DateTime date, DateTime time)
{
ViewData["username"] = User.Identity.Name;
ViewData["performanceDate"] = date;
ViewData["Venue"] = id;
BookingCreate model = new BookingCreate();
model.Seats = (from c in _db.Seat
where c.venue == id
select c);
return this.View(model);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateBooking(BookingCreate bookingCreate, IList<String> seatNumber)
{
Customer theCustomer
= (from c in _db.Customer
select c).First<Customer>(c => c.username == bookingCreate.customer);
//performance details for the performance selected by the user
Performance thePerformance
= (from p in _db.Performance
select p).FirstOrDefault<Performance>(p => p.performanceDate == bookingCreate.performanceDate || p.performanceTime == bookingCreate.performanceTime || p.venue == bookingCreate.venue);
//performance details for the performance selected by the user
Performance seatbooking
= (from p in _db.Performance
select p).FirstOrDefault<Performance>(p => p.performanceDate == bookingCreate.performanceDate || p.performanceTime == bookingCreate.performanceTime || p.venue == bookingCreate.venue);
var now = DateTime.UtcNow;
var bookingToCreate = new Booking();
bookingToCreate.bookingDate = now;
bookingToCreate.bookingTime = now;
bookingToCreate.bookingType = "Web";
bookingToCreate.collect = true;
bookingToCreate.Customer = theCustomer;
bookingToCreate.Performance = thePerformance;
_db.AddToBooking(bookingToCreate);
_db.SaveChanges();
var bookingnumber = (from p in _db.Booking
select p.bookingNo);
foreach (var displaySeat in seatNumber)
{
Seat theseat
= (from c in _db.Seat
select c).FirstOrDefault<Seat>(c => c.seatNumber == displaySeat);
var seatBooking = new SeatBooking();
seatBooking.Booking = bookingToCreate;
seatBooking.Seat = theseat;
_db.AddToSeatBooking(seatBooking);
_db.SaveChanges();
}
return RedirectToAction("ShowsIndex");
}
The code ensures that the correct venue's seats are displayed and that the logged in user and selected performance is chosen.
What i am stuck with is..
I am currently outputting the seats as checkboxes
with
BookingCreate model = new BookingCreate();
model.Seats = (from c in _db.Seat
where c.venue == id
select c);
But I would like for the checkboxes to show what seat number they relate to (at the moment they are just a blank checkbox)
And also how to stop showing seats that have been booked to stop duplication.
Thanks
I would do it this way (providing there are surrogate primary keys Customer.Id and Performance.Id)
public class BookingToCreateVM
{
public int BookingNo{get; set;}
//..etc - all necessary booking fields
public Guid UserId{get; set;}
public Guid PerformanceId{get; set;}
//data for something like dropdowns in view
public IList<Customer> Users{get; set;}
public IList<Performance> Performances{get; set;}
}
and the controller action
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateBooking(BookingToCreateVM bookingToCreateVM)
{
Customer theCustomer
= (from c in _db.Customer
select c).Single<Customer>(c=>c.Id == bookingToCreateVM.UserId);
Performance thePerformance
= (from p in _db.Performance
select p).Single<Performance>(p=> p.Id == bookingToCreateVM.PerformanceId);
var bookingToCreate = new Booking();
bookingToCreate.BookingNo= bookingToCreateVM.BookingNo;
//..etc - initialize all necessary fields
bookingToCreate.Customer = theCustomer;
bookingToCreate.Performance = thePerformance;
_db.AddToBooking(bookingToCreate);
_db.SaveChanges();
return RedirectToAction("ListBookings");
}

Resources