JsonConvert.DeserializeObject Returns missing values - asp.net

I am attempting to push data through AJAX to my ASP.NET Web Service, which inserts the data into my DB. However, i am having problems looping through my deserialized list.
Here is my class:
Public Class TimesheetDetails
Inherits System.Web.Services.WebService
Public Property TimesheetID() As String
Get
Return m_TimesheetID
End Get
Set
m_TimesheetID = Value
End Set
End Property
Private m_TimesheetID As String
Public Property LineNumber() As String
Get
Return m_LineNumber
End Get
Set
m_LineNumber = Value
End Set
End Property
Private m_LineNumber As String
Public Property ProjectCode() As String
Get
Return m_ProjectCode
End Get
Set
m_ProjectCode = Value
End Set
End Property
Private m_ProjectCode As String
Public Property Comments() As String
Get
Return m_Comments
End Get
Set
m_Comments = Value
End Set
End Property
Private m_Comments As String
Public Property SAT() As Decimal
Get
Return m_SAT
End Get
Set
m_SAT = Value
End Set
End Property
Private m_SAT As Decimal
Public Property SUN() As Decimal
Get
Return m_SUN
End Get
Set
m_SUN = Value
End Set
End Property
Private m_SUN As Decimal
Public Property MON() As Decimal
Get
Return m_MON
End Get
Set
m_MON = Value
End Set
End Property
Private m_MON As Decimal
Public Property TUE() As Decimal
Get
Return m_TUE
End Get
Set
m_TUE = Value
End Set
End Property
Private m_TUE As Decimal
Public Property WED() As Decimal
Get
Return m_WED
End Get
Set
m_WED = Value
End Set
End Property
Private m_WED As Decimal
Public Property THU() As Decimal
Get
Return m_THU
End Get
Set
m_THU = Value
End Set
End Property
Private m_THU As Decimal
Public Property FRI() As Decimal
Get
Return m_FRI
End Get
Set
m_FRI = Value
End Set
End Property
Private m_FRI As Decimal
Public Property TOTAL() As Decimal
Get
Return m_TOTAL
End Get
Set
m_TOTAL = Value
End Set
End Property
Private m_TOTAL As Decimal
End Class
and the method
<WebMethod()>
Public Function SaveData(empdata) As String
'WebMethod to Save the data
Dim serializeData = JsonConvert.DeserializeObject(Of List(Of TimesheetDetails))(empdata)
Dim ids As String = ""
For Each obj As Object In serializeData
If obj.LineNumber = "0" Then
Else
Dim timesheetid As String = obj.TimesheetID
Dim linenumber As String = obj.LineNumber
Dim projectcode As String = obj.ProjectCode
Dim comments As String = obj.Comments
Dim monday As String = obj.MON
Dim tuesday As String = obj.TUE
Dim wednesday As String = obj.WED
Dim thursday As String = obj.THU
Dim friday As String = obj.FRI
Dim saturday As String = obj.SAT
Dim sunday As String = obj.SUN
Dim total As String = obj.TOTAL
Dim noteid As String = "No id found"
Debug.WriteLine(linenumber + " | " + projectcode + ", " + monday + tuesday + wednesday + thursday + friday + saturday + sunday)
End If
Next
Return Nothing
End Function
The data arrives from the AJAX post intact, but when the data is deserialized, some of my values remain the same, but others become null or 0.
Here are the before values, successfully posted:
[
{
"timesheetid":"86",
"linenumber":0
},
{
"timesheetid":"86",
"linenumber":1,
"projectcode":"12988",
"comments":" test comment",
"monday":"7.5",
"tuesday":"7.5",
"wednesday":"7.5",
"thursday":"7.5",
"friday":"7",
"saturday":"7.5",
"sunday":"7.5",
"total":"52"
}
]
and here are the values after the data is deserialized:
[
{
"timesheetid":"86",
"linenumber":0
},
{
"timesheetid":"86",
"linenumber":1,
"projectcode":"12988",
"comments":" test comment",
"monday":"0",
"tuesday":"0",
"wednesday":"0",
"thursday":"0",
"friday":"0",
"saturday":"0",
"sunday":"0",
"total":"52"
}
]

