Checking if two lists of objects are equal - asp.net

I need to compare the values of two lists of objects in VB.NET in a web application. I can't seem to find any working examples of how to do this.
I have tried the example here: https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.sequenceequal?view=netframework-4.0
Where they implement a custom interface for doing so. But even using the exact code gives me errors.
Here is the code I'm currently trying. It's basically the same thing as Microsoft's example but using my own class:
Public Class ForumWithName
Inherits IEquatable(Of ForumWithName)
Private mForumID As Integer
Public Property ForumID() As Integer
Get
Return mForumID
End Get
Set(value As Integer)
mForumID = value
End Set
End Property
Private mForumName As String
Public Property ForumName As String
Get
Return mForumName
End Get
Set(value As String)
mForumName = value
End Set
End Property
Private mSubscribed As Boolean
Public Property Subscribed As Boolean
Get
Return mSubscribed
End Get
Set(value As Boolean)
mSubscribed = value
End Set
End Property
Public Function Compare(ByVal other As ForumWithName) As Boolean
If other Is Nothing Then Return False
Return Me.ForumID = other.ForumID AndAlso Me.Subscribed = other.Subscribed
End Function
Public Overrides Function Equals(ByVal obj As Object) As Boolean
Return Compare(TryCast(obj, ForumWithName))
End Function
Public Overrides Function GetHashCode() As Integer
Return (ForumID, Subscribed).GetHashCode()
End Function
End Class
This code fails to compile because of a few errors:
"Classes can inherit only from other classes"
"Predefined type 'ValueTuple(Of,) is not defined or imported."
"Visual Basic 10.0 does not support tuples"
"'GetHashCode' is not a member of '(ForumID as Integer, Subscribed as Boolean)'"
Once I get this code to work, my plan is to compare two lists of the "ForumWithName" class above.
For example(assume SubscribedsForum1 and SubscribedForums2 are both Lists(Of ForumWithName)):
If SubscribedForums1.SequenceEqual(SubscribedForums2) Then
Return True
Else
Return False
End If

