Selecting a single value using linq if already duplicate values exist in mvc4 - linq

I have a table
public class Product
public int Id { get; set; }
public string Model_Name { get; set; }
public string Company_Name { get; set; }
public Nullable<int> Price { get; set; }
public string Photo { get; set; }
Now the table contains multipe items so I just want to retrive the name of the company and dispay it. However the column Company_Name contains duplicate values. How do I need to check if it contains duplicate names then also display the value only once.I want to check it within view. Here is the View.
#foreach (var item in Model)
{
<tr>
//Anything extra could be added here to check the duplicate values
<td>#Html.ActionLink(item.Company_Name, "Brand",
new { Company_Name = item.Company_Name })
</td>
</tr
}
Here is how the table looks like
Id Model_Name Company_Name price photo
1 S7862 Samsung 1500 something
2 Galaxy Samsung 1500 something
3 Apple Apple 2000 something
4 Desire HTC 1500 something
5 Desire X2 HTC 1500 something
6 Nokia Lumia Nokia 1500 something
Now in the above table a few records are missing and if I write
#foreach(var item in Model)
{
<tr>
<td>
#Html.ActionLink(item.Company_Name, "Brand", new {Company_Name=item.Company_Name})
</td>
</tr>
}
now here I get the result as
Brand
Samsung
Samsung
Apple
HTC
HTC
Nokia
I want it to be as
Brand
Samsung
Apple
HTC
Nokia
Any ideas will be appreciated. I want the Linq to come within the view.

Try using a Distinct() on that Property:
#foreach (var companyName in Model.Select(m => m.Company_Name).Distinct())
{
<tr>
//Anything extra could be added here to check the duplicate values
<td>#Html.ActionLink(companyName, "Brand",
new { Company_Name = companyName })
</td>
</tr
}

How about Grouping them on Company_Name:
#{
var grouped = Model.GroupBy(x=>x.Company_Name);
}
#foreach (var item in grouped)
{
<tr>
//Anything extra could be added here to check the duplicate values
<td>#Html.ActionLink(item.Key"Brand",
new { Company_Name = item.Key })
</td>
</tr
}

Related

Property Backer changes returning unknown error on Linq query