I think the problem is some properties of TimesheetDetails class is different with posted object properties. For example, property in posted object is name monday, while in TimesheetDetails class, its name is MON.

Related

How to sort properties of object and populate into an ArrayList

How can I sort the following properties in the class then store in an ArrayList?
I have populated that to an ArrayList but there an issue when page is reloaded items order in the repeater will change. here is population cookies value in to an array
Dim myCookies As HttpCookie=HttpContext.Current.Request.Cookies("Mycard")
Dim varArryItems As ArrayList = New ArrayList
For i AsInteger=0 To varCookies.Values.Count-1
Dim AllValues As String()=myCookies.Values(i).Split("|"c)
Dim item As objCard=New objCard
item.P_ItemID=Integer.Parse(AllValues(0))
item.P_ItemTitle=AllValues(1).ToString
item.P_BrandTitle=AllValues(2).ToString
item.P_ItemImg=AllValues(3).ToString
item.P_ItemPrice=Decimal.Parse(AllValues(4))
'item.P_ItemQauntity=Integer.Parse(AllValues(5))
'item.P_ItemQauntitySelected=Integer.Parse(AllValues(6))
item.P_BarcodeID=Integer.Parse(AllValues(7))
item.P_TotalItemPrice=Decimal.Parse(AllValues(8))
varArryItems.Add(item)
Next
rptcart.DataSource=varArryItems
rptcart.DataBind()
Here is my objCard class store cookies values I need sort all properties I have tried suing ArrayList Sort method it wasn't work for me.
Public Class objCard
Private ID As Integer
Private ItemID As Integer
Private BarcodeID As Integer
Private ItemTitle As String
Private BrandTitle As String
Private ItemImg As String
Private ItemPrice As Decimal
Private TotalItemPrice As String
Private ItemQauntity As Integer
Private ItemQauntitySelected As Integer
Public Property P_ID As Integer
Get
Return Me.ID
End Get
Set
Me.ID = Value
End Set
End Property
Public Property P_ItemID As Integer
Get
Return Me.ItemID
End Get
Set
Me.ItemID = Value
End Set
End Property
Public Property P_BarcodeID As Integer
Get
Return Me.BarcodeID
End Get
Set
Me.BarcodeID = Value
End Set
End Property
Public Property P_ItemTitle As String
Get
Return Me.ItemTitle
End Get
Set
Me.ItemTitle = Value
End Set
End Property
Public Property P_BrandTitle As String
Get
Return Me.BrandTitle
End Get
Set
Me.BrandTitle = Value
End Set
End Property
Public Property P_ItemImg As String
Get
Return Me.ItemImg
End Get
Set
Me.ItemImg = Value
End Set
End Property
Public Property P_ItemPrice As Decimal
Get
Return Me.ItemPrice
End Get
Set
Me.ItemPrice = Value
End Set
End Property
Public Property P_TotalItemPrice As String
Get
Return Me.TotalItemPrice
End Get
Set
Me.TotalItemPrice = Value
End Set
End Property
Public Property P_ItemQauntity As Integer
Get
Return Me.ItemQauntity
End Get
Set
Me.ItemQauntity = Value
End Set
End Property
Public Property P_ItemQauntitySelected As Integer
Get
Return Me.ItemQauntitySelected
End Get
Set
Me.ItemQauntitySelected = Value
End Set
End Property
End Class
If you have
Public Class Card
Property ID As Integer
Property ItemID As Integer
Property BarcodeID As Integer
Property ItemTitle As String
Property BrandTitle As String
Property ItemImg As String
Property ItemPrice As Decimal
Property TotalItemPrice As Decimal
Property ItemQuantity As Integer
Property ItemQuantitySelected As Integer
End Class
Then you can use a List(Of Card) to store the data. This has the advantange that the compiler knows that it has instanced of Card in it instead of just some object.
Dim myCookies As HttpCookie = HttpContext.Current.Request.Cookies("Mycard")
Dim cards = New List(Of Card)
For i As Integer = 0 To varCookies.Values.Count-1
Dim allValues As String() = myCookies.Values(i).Split("|"c)
Dim item = New Card
item.ItemID = Integer.Parse(allValues(0))
item.ItemTitle = allValues(1).ToString
item.BrandTitle = allValues(2).ToString
item.ItemImg = allValues(3).ToString
item.ItemPrice = Decimal.Parse(allValues(4))
'item.ItemQuantity = Integer.Parse(allValues(5))
'item.ItemQuantitySelected = Integer.Parse(allValues(6))
item.BarcodeID = Integer.Parse(allValues(7))
item.TotalItemPrice = Decimal.Parse(allValues(8))
cards.Add(item)
Next
And now that the compiler can get to the properties of the entries in the list, you can
Dim dataToPresent = cards.OrderBy(function(c) c.ItemId).ToList()
rptcart.DataSource = dataToPresent
rptcart.DataBind()
and it will show the data in the order you chose.
If you need to order by different properties at run-time then a search for "linq dynamic orderby" should give you useful code.
I noticed that you had Private TotalItemPrice As String which conflicted with item.P_TotalItemPrice=Decimal.Parse(AllValues(8)). If you use Option Strict On then Visual Studio will point out problems like that for you.
P.S. You have Dim myCookies but you use varCookies.Values.Count. You may want to check that that is correct.

