I am using complex type as datamember of a datacontract - wcf

I am using complex type as datamember of a datacontract. But the service is throwing an exception if i set [DataMember] to the complextype. What might be the reason. KIndly suggest. Below is the code snippet
[DataContract]
public class GetDetailsFromCardNumberResponseBody
{
public GetDetailsFromCardNumberResponseBody()
{
}
public GetDetailsFromCardNumberResponseBody
(PatronAccountCardValidation GetDetailsFromCardNumberResult)
{
this.GetDetailsFromCardNumberResult = GetDetailsFromCardNumberResult;
}
[DataMember]
public PatronAccountCardValidation GetDetailsFromCardNumberResult { get; set; }
}
[DataContract(Name="PatronAccountCardValidation")]
public class PatronAccountCardValidation
{
[DataMember]
public Patron Patron { get; set; }
[DataMember]
public Card Card { get; set; }
[DataMember]
public string BonusDollarLocal { get; set; }
[DataMember]
public string BonusDollarRemote { get; set; }
[DataMember]
public bool Valid { get; set; }
[DataMember]
public string MessageText { get; set; }
}
Check the parameter PatronAccountCardValidation.
Check property Card. It is causing an issue. Please help.
Error received:
An unhandled exception of type
'System.ServiceModel.CommunicationException' occurred in mscorlib.dll
Additional information: An error occurred while receiving the HTTP
response to localhost:9090/DoorAccessAndVendingMachineService. This
could be due to the service endpoint binding not using the HTTP
protocol. This could also be due to an HTTP request context being
aborted by the server (possibly due to the service shutting down). See
server logs for more details

Have you consider to apply Data Contract Know types? It allows you to specify, in advance, the types that should be included for consideration during deserialization. And by default during deserialization, an uninitialized object is first created, without calling any constructors on the type. Then all data members are deserialized. See more details here.
[DataContract]
[KnownType(typeof(PatronAccountCardValidation))]
public class GetDetailsFromCardNumberResponseBody
{
public GetDetailsFromCardNumberResponseBody()
{
}
public GetDetailsFromCardNumberResponseBody
(PatronAccountCardValidation GetDetailsFromCardNumberResult)
{
this.GetDetailsFromCardNumberResult = GetDetailsFromCardNumberResult;
}
[DataMember]
public PatronAccountCardValidation GetDetailsFromCardNumberResult { get; set; }
}
[KnownType(typeof(Card))]
[KnownType(typeof(Patron))]
[DataContract(Name="PatronAccountCardValidation")]
public class PatronAccountCardValidation
{
[DataMember]
public Patron Patron { get; set; }
[DataMember]
public Card Card { get; set; }
[DataMember]
public string BonusDollarLocal { get; set; }
[DataMember]
public string BonusDollarRemote { get; set; }
[DataMember]
public bool Valid { get; set; }
[DataMember]
public string MessageText { get; set; }
}

Related

NServicebus Nhibernate Exception on sending message

When we send a message through NServiceBus containing a full exception stacktrace we get the following NHibernate exception:
Z Error dehydrating property value for
NServiceBus.TimeoutPersisters.NHibernate.TimeoutEntity.Headers NHibernate.PropertyValueException NHibernate.HibernateException NServiceBus.Core
at NServiceBus.Unicast.Transport.Transactional.TransactionalTransport.ProcessMessage(TransportMessage m)
at NServiceBus.Unicast.Transport.Transactional.TransactionalTransport.ReceiveMessage()
at NServiceBus.Utils.TransactionWrapper.RunInTransaction(Action callback, IsolationLevel isolationLevel, TimeSpan transactionTimeout)
at NServiceBus.Unicast.Transport.Transactional.TransactionalTransport.Process()
It has something to do with the length of the message field, but it seems like it's an internal
NServiceBus issue. We use NServiceBus v3.2.4
The message class looks like this:
public class ExceptionOccuredCommand : ICommand
{
public string Message { get; set; }
public string Details { get; set; }
public DateTime ExceptionDate { get; set; }
public string UserName { get; set; }
public string MachineName { get; set; }
public string ApplicationName { get; set; }
public string ErrorQueue { get; set; }
//public string SourceQueue { get; set; }
public string MessageId { get; set; }
}
How can this be fixed?
There is a hard limit on 4000 characters for the headers and you seems to be hitting that limit. I've opened up an issue for this on our issues list: https://github.com/NServiceBus/NServiceBus/issues/737

Json.net fails to deserialize a list of complex types

