Adding Properties to WCF DataContract - vb.net

I've added a service reference to my WCF webservice which generated all of my datacontract objects. I'm using BasicHttpBinding. Using a partial class, I've made one of these objects inherit from another class that adds some properties to it. Now it throws an error when making a call to the service:
Test method CP.Exg2010.Tests.UnitTest1.TestWCF threw exception:
System.ServiceModel.Dispatcher.NetDispatcherFaultException: The
formatter threw an exception while trying to deserialize the message:
There was an error while trying to deserialize parameter
http://tempuri.org/:RunResult. The InnerException message was 'Error
in line 1 position 283. 'Element' 'CommandResult' from namespace
'uri://mycomp.corp/line/exg2010' is not expected. Expecting element
'_EngineTracingData'.'. Please see InnerException for more details.
---> System.Runtime.Serialization.SerializationException: Error in
line 1 position 283. 'Element' 'CommandResult' from namespace
'uri://mycomp.corp/line/exg2010' is not expected. Expecting element
'_EngineTracingData'.
CommandResult is a property that is part of the WSDL. _EngineTracingData is the private field used by a property in a base class.
<XmlIgnore()> <SoapIgnore()> <Newtonsoft.Json.JsonIgnore()> _
Private _EngineTracingData As String = String.Empty
<XmlIgnore()> <SoapIgnore()> <Newtonsoft.Json.JsonIgnore()>
Public Property EngineTracingData As String Implements Interfaces.ICPMasterBaseInfo.EngineTracingData
Get
Return Me._EngineTracingData
End Get
Set(ByVal value As String)
Me._EngineTracingData = value
End Set
End Property
I read something about the deserialization happening in alphabetic order, which would explain why _EngineTracingData is first. But, that field/property shouldn't even be used in deserialization!
Any help would be appreciated!

Ah, I found it!
Adding
<NonSerialized()>
to the private fields in the base class fixed my issue!

Related

Error - 'Unable to cast object of type 'System.Collections.Generic.List`1[]' to type 'System.Collections.Generic.IEnumerable`[]'.'

