adding a search in a MVC - asp.net-mvc

Im trying to add a filter to a MVC with a multiple LINQ query that i got from This Question and i want to make a filter like "add Genre" on this which is a dropdownlist Tutorial if i take off the parameter from the function of brand (i do get my dropdownlist working) And the thing is that im not sure, because in the table i need to filter brand is a number (so i think i need to pass that parameter as integer), however i get an error
"The parameters dictionary contains a null entry for parameter 'brand' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Index(System.String, System.String, System.String, System.Nullable`1[System.Int32], Int32)' in 'BDInventario.Controllers.ArticulosController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters"
Below is my code
Function Index(ByVal sortOrder As String, currentFilter As String, ByVal searchString As String, page As Integer?,brand as Integer) As ActionResult
ViewBag.CurrentSort = sortOrder
ViewBag.NameSortParm = If(String.IsNullOrEmpty(sortOrder), "name_desc", String.Empty)
If Not searchString Is Nothing Then
page = 1
Else
searchString = currentFilter
End If
ViewBag.CurrentFilter = searchString
Dim brandList As New List(Of String)
Dim brandQuery = From a In db.Articulos
Join m In db.Articulo_brand On a.brand_id Equals m.brand_id
Order By m.desc_brand
Select m.desc_brand
brandList.AddRange(brandQuery.Distinct)
ViewBag.brand = New SelectList(brandList)
Dim articulos = From m In db.Articulos Select m
Select Case sortOrder
Case "name_desc"
articulos = articulos.OrderByDescending(Function(s) s.descripcion)
Case Else
articulos = articulos.OrderBy(Function(s) s.articulo_id)
End Select
If Not String.IsNullOrEmpty(searchString) Then
articulos = articulos.Where(Function(Inventario_ADO) Inventario_ADO.descripcion.Contains(searchString))
End If
I think my error is in this section
If Not String.IsNullOrEmpty(brand) Then
articulos = articulos.Where(Function(m) m.brand_id.Equals(brand))
End If
Dim pageSize As Integer = 50
Dim pageNumber As Integer = If(page, 1)
Return View(articulos.ToPagedList(pageNumber, pageSize))
End Function
Any help or tips would be really apreciated

The error is because your brand parameter must be a nullable integer, like the page parameter is.
Also, I would do the ordering after the filtering. And you use ViewBag a lot, why not a ViewModel?

Related

How to send a value from a select statement in MVC controller to Viewbag

I want to return just a value to ViewBag with the LINQ query below
var myCompanyName = (from c in db.Companies
where c.CompanyId == CompanyID
select c.CompanyName).ToString();
ViewBag.myCompanyName = myCompanyName;
In my MVC controller but I get the following output in my View.
SELECT [Extent1].[CompanyName] AS [CompanyName] FROM [dbo].[Companies] AS [Extent1] WHERE [Extent1].[CompanyId] = #p__linq__0 Company Name from Controller Action
The result ViewBag expected from view bag should be something like: CompanyName XYZ. Please how do I make this right?
Your not materializing your query, and I suspect you want to return a single value (not IEnumerable<string>) so you need to replace .ToString() with .FirstOrDefault()
var myCompanyName = (from c in db.Companies
where c.CompanyId == CompanyID
select c.CompanyName).FirstOrDefault();
ViewBag.myCompanyName = myCompanyName;
or if you did want a collection of string, then it would be .ToList()

Error when trying to use context.entity.include()

I am trying to filter records and return them to put them in a list. My variable "companyId" equals 1. When I run, I get an error. What can I do to fix? Thank you.
The error points to this line:
Dim blogs = db.Blogs.Include(Function(b) b.CompanyId = companyId)
The error:
The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties.
Parameter name: path
The whole code:
'
' GET: /ViewBlogs/
Function ViewBlogs() As ViewResult
'Dim blogs = db.Blogs.Include(Function(b) b.Company)
Dim db1 As UserProfileDbContext = New UserProfileDbContext
Dim user = Membership.GetUser()
Dim key As Guid = user.ProviderUserKey
Dim userProfile = db1.UserProfiles.Where(Function(p) p.UserId = key).Single
Dim companyId = userProfile.CompanyId
If (userProfile.IsCompanyOwner) Then
Dim blogs = db.Blogs.Include(Function(b) b.CompanyId = companyId)
Return View(blogs.ToList())
Else
Return View("Home")
End If
End Function
Yes, the solution for me was as simple as this:
Dim blogs = db.Blogs.Where(Function(b) b.CompanyId = companyId)