How to Compare nullable objects

I need to compare a current List of Objects from a DB against a new List of Objects. I want to compare them and highlight for the user those which have changed (in this case, return TRUE that they are different).
Since some of my objects are Nullable, this involves a lot of IF NOT IS Nothing on the side of the NewObj and the CurrentObj...I've trying to find a more efficient way of writing the below as I have to use it to compare about 30 objects of different types, IE Date, Decimal, Int, etc..
The below works until say either of the Obj has no Rank and is therefore Nothing
Suggestions?
Dim Rank As Boolean = CompareData(NewObj, CurrentObj, "Rank")
Dim Regiment As Boolean = CompareData(NewObj, CurrentObj, "Rank")
Dim DateofBirth As Boolean = CompareData(NewObj, CurrentObj, "DoB")
Private Function CompareData(NewObj As Business.Casualty, CurrentObj As Business.Casualty, FieldToComapre As String) As Boolean
Select Case FieldToComapre
Case "DateOfBirth"
Return (Nullable.Equals(NewCasualty.DateOfBirth, CurrentCasualty.DateOfBirth))
Case "Age"
Return (Nullable.Equals(NewCasualty.Age, CurrentCasualty.Age))
Case "Rank"
Return (Nullable.Equals(NewCasualty.Rank.ID, CurrentCasualty.Rank.ID))
Case "Regiment"
Return (Nullable.Equals(NewCasualty.Regiment.ID, CurrentCasualty.Regiment.ID))
Case Else
Return True
End Select
End Function
My first suggestion is to change the name of your function to something like AreFieldValuesTheSame. My second suggestion is to negate the purpose of the function. In other words, return True when the values are the same.
If you follow my first two suggestions, then for each one of your cases, instead of simply
Return (Nullable.Equals(a.ID, b.ID))
you need something more like
Return ((a Is Nothing And b Is Nothing) Or (a.ID Is Nothing And b.ID Is Nothing) Or (Nullable.Equals(a.ID, b.ID)))
For example, a represents NewCasualty.Rank and b represents CurrentCasualty.Rank. You need to check for the object being Nothing (null in other words) before you try to check properties of the object.
Also, at the beginning of the function, you need to check whether NewObj Is Nothing and whether CurrentObj Is Nothing:
If (NewObj Is Nothing) And (CurrentObj Is Nothing) Then
Return True
Else If (NewObj Is Nothing) Or (CurrentObj Is Nothing)
Return False
Please forgive me if my VB syntax is not perfect. (I'm much more fluent in C#.)
I actually ended up just going with an Extension method..it was simpler and cleaner IMO.
Dim Rank As Boolean = CompareData(NewObj, CurrentObj, "Rank")
Dim Regiment As Boolean = CompareData(NewObj, CurrentObj, "Regiment")
Dim Trade As Boolean = CompareData(NewObj, CurrentObj, "Trade")
Private Function CompareData(NewObj As Business.Casualty, CurrentObj As Business.Casualty, FieldToComapre As String) As Boolean
Select Case FieldToComapre
Case "Trade"
Return NewCasualty.Trade.NullableEquals(CurrentCasualty.Trade)
Case "Rank"
Return NewCasualty.Rank.NullableEquals(CurrentCasualty.Rank)
Case "Regiment"
Return NewCasualty.Regiment.NullableEquals(CurrentCasualty.Regiment)
Case Else
Return True
End Select
End Function
public static class NullableCompare
{
public static bool NullableEquals<T>(this T s1, T s2)
where T : class
{
if (s1 == null)
{
return s2 == null;
}
return s1.Equals(s2);
}
}
public partial class Rank
{
public override bool Equals(object obj)
{
var p2 = obj as Rank;
if (p2 == null)
{
return false;
}
if (this.ID != p2.ID)
{
return false;
}
return this.ID == p2.ID;
}
public override int GetHashCode()
{
return this.ID.GetHashCode();
}
}

How can I assign a property value based on another property in a composite control?

Environment: Asp.net 4.5, Webforms
I'm creating a composite control. I've exposed multiple public properties, but running into a slight problem.
Let's say I have two properties:
Public Property Path() As String
Get
Return ViewState("Path")
End Get
Set(ByVal Value As String)
If UseAbsolute = True Then
' do something
Else
' it always lands heere...
End If
End If
ViewState("Path") = Value
End Set
End Property
Private _Path As String = String.Empty
Public Property UseAbsolute() As Boolean
....
End Property
Private _UseAbsolute As Boolean = False
My controls are being assigned values on PreRender. The problem is, when I call "Path" it's getting the default/private value for UseAbsolute. So even if I set the property to True in the control/html, it grabs the false first.
I can work around this many ways, but I feel I'm missing a proper method or understanding.
UPDATE
I forgot to mention. I am:
EnsureChildControls()
in the PreRender...
I also tried adding this to the properties themselves.
Shouldn't Your code be like this instead of how you have it?
Private _Path As String = String.Empty
Private _UseAbsolute As Boolean = False
'
Public Property Path() As String
Get
Return _Path
End Get
Set(ByVal Value As String)
If UseAbsolute = True Then
' do something
_Path = some_absolute_path
Else
' do something else
_Path = some_relative_path
End If
End Set
End Property
'
Public Property UseAbsolute () As Boolean
Get
Return _UseAbsolute
End Get
Set(ByVal Value As Boolean)
_UseAbsolute = Value
End Set
End Property

How to call multiple different methods simultaneously

I have some different methods that each import products from different sites.
If I execute these sequentially the entire process takes a lot of time, particularly when 1 method is running on a site that is less responsive.
I'd rather run them simultaneously.
This is what I have so far with 1 example method:
Public Class feedParameters
Private _productIdPrefix As String
Private _publishersite As String
Private _feedURL As String
Public Property productIdPrefix() As String
Get
Return _productIdPrefix
End Get
Set(value As String)
_productIdPrefix = value
End Set
End Property
Public Property publishersite() As String
Get
Return _publishersite
End Get
Set(value As String)
_publishersite = value
End Set
End Property
Public Property feedURL() As String
Get
Return _feedURL
End Get
Set(value As String)
_feedURL = value
End Set
End Property
End Class
Dim fpm As New feedParameters
fpm.publishersite = "mypublisher.nl"
fpm.feedURL = "http://www.domain.com/test.xml"
fpm.productIdPrefix = "10"
Protected Sub ImportProductsPublisherA(ByVal productIdPrefix As String, ByVal publishersite As String, ByVal feedURL As String)
End Sub
I tried this:
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsPublisherA()), fpm)
Then I get 3 errors that I have not specified arguments for the 3 parameters: productIdPrefix, publishersite and feedURL
I also tried:
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsPublisherA), fpm)
I get this error:
Method 'Protected Sub ImportProductsPublisherA(productIdPrefix As String, publishersite As String, feedURL As String)' does not have a signature compatible with delegate 'Delegate Sub WaitCallback(state As Object)'.
Any help is greatly appreciated!
using System.Threading.Tasks;
namespace Foo
{
public class Bar
{
public void ImportProductsSiteA() { }
public void ImportProductsSiteB() { }
public void ImportProductsSiteC() { }
public void ImportProductsSiteD() { }
public void Execute()
{
var a = Task.Factory.StartNew(ImportProductsSiteA);
var b = Task.Factory.StartNew(ImportProductsSiteB);
var c = Task.Factory.StartNew(ImportProductsSiteC);
var d = Task.Factory.StartNew(ImportProductsSiteD);
Task.WaitAll(a, b, c, d);
}
}
}
Is this WinForms or asp.net?
If winforms create a background worker for each function and start all of them, they will work independently in a separate thread.
If asp.net you want to look at using System.Threading.ThreadPool - http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsSiteA))
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsSiteB))
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsSiteC))
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsSiteD))
If you functions take any parameters you can pass them like this:
System.Threading.ThreadPool.QueueUserWorkItem(New System.Threading.WaitCallback(AddressOf ImportProductsSiteA), parameter-here)

