Some errors in controller (asp.net mvc) - 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.

Related

Orderby clause not working with drop down list in mvc

I am populating a drop down list using Linq and the orderby clause doesn't seem to work.
public List<Hello> getManagers()
{
var que = (from man in db.Table1
where man.Role == "Manager"
orderby man.Name
select new Hello
{
Managers = man.Name
}).Distinct().ToList();
return que;
}
Controller Class:
public ActionResult Index()
{
rp = new RequestProcess();
ViewBag.ID = fillSelectedList("", "ID", rp);
ViewBag.Managers = fillSelectedList("", "Managers", rp);
return View(""); //View 1
}
public static List<SelectListItem> fillSelectedList(string selValue, string type, RequestProcess rp )
{
List<SelectListItem> list = new List<SelectListItem>();
SelectListItem obj = new SelectListItem();
if (type == "Managers") {
var tempList= rp.getManagers();
tempList.ForEach(x =>
{
obj = new SelectListItem();
obj.Text = x.Managers;
obj.Value = x.Managers;
obj.Selected = x.Managers == selValue ? true : false;
list.Add(obj);
});
}
return list;
}
I am still receiving an un-ordered list. Any fixes?
The result is not ordered, because method Distinct does not return ordered results. What you need to do instead is to first call Disctinct, and only then OrderBy:
var que = (from man in db.Table1
where man.Role == "Manager"
select new Hello
{
Managers = man.Name
}).Distinct() // <- First distinct ...
.OrderBy(x => x.Managers) // <- ... then order by
.ToList();
As mentioned in the answer above, you need to sort the result after Distinct().
Also note that you are mixing Lambda expression and LINQ to Entities Queries... you may want to consider choosing one of them for consistency (though there is no syntax error if you mix them). This is the same query using lambda expression:
var que = _context.Table1
.Where(m => m.Role == "Manager")
.Select(h => new Hello { Managers = h.Name })
.Distinct()
.OrderBy(o => o.Managers)
.ToList();

how to return selected columns based on user choice

I'm trying to limit which fields are returned by an API based on a parameter called fields which I accept multiple strings doing this
private readonly string[] fields;
public string[] SelectiveSerializer(string fields)
{
string[] _fields;
var fieldColl = fields.Split(',');
_fields = fieldColl
.Select(f => f.ToLower().Trim())
.ToArray();
return _fields;
}
I want to be able to choose what I return based on whatever the user gives me in _fields. Normal way to do it:
var linq = (from entity in db.users
where entity.ID== id
&& entity.ON== false
select( new {
ID = entity.ID,
FirstName = entity.FirstName,
LastName =entity.LastName,
FotherName = entity.FotherName
}).ToList();
but here I have to specify the fields in Select (ID, FirstName ..etc), which I want it to be dynamic based on what fields[] has. Is there a way to do this?
sort of this (which is wrong):
var linq = (from entity in db.users
where entity.ID== id
&& entity.ON== false
select( new {
foreach (string s in _fields)
{
entity.s;
}
}).ToList();
Use a ternary expression for each assignment
var user = entityContext.Users.Where(u => u.ID == id)
.Select(u => new {
ID = _fields.Contains['id'] ? u.ID : 0,
FirstName = _fields.Contains['firstname'] ? u.FirstName : null,
LastName = _fields.Contains['lastname'] ? u.LastName : null,
otherName = _fields.Contains['othername'] ? u.otherName : null
})
.ToList();
I also would put the field names in a HashSet<string> for a better performance.
var _fields = new HashSet<string>(fields.Split(',').Select(f => f.ToLower().Trim()));
This solution keeps all the properties but sets the unwanted ones to null. If you want to dynamically add properties, see this other SO question: How to dynamically create a class in C#?. But note that this only useful in scenarios where objects of this type are processed dynamically as well.
I was finally able to do this with minimal work.
assuming the filter is a string list. string array.
so to avoid reflection and all that jazz, I iterate over each record and see if the variable is in the filter list, then create a dic entry with (var,val) assuming that no duplicate var in the same record, which can be catch if you want but I don't have this issue.
Then at the end add that dic to a list.
the method accept anonymous type list and a filter list.
public static List<Dictionary<string, object>> filteredList(IEnumerable source, string[] filter)
{
var filteredList = new List<Dictionary<string, object>>();
foreach (var single in source)
{
var type = single.GetType();
var props = type.GetProperties();
var singleRecord = new Dictionary<string, object>();
foreach (var v in props)
{
if (filter.Contains(v.Name))
{
var tempValue = type.GetProperty(v.Name).GetValue(single, null);
singleRecord.Add(v.Name, tempValue);
}
}
filteredList.Add(singleRecord);
}
return filteredList;
}

MVC db.SaveChanges(); 2 Times Error: Object reference not set

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 });
}

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...

MVC C# Select Where

I am trying to add filter by ID for the following:
public ActionResult Index()
{
var model = from o in new MainDBContext().OffLinePayments
select new EditOffLinePayment
{
ID = o.ID,
Amount = o.Amount
};
return View(model);
}
What I would like to do is the following:
public ActionResult Index(long? id)
{
if (id != null)
{
var model = from o in new MainDBContext().OffLinePayments
**Where Assigned_ID == id**
select new EditOffLinePayment
{
ID = o.ID,
Amount = o.Amount
};
return View(model);
}
else
{
var model = from o in new MainDBContext().OffLinePayments
select new EditOffLinePayment
{
ID = o.ID,
Amount = o.Amount
};
return View(model);
}
}
try
var model = from o in new MainDBContext().OffLinePayments
where o.Assigned_ID == id
select new EditOffLinePayment
{
ID = o.ID,
Amount = o.Amount
};
If I understand correctly, your problem is that the compiler doesn't let you write where o.Assigned_ID == id in the query.
That's because id is a Nullable<long>, which is not implicitly convertible to a long (which OffLinePayment.Assigned_ID presumably is).
You need to write where o.Assigned_ID == id.Value instead. Take a look at what the Value property does so that you don't get any surprises.
A cleaner, shorter and much more readable syntax would look like this:
public ActionResult Index(long? id){
using (var ctx = new MainDBContext())
{
var entities = ctx.OfflinePayments.Where(e => !e.HasValue || e.Assigned_ID == id.Value);
var model = entities.Select(e => new EditOfflinePayment { ID = e.ID, Amount = e.Amount }).ToList();
return View(model);
}
}

Resources