Programatic referencing of literals and object properties - asp.net

I have advice that this might work for programmatically filling a set of literals from a set of object properties:-
For i As Integer = 1 To noOfTexts
Dim ctl As Literal = DirectCast(FindControl("help" & i), Literal)
If ctl IsNot Nothing Then
ctl.Text = pageData.help(i).trim()
ctl.Visible = True
End If
Next
However, the line: ctl.Text = pageData.help(i).trim() fails because it's not understood that pageData.help(i) should translate to pageData.help1, pageData.help2, etc.
Is there some syntax that would achieve this in VS2010 Asp.net VB?

You can reference properties dynamically using reflection...
Dim PageDataType As Type = GetType(pageData)
Dim PropertyName As String = "help" & i
Dim Property As PropertyInfo = PageDataType.GetProperty(PropertyName)
Dim PropertyValue As String
If Property IsNot Nothing
PropertyValue = Property.GetValue(pageData, Nothing)
End If
Note: Reflection in .NET is slower than direct access, but not enough to make its use impractical

Related

Expression of type 'System.Boolean' cannot be used for return type 'System.Object'

I want to create an Expression(Of Func(Of TModel, TResult)) from the TModel and the string property name.
I've tried it like this:
Error from Expression.Lambda(): Expression of type 'System.Boolean' cannot be used for return type 'System.Object'
<Extension>
Public Function ModelEditor(Of TModel)(html As HtmlHelper(Of TModel)) As MvcHtmlString
Dim meta = html.ViewData.ModelMetadata
Dim htmlString As New StringBuilder()
Dim paramExp = Expression.Parameter(GetType(TModel), "model")
For Each editor In meta.Properties
Dim memberExp = Expression.Property(paramExp, editor.PropertyName)
Dim exp = Expression.Lambda(Of Func(Of TModel, Object))(memberExp, paramExp)
htmlString.Append(html.EditorFor(exp))
Next
Return MvcHtmlString.Create(htmlString.ToString())
End Function
And then I've tried to convert the value:
Error from EditorFor(): Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.
Dim memberExp = Expression.Property(paramExp, editor.PropertyName)
' Convert to a Object
Dim convertExp = Expression.Convert(memberExp, GetType(Object))
Dim exp = Expression.Lambda(Of Func(Of TModel, Object))(convertExp, paramExp)
htmlString.Append(html.EditorFor(exp))
When you look at the source code you can see that the ExpressionType can only be: ExpressionType.ArrayIndex, ExpressionType.Call, ExpressionType.MemberAccess or ExpressionType.Parameter
How can I do this without getting errors? Or am I taking the wrong approach?
I found a solution myself by using a lot of ugly reflection. There's probably still a way better way to do it though.
Option Strict Off
<Extension>
Public Function ModelEditor(Of TModel)(html As HtmlHelper(Of TModel)) As MvcHtmlString
Dim meta = html.ViewData.ModelMetadata
Dim htmlString As New StringBuilder()
Dim paramExp = Expression.Parameter(GetType(TModel), "model")
For Each prop In meta.Properties
' Equivalent to: Function(model) model.{PropertyName}
Dim memberExp = Expression.Property(paramExp, prop.PropertyName)
' Ugly unsafe reflection
Try
' Use reflection to get this: Func(Of TModel, TValue)
Dim delegateType = GetType(Func(Of ,)).MakeGenericType(GetType(TModel), prop.ModelType)
' Use reflection to call this: Expression.Lambda(Of Func(Of TModel, Object))(memberExp, paramExp)
' Result: Expression(Of Func( TModel, TValue))
Dim exp = GetType(Expression).
GetMethods(BindingFlags.Public Or BindingFlags.Static).
FirstOrDefault(Function(x) x.Name = "Lambda" AndAlso x.IsGenericMethod AndAlso x.GetParameters.Length = 2 AndAlso x.GetParameters.Select(Function(y) y.ParameterType).Contains(GetType(ParameterExpression()))).
MakeGenericMethod(delegateType).
Invoke(Nothing, New Object() {memberExp, New ParameterExpression() {paramExp}})
htmlString.Append(EditorExtensions.EditorFor(html, exp))
Catch
Continue For
End Try
Next
Return MvcHtmlString.Create(htmlString.ToString())
End Function

How to find the value of a dropdownlist using FindControl?