I am new to API's and I am developing one (trying to) in VB.net and have followed this video - https://www.youtube.com/watch?v=nMGlaiNBbNU. although I am using Visitors instead of employees.
I have translated the code to this - (From C# To VB)
Namespace Controllers
Public Class VisitorsController
Inherits ApiController
Public Function [Get]() As IEnumerable(Of Visitor)
Using entities As SignInSystemLiveEntities = New SignInSystemLiveEntities()
Return entities.pa_Visitors_GetOnSite.ToList()
End Using
End Function
End Class
End Namespace
although when i execute this i get the following error message:
System.InvalidCastException: 'Unable to cast object of type 'System.Collections.Generic.List1[VisitorsDA.pa_Visitors_GetOnSite_Result]' to type 'System.Collections.Generic.IEnumerable1[VisitorsDA.Visitor]'.'
Please Help
Many Thanks,
The List<T> class does implement the IEnumerable<T> interface, so that's not the problem. The issue is the item type. As the error message says, the method is supposed to return a list of VisitorsDA.Visitor objects but you're actually trying to return a list of VisitorsDA.pa_Visitors_GetOnSite_Result objects. Either get different objects to return or change the return type of the method, or else map the data between those two types somehow.

Why is this Entity Framework association not loading lazily?

I'm using a Code First Entity Framework approach, and in my OnModelCreating function I have the following code:
With modelBuilder.Entity(Of FS_Item)()
.HasKey(Function(e) e.ItemKey)
.Property(Function(e) e.ItemRowVersion).IsConcurrencyToken()
.HasMany(Function(e) e.ItemInventories) _
.WithRequired(Function(e) e.Item).HasForeignKey(Function(e) e.ItemKey)
End With
Elsewhere I have a Web API Get implementation with some diagnostic code I'm looking at in a debugger:
Public Function GetValue(ByVal id As String) As FS_Item
GetValue = If(data.FS_Item.Where(Function(i) i.ItemNumber = id).SingleOrDefault(), New FS_Item())
Dim c = GetValue.ItemInventories.Count
End Function
I expect that c should get a non-zero value by looking up rows in the FS_Inventory view where ItemKey matches the retrieved FS_Item row's ItemKey. But I'm getting 0 even though there are matching rows. Am I calling .HasMany, .WithRequired and .HasForeignKey properly?
Note that .WithRequired is operating on the return value from the previous line whereas the other lines are operating on the With block expression.
Edit This model for FS_Item has been requested. Here it is:
Partial Public Class FS_Item
Public Property ItemNumber As String
Public Property ItemDescription As String
Public Property ItemUM As String
Public Property ItemRevision As String
Public Property MakeBuyCode As String
' Many many more properties
Public Property ItemRowVersion As Byte()
Public Property ItemKey As Integer
Private _ItemInventories As ICollection(Of FS_ItemInventory) = New HashSet(Of FS_ItemInventory)
Public Overridable Property ItemInventories As ICollection(Of FS_ItemInventory)
Get
Return _ItemInventories
End Get
Friend Set(value As ICollection(Of FS_ItemInventory))
_ItemInventories = value
End Set
End Property
End Class
Edit Learned something interesting. If I change Dim c = GetValue.ItemInventories.Count to this:
Dim c = data.FS_ItemInventory.ToList()
Dim correctCount = GetValue.ItemInventories.Count
Then correctCount gets the value of 3. It's like it understands the association between the objects, but not how to automatically query them as I'm used to coming from LINQ-to-SQL. Is EF different somehow in this regard?
Edit I have determined that I can make the associated objects load using this explicit loading code:
data.Entry(GetValue).Collection(Function(e) e.ItemInventories).Load()
What I want to understand now is what exactly determines whether an entity will load lazily or not? From all indications I can find, it should have loaded lazily. I even tried changing the declaration of ItemInventories to this, but then I got a NullReferenceException when trying to access it:
Public Overridable Property ItemInventories As ICollection(Of FS_ItemInventory)
It turns out that code which I thought was unrelated had disabled lazy loading. I have this in the constructor of FSDB:
DirectCast(Me, IObjectContextAdapter).ObjectContext.ContextOptions.ProxyCreationEnabled = False
Thanks to EF 4 - Lazy Loading Without Proxies I see that this will also disable lazy loading. The reason that code had been added was due to another error:
Type
'System.Data.Entity.DynamicProxies.FS_Item_64115A45C642902D6044AFA1AFD239E7DCB82FD000A10FE4F8DE6EA26A2AB418'
with data contract name
'FS_Item_64115A45C642902D6044AFA1AFD239E7DCB82FD000A10FE4F8DE6EA26A2AB418:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies'
is not expected. Consider using a DataContractResolver or add any
types not known statically to the list of known types - for example,
by using the KnownTypeAttribute attribute or by adding them to the
list of known types passed to DataContractSerializer.
And according to Serialization of Entity Framework objects with One to Many Relationship, the easy solution for that was to disable proxies.

WCF deserialization of type object Properties

I am having trouble achieving the following scenario.
We currently have a method which expects a list of 'context' key value pairs. The value however can be of any type.
the goal is to make this method available using WCF. So I created a
public List<Element> Transform(List<Element> elements)
{
... Transformation of elements takes place
}
[DataContract(Namespace = Constants.NAMESPACE)]
public struct Element
{
[DataMember(Order = 0, IsRequired = true)]
public string Key;
[DataMember(Order = 1, IsRequired = true)]
public object Value;
}
When I use a .Net test project everything works fine.
However, when I call this service using SOAP UI I get an error message:
The formatter threw an exception while trying to deserialize the
message: There was an error while trying to deserialize parameter
elements. The InnerException message was 'Element Value cannot have
child contents to be deserialized as an object. Please use XmlNode[]
to deserialize this pattern of XML.'.
I am having trouble figuring out what to do. any help appreciated.
the xml i use is this:
<ws:Transform>
<ws:elements>
<ws:Element>
<ws:Key>Key1</ws:Key>
<ws:Value>A</ws:Value>
</ws:Element>
<ws:Element>
<ws:Key>Key2</ws:Key>
<ws:Value>B</ws:Value>
</ws:Element>
<ws:ScriptName>SetVariable</ws:ScriptName>
</ws:elements>
</ws:Transform>
In this case, SoapUI uses .Net technology which does not understand target type for object.
sending object is not valid across all platforms. In fact you might get an error with a .Net client as well. Your best bet is create a generic xml representation of the Value and have all clients inflate the object from the xml

Bind Details view with class object

How can I bind the details view and return a class object?
Dim _obj As New NewRequestDetailsBL
_obj = NewRequestDetailsBL.SelectRequestDetails(Session("requestid"),
Session("contactid"))
dvAdmin1.DataSource = _obj ' this line is giving the error
dvAdmin1.DataBind()
Error:
System.InvalidOperationException: Data source is an invalid type.
It must be either an IListSource, IEnumerable, or IDataSource.
The error contains every information you need!
It must be either an IListSource, IEnumerable, or IDataSource.
Your class has to implement at least one of these interfaces and then you'll be able to set DataSource to an instance of NewRequestDetailsBL class.

WCF Deserialization resets DataMember value to default after OnDeserializing callback

I have developed a WCF Service Application hosted in IIS 7.5 targeting .NET 3.5 configured with only a basicHttpBinding endpoint. The OperationContract signature consists of a Composite type where one of its properties is a custom type. When this property is not initialized by the consuming client, the deserializer on the service appears to ignore the property leaving it null/nothing. I would like to initialize this custom type if it null/nothing and I realize that WCF serialization doesn't call constructors so I've used the deserialization callback. The callback executes and intializes the type but immediately after the callback completes this property returns to null/nothing. Stepping through the code, the ExtensionData property setter executes immediately after the callback and it is at this point where I notice that the property is reset to null/nothing. What am I missing? Here is my sample code
<DataContract(Name:="Request")> _
Public Class Request
Implements IExtensibleDataObject
<DataMember(Name:="MyCustomType")>
Public MyCustomType As CustomType
Private _ExtensionDataObject As ExtensionDataObject
Public Overridable Property ExtensionData() As ExtensionDataObject Implements IExtensibleDataObject.ExtensionData
Get
Return _ExtensionDataObject
End Get
Set(value As ExtensionDataObject)
_ExtensionDataObject = value
End Set
End Property
<OnDeserializing()>
Sub OnDeserializing(c As StreamingContext)
Me.myCustomType = New CustomType()
End Sub
End Class
If the client didn't initialize the property, then it's value is actually Nothing, and the fact that it is null/Nothing will be present in the serialized Request object. So prior to the deserialization happening, your OnDeserializing method is called, and it initializes the variable; but then the deserialization happens, and since there is a value for the property (which happens to be Nothing/null), it will override it.
I think what you want is to have an OnDeserializ*ed* callback, which will initialize the member after the deserialization happened, if it's value is Nothing:
<OnDeserialized()>
Sub OnDeserialized(ByVal c as StreamingContext)
If Me.myCustomType Is Nothing Then
Me.myCustomType = new CustomType()
End If
End Sub