I'm using json.net to perform handle my json deserialization in a IIS hosted restful service.
First, here are the objects I'm trying to work with.
[DataContract]
public class CreateSamplesRequest
{
[DataMember] public Guid SessionId { get; set; }
[DataMember] public SampleTemplateDTO Template { get; set; }
}
[DataContract]
public class SampleTemplateDTO
{
[DataMember] public int NumberOfSamples { get; set; }
[DataMember] public int CompanyId { get; set; }
[DataMember] public int SampleTypeId { get; set; }
[DataMember] public HmisDTO Hmis { get; set; }
[DataMember] public List<AttributeValueDTO> AttributeValues { get; set; }
}
[DataContract]
public class AttributeValueDTO
{
[DataMember] public int AttributeId { get; set; }
[DataMember] public string AttributeName { get; set; }
[DataMember] public string Value { get; set; }
}
[DataContract]
public class HmisDTO
{
[DataMember] public string Health { get; set; }
[DataMember] public string Flammability { get; set; }
[DataMember] public string Reactivity { get; set; }
[DataMember] public string Equipment { get; set; }
}
The help page asks for json in this format for the CreateSamplesRequest
{
"SessionId":"1627aea5-8e0a-4371-9022-9b504344e724",
"Template":{
"NumberOfSamples":2147483647,
"CompanyId":2147483647,
"SampleTypeId":2147483647,
"Hmis":{
"Health":"String content",
"Flammability":"String content",
"Reactivity":"String content",
"Equipment":"String content"
},
"AttributeValues":[{
"AttributeId":2147483647,
"AttributeName":"String content",
"Value":"String content"
}]
}
}
And this is what I'm actually sending:
{
"SessionId":"17aaec11-be28-4536-b5df-d98fbda91e91",
"Template":{
"NumberOfSamples":1,
"CompanyId":1,
"SampleTypeId":9,
"Hmis":{
"Health":"2",
"Flammability":"0",
"Reactivity":"0",
"Equipment":"E",
},
"AttributeValues":[
{"AttributeId":1,"AttributeName":"Item No.","Value":"MN0002NG"},
{"AttributeId":2,"AttributeName":"Lot No.","Value":"C4526"}
]
}
}
The problem I'm having is that the AttributeValues property of the SampleTemplateDTO object always ends up being ignored. With the above code, it will be null. If I instanciate it to a empty List<AttributeValueDTO> it will be an empty list. I've been banging my head against this for a few hours.
I've tried creating a service that just takes a List<AttributeValueDTO> and it works fine. I've tried creating a wrapper class for the AttributeValues and it still ends up as null. I'm completely stumped. Any ideas?
MOTHER OF GOD, I JUST WASTED 5 FREAKING HOURS ON A FREAKING COMMA. The trailing comma in the HMIS section was apparently telling json.net to stop parsing at that point.
When I submit this json:
{
"SessionId":"17aaec11-be28-4536-b5df-d98fbda91e91",
"Template":{
"NumberOfSamples":1,
"CompanyId":1,
"SampleTypeId":9,
"Hmis":{
"Health":"2",
"Flammability":"0",
"Reactivity":"0",
"Equipment":"E"
},
"AttributeValues":[
{"AttributeId":1,"AttributeName":"Item No.","Value":"MN0002NG"},
{"AttributeId":2,"AttributeName":"Lot No.","Value":"C4526"}
]
}
}
Everything works great.

Returning IEnumerable<> from WCF service causes exception: The underlying connection was closed: The connection was closed unexpectedly