I am working on a website with VB.NET and ASP.NET. I currently have recurring DropDownLists for the user to provide input.
The design is recurring. These DropDownLists get their values from a database table, Everything with the Web interface is working except for writing these recurring values to the database - that is just to give you some background.
I have set the ID's of each DropDownList like so:
FrequencyList.ID = String.Concat("FreqList", DBReader(0))
That is in a loop while reading the DatabaseReader.
This is what I'm having issues with (please note I simplified the code down to make it easier to read:
Dim i As Integer
DBCommand = New SqlCommand()
DBCommand.Connection = DBConnection
DBCommand.CommandType = Data.CommandType.StoredProcedure
DBCommand.CommandText = "StoredProcedureName"
DBConnection.Open()
For i = 1 To AspectTableLength
Dim ParamFrequencyID As SqlParameter = DBCommand.Parameters.Add("#nFrequencyID", SqlDbType.Int)
ParamFrequencyID.Value = FindControl("FreqList" & Convert.ToString(i))
ParamFrequencyID.Direction = ParameterDirection.Input
Next
The FindControl("FreqList" & Convert.ToString(i)) variable is incorrect because it does not access the value - and adding .SelectedItem.Value does not work.
I got help from a developer.
Dim MyControls As ControlCollection = Panel.Controls
Dim Number As Integer 'this is the same as "DBReader(0)"
For Each MyControl As Control In MyControls
If MyControl.ID Is Nothing Then
Else
If MyControl.ID.StartsWith("Span") Then
Number = Replace(MyControl.ID, "Span", "")
Dim Freq As DropDownList = PanelMain.FindControl(“FreqList” & Number)
Dim ParamFrequencyID As SqlParameter = DBCommand.Parameters.Add("#nFrequencyID", SqlDbType.Int)
ParamFrequencyID.Value = Freq.SelectedIndex
ParamFrequencyID.Direction = ParameterDirection.Input
DBCommand.ExecuteNonQuery()
DBCommand.Parameters.Clear()
End If
End If
Next
DBConnection.Close()

Can't get value in dim with CInt vb.net

I'm fairly new to vb.net and can't find why this is not working, dim test is just empty after this line happened. Any possible problems?
Dim test As Integer = CInt(System.Configuration.ConfigurationManager.AppSettings("TermstextFieldTypeId"))
Try this code;
If your TermstextFieldTypeId setting IsNullOrEmpty then get default(0) value else getter setting value.
Dim val = System.Configuration.ConfigurationManager.AppSettings("TermstextFieldTypeId")
Dim test As Integer = CInt(IIf(String.IsNullOrEmpty(val), 0, val))

ASP NET MVC VB if searchstring is empty do or else LINQ

Function Index(SearchString As String, page As Integer?) As ActionResult
If page Is Nothing Then
page = 1
Else
page = page
End If
Dim List = (From m In db.maintenances Where (m.description OrElse m.description.Contains(SearchString)))
Dim pagesize = 25
Dim pageNumber As Integer = (If(page, 1))
Return View(List.OrderBy(Function(o) o.id).ToPagedList(pageNumber, pagesize))
End Function
Now i have this piece of code in my controller
what i would like to do if searchstring is empty return all results but if its not empty filter those that contain the searchstring how can i make this so i dont have to write multple queries to filter out the data?
You could add the Where clause only if it is required. Instead of
Dim List = (From m In db.maintenances Where (m.description OrElse m.description.Contains(SearchString)))
you change to Linq extension method syntax and add the Where clause only if it is required:
Dim List = db.maintenances.AsQueryable()
If Not String.IsNullOrWhitespace(SearchString) Then
List = List.Where(Function(x) m.description IsNot Nothing AndAlso m.description.Contains(SearchString))
End If
The query will only be executed at the end of your method when you call ToPagedList, so all the records are only retrieved if there is no search clause.
If you need to add another condition, just add another Where clause, for example:
Dim List = db.maintenances.AsQueryable()
If Not String.IsNullOrWhitespace(SearchString) Then
List = List.Where(Function(x) m.description IsNot Nothing AndAlso m.description.Contains(SearchString))
End If
If selectedBranchId IsNot Nothing Then
List = List.Where(Function(x) m.branch_id = selectedBranchId)
End If

VB.net Null reference on database connection

I know I'm being an idiot here and I just can't work it out. But i'm trying to take some data back from a vb.net database. It's falling over with a Object reference not set to an instance of an object error. And before the code runs it's saying the variable is being used before it's set, but I can't see how. Code:
Private taNotifications As dsDataTableAdapters.NotificationsTableAdapter = New dsDataTableAdapters.NotificationsTableAdapter
Dim notification As dsData.NotificationsDataTable = taNotifications.GetDataByClientID(userrow.UserID)
If notification.Rows.Count > 0 Then
Dim notificationrow As dsData.NotificationsRow
Dim forwardURL As String = notificationrow.ForwardLocation
End If
It falls over on the Dim forwardURL As String = notificationrow.ForwardLocation
The problem is that you have never instantiated the notificationRow inside the if statement. You've declared it, but it doesn't belong to anything. You need to make an assignment or loop through your rows before doing anything with this object:
Dim notificationrow As dsData.NotificationsRow ' this is not instantiated
Dim forwardURL As String = notificationrow.ForwardLocation
What you really want in this case is:
For Each notificationRow As dsData.NotificationRow In notification
Dim forwardURL As String = notificationRow.ForwardLocation
' Do Something
Next
If you only HAVE one row and you know you only have 1 or 0 rows then you could use your if statement by doing:
If notification.Rows.Count > 0 Then
Dim notificationrow As dsData.NotificationsRow = _
CType(notification.Rows(0), dsData.NotificationsRow)
Dim forwardURL As String = notificationrow.ForwardLocation
End If
Edit: In the code above, I originally just had notification.Rows(0). This will produce a DataRow object, but it will not be strongly typed. You need to perform the CType that I added in order to use the custom property ForwardLocation.
You never set notificationrow to anything. Did you mean to set it like this?
Dim notificationrow As dsData.NotificationsRow = CType(notification.Rows(0), dsData.NotificationsRow)

Resources