IEquatable is an Interface, it needs to be Implemented and not inherited. (I am guessing here, but I think it's a Typo in the MSDN page you linked)
Change the class declare from:
Public Class ForumWithName
Inherits IEquatable(Of ForumWithName)
to be
Public Class ForumWithName
Implements IEquatable(Of ForumWithName)
Once you have done that, you will also need to add this function
Public Overloads Function Equals(other As ForumWithName) As Boolean Implements IEquatable(Of ForumWithName).Equals
Return Compare(TryCast(other, ForumWithName))
End Function
To work around the problem of not being able to use Tuples, you should be able to use this:
Public Overrides Function GetHashCode() As Integer
Return (ForumID & Subscribed).GetHashCode()
End Function
EDIT:
On a side note, you may want to include the properties ForumName and Subscribed in the GetHashCode function to check if the objects are truly equal to one another.

Related

ASP.NET Web API - Return Object - Property Missing

I'm using ASP.NET Web API to return a custom class object. The class has several properties, one of which takes an optional parameter. All the properties except the one with the optional parameter are available in the resulting JSON response. If I remove the optional parameter the other property is then available as well. Any way to return the other property with the optional parameter in place? Thanks!
Here is the specific property I'm having trouble with:
Public Class customer
...
Public ReadOnly Property photoSrc(Optional shape As String = Nothing) As String
Get
Dim srcString = "/Images/User.png"
If shape = "square" Then
srcString = "/Images/UserSquare.png"
End If
Return srcString
End Get
End Property
...
End Class
And here is the api controller function I'm using to return json:
Public Function GetCustomer(id As Integer) As Object
Dim customer As customer = New customer(id)
Return customer
End Function
A property with a parameter is called an indexed property, or indexer. By design, Json.Net (which is used by Web API for JSON serialization) does not serialize indexed properties, even if the index parameter is optional. (You can see this for yourself in the source code for the GetSerializableMembers method of the DefaultContractResolver class.)
The simplest workaround is to add a separate non-indexed property to your class which calls the indexer with the parameter value you want it to have when serialized. You can make the property private if you want; if you do, you just need to mark it with a <JsonProperty> attribute to allow the serializer to "see" it. You can also use this attribute to give the alternate property the same name in the JSON as the indexed property it is replacing.
Public Class Customer
...
<JsonProperty("photoSrc")>
Private ReadOnly Property defaultPhotoSrc As String
Get
Return photoSrc()
End Get
End Property
Public ReadOnly Property photoSrc(Optional shape As String = Nothing) As String
Get
Dim srcString = "/Images/User.png"
If shape = "square" Then
srcString = "/Images/UserSquare.png"
End If
Return srcString
End Get
End Property
...
End Class
Fiddle: https://dotnetfiddle.net/ffNs9D

ASP.NET shared DLL

I asked this question several weeks ago and received some good answers: ASP.NET Class Library best practice. I now have another question.
The problem I have is that I have inherited an ASP.NET application, which contains lots of classes with tight coupling and low cohesion, which is not ideal. I want to share some of the code with other apps. Most of the code exists in one class, however the class references other classes and those classes reference other classes etc. Is there any way of sharing the code in one class (which references other classes)? The only way I can think of doing this is using web services, but there is sensitive information.
The only good option, in cases like this, is refactoring the code. You don't have to change the existing class interface, however. You can create multiple new classes that are designed properly and replace the logic in the original poorly designed class. Then you can refactor the original class to use the new classes internally to perform the functionality. You don't have to do this all at once. As you find that you need a particular bit of logic in a shared library, just refactor that logic and leave the rest untouched. Over time you can, in this way, refactor the whole thing. Unless, of course, it's not that big or you have all the time in the world to refactor the beast. However, usually that's not the case.
For instance, let's say you have the following overly simplified classes:
Public Class OriginalBeast
Private _dependency As New Dependency()
Public Function Method1() As Integer
Return _dependency.Calculate(2)
End Sub
Public Function Method2() As Integer
Return _dependency.Calculate(2)
End Sub
' ...
Public Function Method1027() As Integer
Return _dependency.Calculate(1027)
End Sub
End Class
Public Class Dependency
Public Function Calculate(value As Integer) As Integer
Return value * 2
End Function
End Class
And you want to share the logic in OriginalBeast.Method2 in a class library, you would need to move the Dependency class to the class library (and likely need to partially refactor it as well). Then you would need to create a new class that contains just the desired methods from the original beast:
Public Interface INice
Function Method2() As Integer
End Interface
Public Class Nice
Implements INice
Public Sub New(dependency As IDependency)
_dependency = dependency
End Sub
Private _dependency As IDependency
Public Function Method2() As Integer Implements INice.Method2
Return _dependency.Calculate(2)
End Function
End Class
Public Interface IDependency
Function Calculate(value As Integer) As Integer
End Interface
Public Class Dependency
Implements IDependency
Public Function Calculate(value As Integer) As Integer Implements IDependency.Calculate
Return value * 2
End Function
End Class
Then, you would need to refactor the original beast to use the class library instead of doing the logic itself:
Public Class OriginalBeast
Public Sub New()
_dependency = New Dependency()
_nice = New Nice(_dependency)
End Sub
Private _dependency As IDependency
Private _nice As INice
Public Function Method1() As Integer
Return _dependency.Calculate(2)
End Sub
Public Function Method2() As Integer
Return _nice.Method2()
End Sub
' ...
Public Function Method1027() As Integer
Return _dependency.Calculate(1027)
End Sub
End Class
Obviously real-world beasts are never that simple and it will likely require a lot of work to refactor even a small part of it, but hopefully that gives you an idea of what I'm talking about.

VB.NET Entity Framework issue with WHERE clause and Boolean values

I'm pretty new to MVC and the Entity Framework, but I'm sure this should be straight forward. I've got a class with a boolean "Active" flag. I then have a function that returns the results by date descending. All I want to do is ensure that only active records are returned. Should be simple, but it fails with the following error:
Error 13 Overload resolution failed because no accessible 'Where' can be called with these arguments:
Extension method 'Public Function Where(predicate As System.Func(Of Review, Integer, Boolean)) As System.Collections.Generic.IEnumerable(Of Review)' defined in 'System.Linq.Enumerable': Value of type 'Boolean' cannot be converted to 'System.Func(Of PowellCasting.Models.Review, Integer, Boolean)'.
Extension method 'Public Function Where(predicate As System.Func(Of Review, Boolean)) As System.Collections.Generic.IEnumerable(Of Review)' defined in 'System.Linq.Enumerable': Value of type 'Boolean' cannot be converted to 'System.Func(Of PowellCasting.Models.Review, Boolean)'.
Extension method 'Public Function Where(predicate As System.Linq.Expressions.Expression(Of System.Func(Of Review, Integer, Boolean))) As System.Linq.IQueryable(Of Review)' defined in 'System.Linq.Queryable': Value of type 'Boolean' cannot be converted to 'System.Linq.Expressions.Expression(Of System.Func(Of PowellCasting.Models.Review, Integer, Boolean))'.
Extension method 'Public Function Where(predicate As System.Linq.Expressions.Expression(Of System.Func(Of Review, Boolean))) As System.Linq.IQueryable(Of Review)' defined in 'System.Linq.Queryable': Value of type 'Boolean' cannot be converted to 'System.Linq.Expressions.Expression(Of System.Func(Of PowellCasting.Models.Review, Boolean))'. C:\Web Projects\Powell Casting\PowellCasting\PowellCasting\Models\Review.vb 42 14 PowellCasting
It looks as thought it doesn't like comparing Booleans but they have the same data type. I'm sure this should be simple, but would appreciate some help. Please see my code below.
Public Class Review
Private PowellCastingDB As PowellCastingEntites = New PowellCastingEntites
<ScaffoldColumn(False)>
Public Property ReviewID As Integer
<Required(ErrorMessage:="An review title is required")>
<StringLength(256)>
<DisplayName("Title")>
Public Property Title As String
<DisplayName("Heading")>
Public Property Heading As String
<DisplayName("ReviewText")>
<StringLength(4096)>
Public Property ReviewText As String
<DisplayName("Author")>
<StringLength(256)>
Public Property Author As String
<DisplayName("Publication")>
<StringLength(150)>
Public Property Publication As String
<DisplayName("PublicationDate")>
Public Property PublicationDate As Date
<DisplayName("PublicationLink")>
<StringLength(1000)>
Public Property PublicationLink As String
<DisplayName("Image")>
<StringLength(512)>
Public Property Image As String
<DisplayName("Active")>
Public Property Active As Boolean
Public Property Reviews As List(Of Review)
Public Function GetLatestReviews(ByVal count As Integer) As List(Of Review)
Return PowellCastingDB.Reviews.Where(Active = True).
OrderByDescending(Function(a) a.PublicationDate).
Take(count).
ToList()
End Function
End Class
End Namespace
You need to specify a lambda expression:
Return PowellCastingDB.Reviews.Where(Function(x) x.Active = True).
(rest of query)
Or just:
Return PowellCastingDB.Reviews.Where(Function(x) x.Active).
(rest of query)
Try this:
Return PowellCastingDB.Reviews.Where(Function(review) review.Active = True)

Entity Framework: Metadata when Entity Name is Same as Property?

I have a EDM with a entity "Extensions" - within this object is the property extension. I've wired up all the other columns just fine, but this one refuses to wire up. I'm guessing because the entity and the property share the same name?
Here is my code, the extensions doesn't work, the prefix does work:
Imports System.Web.DynamicData
Imports System.ComponentModel.DataAnnotations
<MetadataType(GetType(ExtensionsMetaData))> _
Partial Public Class Extensions
End Class
Public Class ExtensionsMetaData
Private _phones_extensions As Object
Private _prefix As Object
Private _did_flag As Object
Private _len As Object
Private _sfc_id As Object
Private _name_display As Object
Private _floor As Object
Private _room As Object
Private _phones_departments As Object
Private _phones_buildings As Object
Private _phones_phones As Object
Private _phones_restriction_classes As Object
Private _phones_tens As Object
<DisplayName("Extension")> _
Public Property extensions() As Object
Get
Return _phones_extensions
End Get
Set(ByVal value As Object)
_phones_extensions = value
End Set
End Property
<DisplayName("Prefix")> _
Public Property prefix As Object
Get
Return _prefix
End Get
Set(ByVal value As Object)
_prefix = value
End Set
End Property
End Class
How can I get this code to work? I've looked all through my data model and it looks like the name should be Extensions!
The error I am receiving is: The associated metadata type for type 'phoneDBentities.Extensions' contains the following unknown properties or fields: extensions. Please make sure that the names of these members match the names of the properties on the main type.
This is a limitation of EF's "convention over configuration" feature.
Here's a related question: Entity Framework Mapping Oddity - member names cannot be the same as their enclosing type
The easiest way to fix the problem would be to rename the property to "PhoneExtension."

Is it possible get the functionality of namespaces inside a class?

I have the following code:
Public Class Form1
Private Function Step1_Execute() As Boolean
Return Step1_Verify()
End Function
Private Function Step1_Verify() As Boolean
Return True
End Function
Private Function Step2_Execute() As Boolean
Return Step2_Verify()
End Function
Private Function Step2_Verify() As Boolean
Return True
End Function
End Class
What I would like to do is be able to separate the code, similar to the following (which obviously doesn't work):
Public Class Form1
Namespace Step1
Private Function Step1_Execute() As Boolean
Return Step1_Verify()
End Function
Private Function Step1_Verify() As Boolean
Return True
End Function
End Namespace
Namespace Step2
Private Function Step2_Execute() As Boolean
Return Step2_Verify()
End Function
Private Function Step2_Verify() As Boolean
Return True
End Function
End Namespace
End Class
I would like the functionality of namespaces inside of a class, as in something that would let me call Step2.Execute() instead of having to put Step2_ in front of a whole bunch of functions. I don't want to have to create separate classes / modules for step1, step2, etc.
Is there a way that I can accomplish namespace functionality from inside a class?
How about just using a module (equivalent for the most part to a static class in C#)? That would seem to do the job well and give you the reference style you want.
Module Step1
Private Function Execute() As Boolean
Return Verify()
End Function
Private Function Verify() As Boolean
Return True
End Function
End Module
Module Step2
Private Function Execute() As Boolean
Return Step2_Verify()
End Function
Private Function Verify() As Boolean
Return True
End Function
End Module
I believe you can even nest VB.NET Modules within other classes, if you wish.
Edit:
Just realised that all of the modules have the same contract (set of method signatures), so it would actually make sense to implement an interface here, and create instances of the class. A tad more code perhaps, but if you want to abstractify things, it may be worth the effort.
No.
Namespaces are nothing real existing. A namespace is merely a part of the name of a class. So if you have the class System.Text.StringBuilder, the "using System.Text" part is a hint to the compiler like "if you don't find the type, look for all types with the unknown identifier that start with 'System.Text' in front of the unknown part.
Obviously you need to split this up in 3 classes. One that will execute the code. And than 2 that inherit the same interface with an execute and verify method in it.
The executing class wil then contain a collection of this interface and you just add them in the order you wan to execute them.

Resources