When I return IEnumerable<ProgramRange> an exception is thrown:
The underlying connection was closed: The connection was closed unexpectedly.
The class ProgramRange looks like this:
[DataContract]
public partial class ProgramRange
{
public ProgramRange()
{
this.GradeVariants = new HashSet<GradeVariant>();
}
[DataMember]
public int ID { get; set; }
[DataMember]
public int Range { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public virtual ICollection<GradeVariant> GradeVariants { get; set; }
}
The collection only contains eight items, so I don't think it's the <dataContractSerializer maxItemsInObjectGraph="2147483647" /> which is often suggested.
When I fetch the data from the context I do .ToList() so it can't be that:
public IEnumerable<ProgramRange> GetAll()
{
using (Entities dbContext = new Entities())
{
return dbContext.ProgramRanges.ToList();
}
}
I've tried to add the ProgramRange class to the known types of your service in the implementation:
[ServiceBehavior]
[ServiceKnownType(typeof(ProgramRange))]
public class ValidationService : IValidationService
I've tried returning several other things just to test: ProgramRange (works), IEnumerable<string> (works), List<ProgramRange> (does't work)
I know there are several question on the subject here on stackowerflow and I tried a lot of suggestions, but I can't get it to work.
Edit:
Here's the GradeVariant class:
[DataContract]
public partial class GradeVariant
{
public GradeVariant()
{
this.GradeVariantRules = new HashSet<GradeVariantRule>();
}
[DataMember]
public int ID { get; set; }
[DataMember]
public int GradeTypeID { get; set; }
[DataMember]
public int ProgramRangeID { get; set; }
[DataMember]
public Nullable<int> ProgramID { get; set; }
[DataMember]
public Nullable<int> ApprenticeID { get; set; }
[DataMember]
public Nullable<int> Prefix { get; set; }
[DataMember]
public Nullable<bool> IV { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public virtual GradeType GradeType { get; set; }
[DataMember]
public virtual ProgramRange ProgramRange { get; set; }
[DataMember]
public virtual ICollection<GradeVariantRule> GradeVariantRules { get; set; }
}
Edit :
You are using nullable objects, this is not allowed in a wcf service.
Add [IgnoreDataMember] in front of these members or make them not nullable to fix your issue.
Could you post the class GradeVariant as well? It's possible there are certain unparsable elements in that class which throw the connection was closed unexpectedly.
A few posibilities are a dictionary or nullable item.
Your test with a single ProgramRange might work because the list of GradeVariants is empty or null.
A good tip to try out is to check the inner exception of the inner exception of the inner exception....
At the end of the line it usually says something like can't parse Dictionary.
If it's the serialization (which it probably is), try this more directly to see if you can find the issue:
try
{
MemoryStream tempWrite = new MemoryStream();
DataContractSerializer ds = new DataContractSerializer(typeof(ProgramRange));
ds.WriteObject(myProgramRangeInstance, tempWrite);
MemoryStream tempRead = new MemoryStream(tempWrite.GetBuffer());
ProgramRange newInstance = (ProgramRange)ds.ReadObject(tempRead);
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
Try that with myProgramRangeInstance starting out as a valid instance of your class. That'll tell you if it's a serialization issue, and what exactly is causing it.
Right now, I'm betting on the fact that you're using a HashSet, but I really don't know. The exception information from the above should give more information.
I found the answer to my own question and here goes:
The problem was that WCF was unable to serialize the circular reference that Entity Framework created when loading the referenced entities.
To resolve this issue, simply put
[DataContract(IsReference = true)]
over the model class.
It's explained in detail here, http://www.binaryforge-software.com/wpblog/?p=129

Interface segregation in WCF for JSON

I am a newbie in WCF. I was wondering if we can retrive properties from base interface in the REST output.
Please consider following structure. Product includes IVenueView not Venue. Is it possible to only have Venue.Id in Product JSON response?
[DataContract]
public class Product {
[DataMember]
public Guid? Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public IVenueView Venue { get; set; }
}
public interface IVenueView {
[DataMember]
Guid? Id { get; set; }
}
[DataContract]
public class Venue : IVenueView
{
[DataMember]
public Guid? Id { get; set; }
[DataMember]
public string Name { get; set; }
}
Data contracts are all about data - interfaces define behaviors, so they don't really mix up well. The data contract that you have likely will not work (because the serializer doesn't "know" about the Venue type (it only knows about IVenueView), it won't be able to serialize / deserialize instances of Product.
No it is not possible because serialization and deserialization works with the implementation (actual data) not with interfaces. Moreover for pure serialization you will have to use something like:
[DataContract]
[KnownType(typeof(Venue))]
public class Product
{
[DataMember]
public Guid? Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public IVenueView Venue { get; set; }
}

WCF - DataMember as DataContract

I have a [DataContract] class Template declared as follows:
[DataContract]
public abstract class Template
{
[DataMember]
public virtual int? Id { get; set; }
[DataMember]
public virtual byte[] TemplateDoc { get; set; }
[DataMember]
public virtual string Title { get; set; }
[DataMember]
public virtual TemplateStatusInfo TemplateStatus { get; set; }
}
[DataContract]
public class TemplateStatusInfo
{
[DataMember]
public virtual List<string> ValidCodes { get; set; }
[DataMember]
public virtual List<string> InvalidCodes { get; set; }
[DataMember]
public virtual string TemplateError { get; set; }
}
As you can see Template has a [DataMember] child object 'TemplateStatusInfo'.
I just want to make sure if it is valid in WCF to declare child object with both attributes- [DataMember] as well as [DataContract].
I am not getting any compile time error.
Please guide.
It is correct what you have done. DataContract is applied to types, and DataMember to properties to specify if it should be included.