LINQ concatenate 2 fields to search on

I'm trying to concatenate two fields in LINQ so that I can then filter with a keyword. I found a question posted here that I thought was my answer, but I'm getting 0 records back for some reason. This is supposed to return a JSON result for an autocomplete textbox (it works when I don't concatenate fields).
Here's my code:
Function CostCodeList(ByVal term As String) As ActionResult
Dim results = From c In db.ORG_CHART_V
Let Fullname = CStr(c.COSTCTR_CD & " - " & c.BREADCRUMB)
Where Fullname.ToUpper.Contains(CStr(term).ToUpper)
Order By Fullname
Select New With {.label = Fullname, .id = c.ORG_NODE_ID}
Return Json(results.ToArray, JsonRequestBehavior.AllowGet)
End Function
I'm also getting this error on the Return:
Public member 'ToArray' on type 'DbQuery(Of VB$AnonymousType_3(Of
String,Integer))' not found.
Before trying to concatenate the two fields I was searching on them separately, successfully. But when I concatenate them, it seems like everything I try either gets me an error and/or zero records.
Here is a different function that does work:
Function RoleList(ByVal term As String) As ActionResult
Dim list As New ArrayList
Dim results As IQueryable(Of JOB_ROLE)
If IsNumeric(term) Then
results = From c In db.JOB_ROLE
Where CStr(c.JBROLE_NO).StartsWith(term)
Else
results = From c In db.JOB_ROLE
Where c.JOB_ROLE_NAME.ToUpper.Contains(CStr(term).ToUpper)
End If
results = results.OrderBy(Function(e) e.JOB_ROLE_NAME)
For Each item In results
list.Add(New With {.label = item.JOB_ROLE_NAME, .id = item.JOB_ROLE_ID})
Next
Return Json(list.ToArray, JsonRequestBehavior.AllowGet)
End Function
Here is the new function that works as intended:
Function CostCodeList(ByVal term As String) As ActionResult
Dim list As New ArrayList
Dim results = db.ORG_CHART_V.Where(Function(e) (CStr(e.COSTCTR_CD) + " - " + e.BREADCRUMB).Contains(CStr(term).ToUpper)).OrderBy(Function(o) o.COSTCTR_CD)
For Each item In results
list.Add(New With {.label = item.COSTCTR_CD & " - " & item.BREADCRUMB, .id = item.ORG_NODE_ID})
Next
Return Json(list.ToArray, JsonRequestBehavior.AllowGet)
End Function

How does Select statement works in a Dynamic Linq Query?