Object references and cache

I have a function GetAllProducts() which fetches all products from a database and stores it in the cache for future requests. This works fine, but if I then call the function e.g. ProductSearchResults = GetAllProducts(), and then modify ProductSearchResults variable, this also modifies the cache, which is very important this never happens, as the cache affects the whole website.
I understand this is because both ProductSearchResults and the cache now have the same reference, but how do I solve the problem? Is there something that I can put in GetAllProducts() to ensure the cache always uses its own value?
Public Shared Function GetAllProducts() As ProductCollection
Dim Products As New ProductCollection()
If IsNothing(System.Web.HttpContext.Current.Cache("ProductData")) Then
'////// Database code to get products goes here //////
System.Web.HttpContext.Current.Cache.Insert("ProductData", Products, Nothing, DateTime.Now.AddMinutes(5), TimeSpan.Zero)
End If
Products = System.Web.HttpContext.Current.Cache("ProductData")
Return Products
End Function
Public Shared Function SearchProducts(ByVal SearchText As String) As ProductCollection
Dim ProductSearchResults As ProductCollection = Nothing
If SearchText <> "" Then
SearchText = SearchText.ToLower()
Dim Keywords As New ArrayList()
Keywords.AddRange(SearchText.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
ProductSearchResults = GetAllProducts()
For i As Integer = 0 To Keywords.Count - 1
For j As Integer = ProductSearchResults.Count - 1 To 0 Step -1
If ProductSearchResults(j).ProductName.ToLower.Contains(Keywords(i)) = False Then
ProductSearchResults.RemoveAt(j)
End If
Next
Next
End If
Return ProductSearchResults
End Function
This is because you are essentially returning a collection of pointers to the object thats in the cache. You could implement IClonable on your object and have a Function that returns a new collection with cloned objects.
Public Function GetClonedObjects() As ProductCollection
Dim myCollection As New List(Of MyObject)
For Each item as Product in GetProducts()
myCollection.Add(item.Clone)
Loop
Return myCollection
End Function
Or Create a property to hold a cloned copy of the collection
Private _clonedProducts As ProductCollection = Nothing
Public ReadOnly Property ClonedProducts As ProductCollection
Get
If _clonedProducts Is Nothing Then
_clonedProducts = New ProductCollection
For Each item As Product In GetAllProducts()
_clonedProducts.Add(item.Clone())
Next
End If
Return _clonedProducts
End Get
End Property

Resources