I have an application in ASPCore MVC.
My goal was to adjust the model to automatically capitalize email addresses.
It seemed this would be better than adjusting each controller.
After some research, I came upon this solution below, to modify the property backers.
public class PostFou
{
private string _name;
private string _email;
private string _address;
[Key]
public int FouId { get; set; }
[Display(Name = "Full Name")]
[RegularExpression(#"[a-zA-Z0-9""'\s-|\.\=\+\*\/\\]*$")]
[StringLength(45)]
public string FouName { get; set; }
[Display(Name = "Phone")]
[RegularExpression(#"[0-9]*$")]
[StringLength(20)]
[DataType(DataType.PhoneNumber)]
public string FouPhon { get; set; }
[Display(Name = "Email")]
[StringLength(45)]
public string FouEmai //{ get; set; }
{
get { return _email; }
set { _email = value.ToUpper(); }
}
}
The problem is that now all my linq queries are returning a nullReference exception one things that seem unrelated. for example, in my razor view, I have the following code
#foreach (var item in Model) { //error occurs here
<tr>
<td>
#Html.DisplayFor(modelItem => item.FouZero)
</td>
<td>
#Html.DisplayFor(modelItem => item.FouName)
</td>
<td>
#Html.DisplayFor(modelItem => item.FouPhon)
</td>
<td>
#Html.DisplayFor(modelItem => item.FouEmai)
</td>
In the controller, for this view, there is a Linq simple query:
public IActionResult Index(string searchString)
{
var titles = _context.PostFous.Where(m =>
m.FouZero.Contains(searchString) ||
m.FouName.Contains(searchString) ||
m.FouEmai.Contains(searchString)
);
//return View(await _context.PostFous.ToListAsync());
return View(titles);
}
in debugging, digging as deep as I know how, I found this message, consistently across the errors:
at lambda_method(Closure , QueryContext , DbDataReader , ResultContext , Int32[] , ResultCoordinator )
I'm not sure what that means.
The question is, what is going wrong?
Given that that is a broad question, more narrowly, in adjusting the property backing, should I have also adjusted something else?
Follow up, is there a different way to accomplish my goal of auto-capitalizing the email addresses in the model?
I would like to avoid making changes to the db, and keep this within the application.
My guess would be that the field could be null-able in the data. This means your setter needs to handle the fact that the DB row might have a #null eMail address, and your filter queries would as well:
[Display(Name = "Email")]
[StringLength(45)]
public string FouEmai //{ get; set; }
{
get { return _email; }
set
{
if (value == null)
_email = null;
else
_email = value.ToUpper();
}
}
Then when querying:
var titles = _context.PostFous.Where(m =>
m.FouZero.Contains(searchString) ||
m.FouName.Contains(searchString) ||
(m.FouEmai != null && m.FouEmai.Contains(searchString))
);
For performance considerations I recommend defaulting text matching searches to default to BeginsWith() where users would be expected to enter what values start with rather than Contains. For instance If they type "mark" then they are typically looking for names/emails that start with "mark" but if they don't find a match and want a more open search looking for "%" or "*" common wildcard characters. That way they can opt to search for "mark" for a Contains. This gives them the flexibility while helping ensure that the majority of such queries can perform better.
I tried again and reproduced the similar error:
In first case,the FouNum property of PostFou entity could not be null,
in db,the FouNum column could be null
And if the data in db was not sharing the same type with the property it would also get the similar error
You could check if any property type of int (Maybe FouNum in your case?) was in similar situation and share the more detailed information with us

asp.net mvc linq I want to fetch two columns from two join table

I have two tables join with PrId column, I have a view which show two columns from both tables, first column from first table and second column from second table. my actionresult is :
public ActionResult extrapoints()
{
ViewBag.dList = (from m in _session.customer
join p in _session.Products on m.PrId equals p.PrId
where m.UserId== 'john'
select new { FName = m.FName, price=p.price});
return View();
}
and in view i want to show both FName and price, I have following view :
#foreach (var item in ViewBag.dList)
{
<tr>
<td>#item.FName </td>
<td> #item.price</td>
</tr>
}
but is show error object' does not contain a definition for FName but when i use without Fname,price like
#foreach (var item in ViewBag.dList)
{
<tr>
<td>#item</td>
<td> #item</td>
</tr>
}
is shows :
{ FName = Shailendra, price= 1000 }
how to solve, please help
You Can Convert the Anonymous class to typed class, first add this class
class Test
{
public string FName { get; set; }
public decimal price { get; set; }
}
and make you linq statment as
ViewBag.dList = (from m in _session.customer
join p in _session.Products on m.PrId equals p.PrId
where m.UserId== 'john'
select new Test{ FName = m.FName, price=p.price});
and finally Cast the viewpage to type "Test"
#foreach (var item in (List<Test>)ViewBag.dList)
{
<tr>
<td>#item.Fname</td>
<td> #item.price</td>
</tr>
}

Incorporating custom view model data from multiple tables into a view

I can't understand why I can't find anything that clearly explains how to do this with MVC. Seems like a pretty routine issue:
I have three tables:
PackageName: PackageNameID,PackageName
Food: FoodID,Food
PackageContent: PackageContentID, PackageNameID, FoodID, Qty
The application is supposed to describe packages of food. For example, a package named "A" might contain 4 onions and 3 peppers. Another package, "B", might contain 2 rolls and 2 onions.
Currently I have a custom view model ("PackageNameModel") that collects the data:
public ViewResult Index() {
var viewModel =
from pn in db.PackageNames
from pc in db.PackageContents
.Where(p => p.PackageNameID == pn.PackageNameID).DefaultIfEmpty()
from f in db.Foods
.Where(f => f.FoodID == pc.FoodID).DefaultIfEmpty()
select new PackageFoodModel { PackageName = pn, PackageContent = pc, Food = f };
return View( viewModel );
}
This returns the data correctly, but what do I do with it so that the view is actually one that is useful for the application?
Using this in my view:
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.PackageName.PackageName1 ) ,
#Html.DisplayFor(modelItem => item.Food.Food1)=#Html.DisplayFor(modelItem => item.PackageContent.Qty)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.PackageName.PackageNameID }) |
#Html.ActionLink("Details", "Details", new { id = item.PackageName.PackageNameID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.PackageName.PackageNameID })
</td>
</tr>
}
I am able to display the following:
- A , Onions=4 Edit | Details | Delete
- A , Peppers=3 Edit | Details | Delete
- B , Rolls=2 Edit | Details | Delete
- B , Onions=2 Edit | Details | Delete
This is not very useful. What I'm trying to do is display something like this:
- A (Onions=4,Peppers=3) Edit | Details | Delete
- B (Rolls=2,Onions=2) Edit | Details | Delete
Eventually, the next page down after navigating to the "Edit" action would provide an editable name for the package as well as a table of all available foods and an adjacent quantity box so that the foods/quantities within each package may be updated.
Can anyone explain how this is done within the MVC framework?
All the tutorials I have seen on the web/in books deal with data that is much simpler. Can anyone point me to some sample code / tutorials that deal with something like this?
Thanks in advance!
You need to aggregrate your results.
Create a view model like this
public class PackageViewModel
{
public int ID { set;get;}
public string Name { set;get;}
public List<FoodItem> FoodItems { set;get;}
public PackageViewModel()
{
FoodItems=new List<FoodItem>();
}
}
public class FoodItem
{
public string FoodName { set;get;}
public int Quantity { set;get;}
}
and in your Get action, You need to do the aggregate the data from your data which is ccoming from your data access layer and fill to the ViewModel List
public ActionResult IndeX()
{
List<PackageViewModel> listVM=new List<PackageViewModel>();
//Get your data and do aggregation and fill in listVM
return View(listVm)l
}
and in our view,
#model List<PackageViewModel>
#foreach(var item in Model)
{
<tr>
<td>#item.Name</td>
<td>
foreach(var food in item.FoodItems)
{
#food.FoodName - #food.Quantity
}
</td>
<td>
#Html.ActionLink("Edit","Edit",new {#id=item.ID})
</td>
</tr>
}

MVC3 Ajax Checkboxes grid

I want to do a grid of checkboxes that contain products/categories. The products and categories could be dynamic (I mean, the count of products/categories can change). I'm able to create the grid and save the data when I check a box. My problem is to use ajax properly.
Here is my model :
public class ProductModel
{
public List<List<ProductItemGrid>> ProductItemGrid { get; set; }
public List<string> ProductNameList { get; set; }
public List<string> CategoryNameList { get; set; }
}
public class ProductItemGrid
{
public int ProductID { get; set; }
public int CategoryID { get; set; }
public bool ProductInCategory { get; set; }
}
Part of my view, (I use the list of list to populate it) :
#for (int i = 0; i < Model.ProductNameList.Count(); i++)
{
<tr class=#(i % 2 == 0 ? "even" : "odd")>
<td style="font-weight: bold;">
#Html.DisplayFor(x => x.ProductNameList[i])
</td>
#foreach (var result in Model.ProductItemGrid[i])
{
string ckBoxName = result.ProductID.ToString() + result.CategoryID.ToString();
<td id='<%=ckBoxName%>'>
#using (Ajax.BeginForm("UpdateProductItem", "Product", new AjaxOptions() { InsertionMode = InsertionMode.Replace, UpdateTargetId = ckBoxName }))
{
#Html.Hidden("p_CategoryID", result.CategoryID)
#Html.Hidden("p_ProductID", result.ProductID)
#Html.CheckBox("<%=ckBoxName%>", result.ProductInCategory, new { onclick = "test" })
}
</td>
}
</tr>
}
Right now the view contain some error, but Im sure you get the main idea. With the ajax form, Im able to update my database, but my main problem is to update the checkbox itself after doing the C# part. Also, I'm trying to name the < td> to be able to update the ckbox by giving him a name as ProductID_CategoryID (so it would be easier for me to know which one Im updating). Thks.
Have you checkout http://knockoutmvc.com it has a very nice integration with ASP.NET MVC3 and it looks like the type of library that can help you easily achieve what you need.

MVC3 Dropdown drillthrough hierarchy

I have a table for product category that has a hierarchical structure. Each Category_ID may have a number of children determined by their Parent_id. For example Air Fresheners (26) has children 26, 27 and 28 as they have a Parent_id of 25.
I would like to set up a page to drill through the categories with dropdowns. A user would select a level 2 category such as Air Fresheners they would then get a dropdown containing children of the previous selection.
What is the best way to do this? I am considering jQuery and JSON, but there might be a better way.
I have the following GetCategoryChildren method:
public string ThisName { get; set; }
public int ThisHLevel { get; set; }
public IEnumerable<SelectListItem> Children { get; set; }
public GetCategoryChildren(int category_ID)
{
var rep = new Product_CategoryRepository();
Children = rep.All.Where(x => x.Parent_id == category_ID).ToList()
.Select(x => new SelectListItem
{
Text = x.Name,
Value = x.Category_ID.ToString()
});
ThisName = rep.All.Where(x => x.Category_ID == category_ID)
.FirstOrDefault().Name;
ThisHLevel = rep.All.Where(x => x.Category_ID == category_ID)
.FirstOrDefault().HLevel;
}
Lend me your brains.
Take a look at Project Awesome
The AjaxDropdown does the trick.

Resources