1) I've a Product table with 4 columns: ProductID, Name, Category, and Price. Here's the regular linq to query this table.
public ActionResult Index()
{
private ProductDataContext db = new ProductDataContext();
var products = from p in db.Products
where p.Category == "Soccer"
select new ProductInfo { Name = p.Name, Price = p.Price}
return View(products);
}
Where ProductInfo is just a class that contains 2 properties (Name and Price). The Index page Inherits ViewPage - IEnumerable - ProductInfo. Everything works fine.
2) To dynamicaly execute the above query, I do this:
Public ActionResult Index()
{
var products =
db.Products
.Where("Category = \"Soccer\"")
.Select(/* WHAT SOULD I WRITE HERE TO SELECT NAME & PRICE?*/)
return View(products);
}
I'm using both 'System.Lind.Dynamic' namespace and the DynamicLibrary.cs (downloaded from ScottGu blog).
Here are my questions:
What expression do I use to select only Name and Price?
(Most importantly) How do I retrieve the data in my view? (i.e. What type the ViewPage inherits? ProductInfo?)
===================
EDIT
When I write .Select("new(Name, Price)"), I'm able to pass an object to the ViewData's Model property. Unfortunately, in order to use the Viewdata object, I'm asked to cast the Viewdata to a type. But, I do not know how to determine the type to do the casting.
====================
EDIT
Instead of the ViewData's Model property, I'm using simply the ViewData["products"]. To retrieve the content, I just place a IEnumerable cast before the ViewData, like this:
<% foreach(var item in (IEnumerable)ViewData["products"]){%>
<p><% = Html.Encode(item)%><p>
<%}%>
There are 2 situations:
1) If I select only one column (for instance, Name), everything work fine.
2) If I select more than 1 more columns (Name, Price), I get something like this
{Name=Soccer, Price=19.50}
{Name=Shin Pads, Price=11.59}
Why I just don't get something like
Soccer, 19.50
Shin Pads, 11.59
=================================
EDIT April 02 - 05h47 AM
I've define the GetPropertyValue Method (as your response suggets) as static in a static Class that I called 'HelperClass'. Now, this is the way I try to access the value of Name from my object.
<% = Html.Encode(HelperClass.GetPropertyValue(ViewData["product"], "Name")) %>
I get the following Exception:"Object reference not set to an instance of an object". And, the following line from the inside GetPropertyValue() his highlight.
Line 22: return propInfo.GetValue(obj, null);
Do I need to use new keyword? (where?)
Thanks for helping
Private Sub filter()
Dim coll = db.Products.Where(Function(x) x.Category.Equals("Soccer")) _
.Select(Function(x) GetObject(x.Name, x.Price))
End Sub
Private Function GetObject(ByVal name As String, ByVal price As String) As Object
Return new ProductInfo(name, price)
End Function
1) To generate a new projection type at runtime you can:
.Select("new(Name, Price)")
2) To read values from the object, you need to use reflection:
string name = GetPropertyValue(someObject, "Name");
...
public static object GetPropertyValue(object obj, string propName)
{
System.Reflection.PropertyInfo propInfo = obj.GetType().GetProperty(propName);
return propInfo.GetValue(obj, null);
}

Combining extension methods

I'm trying to write 2 extension methods to handle Enum types. One to use the description attribute to give some better explanation to the enum options and a second method to list the enum options and their description to use in a selectlist or some kind of collection.
You can read my code up to now here:
<Extension()> _
Public Function ToDescriptionString(ByVal en As System.Enum) As String
Dim type As Type = en.GetType
Dim entries() As String = en.ToString().Split(","c)
Dim description(entries.Length) As String
For i = 0 To entries.Length - 1
Dim fieldInfo = type.GetField(entries(i).Trim())
Dim attributes() = DirectCast(fieldInfo.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())
description(i) = If(attributes.Length > 0, attributes(0).Description, entries(i).Trim())
Next
Return String.Join(", ", description)
End Function
<Extension()> _
Public Function ToListFirstTry(ByVal en As System.Enum) As IEnumerable
Dim type As Type = en.GetType
Dim items = From item In System.Enum.GetValues(type) _
Select New With {.Value = item, .Text = item.ToDescriptionString}
Return items
End Function
<Extension()> _
Public Function ToListSecondTry(ByVal en As System.Enum) As IEnumerable
Dim list As New Dictionary(Of Integer, String)
Dim enumValues As Array = System.Enum.GetValues(en.GetType)
For Each value In enumValues
list.Add(value, value.ToDescriptionString)
Next
Return list
End Function
So my problem is both extension methods don't work that well together. The methods that converts the enum options to an ienumerable can't use the extension method to get the description.
I found all kind of examples to do one of both but never in combination with each other. What am I doing wrong? I still new to these new .NET 3.5 stuff.
The problem is that Enum.GetValues just returns a weakly typed Array.
Try this:
Public Function ToListFirstTry(ByVal en As System.Enum) As IEnumerable
Dim type As Type = en.GetType
Dim items = From item In System.Enum.GetValues(type).Cast(Of Enum)() _
Select New With {.Value = item, .Text = item.ToDescriptionString}
Return items
End Function
(It looks like explicitly typed range variables in VB queries don't mean the same thing as in C#.)

Resources