object collision with wcf - c#

Could someone explain why this is happening, I have a C# backend that I'm connecting to via WCF. In the back end, i have two classes in the same namespace that have two properties that have the same name. These classes are used in a separate object. The types of the properties are different, one is a string and one is an object but there seems to be some sort of collision when deserializing the object?
It's returning this random error when I call to return the object.
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.
Here are the classes, the property causing the problem is BCIssued
public class Activities
{
public string ApplicationReceived { get; set; }
public string PIMGranted { get; set; }
public Bcgranted[] BCGranted { get; set; }
public object CCCGranted { get; set; }
// public object BCIssued { get; set; }
public object CCCIssued { get; set; }
}
public class CCC
{
public string BCIssued { get; set; }
public string FinalIns { get; set; }
public string LapsedMonths { get; set; }
public object WorkStarted { get; set; }
public object Notified { get; set; }
public object Lapsed { get; set; }
public object Extension { get; set; }
}

Thanks to Rene's post about WCF logging, i was able to turn on logging and found the error on the server side
Type 'Newtonsoft.Json.Linq.JToken' is a recursive collection data contract
which is not supported. Consider modifying the definition of collection
'Newtonsoft.Json.Linq.JToken' to remove references to itself.

Related

Issue for nested child list for Swagger

I'm developing a web api with .NET Core
I use Swagger for API documentation
For an endpoint i have a return object like this
public class TaxonomyNode
{
public int Id { get; set; }
public string Key { get; set; }
public string Title { get; set; }
public string ParentKey { get; set; }
public bool HasAssociations { get; set; }
public int Level { get; set; }
public IEnumerable<TaxonomyNode> Children { get; set; }
}
When i launch my web application on swagger page and expland my API endpoint swagger give me this error
Resolver error at paths./api/Taxonomies/{idTaxonomyItemDbMaster}/GetNodes.get.responses.200.content.application/json.schema.properties.children.items.$ref
Could not resolve reference:
Resolver error at paths./api/Taxonomies/{idTaxonomyItemDbMaster}/GetNodes.get.responses.200.content.text/json.schema.properties.children.items.$ref
Could not resolve reference:
Resolver error at paths./api/Taxonomies/{idTaxonomyItemDbMaster}/GetNodes.get.responses.200.content.text/plain.schema.properties.children.items.$ref
Could not resolve reference:
the problem is
public IEnumerable Children { get; set; }
i think that swagger go into an overflow when generating documentation for response
How can i prevent this?
thanks
Your model of type TaxonomyNode is refering to the type TaxonomyNode as a property.
Therefore it will cause a infinite loop if you wish to serialize this type.
It is the cause of the error you are getting

COMException when Service Fabric stateless service returns POCO object graph

I have a stateless service that loads and returns an array of entity objects (POCO using EF). Lazy loading and proxy creation is disabled.
Everything is works just fine as long as I only return a single level graph:
var devices = context.Devices.Where(d => d.ParentHost_Id == hostId);
return Task.FromResult(devices.ToArray());
However, if I want to include another level, things go south in bad way:
var devices = context.Devices.Where(d => d.ParentHost_Id == hostId).Include(d => d.ConnectedDevices);
return Task.FromResult(devices.ToArray());
In this case, my code will load and return the requested objects without any trouble, but somewhere upstream in the call chain Service Fabric throws a COMException which it then handles by calling my service again. This results in a new COMExcetion, and it keeps doing this until I stop it.
{System.Runtime.InteropServices.COMException (0x80071C4C): Undantag från HRESULT: 0x80071C4C
vid Microsoft.ServiceFabric.Services.Communication.FabricTransport.Common.NativeServiceCommunication.IFabricServiceCommunicationClient.EndRequest(IFabricAsyncOperationContext context)
vid Microsoft.ServiceFabric.Services.Communication.FabricTransport.Client.NativeServiceCommunicationClient.EndRequest(IFabricAsyncOperationContext context)}
The Devices class is generated by EF and looks like this:
public partial class Devices
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Devices()
{
this.LogValues = new HashSet<LogValues>();
}
public long Id { get; set; }
public int DeviceId { get; set; }
public int Type { get; set; }
public string Property { get; set; }
public string Name { get; set; }
public Nullable<long> ParentHost_Id { get; set; }
public virtual Hosts Hosts { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<LogValues> LogValues { get; set; }
public virtual ConnectedDevices ConnectedDevices { get; set; }
}
Any ideas on why this happens would be appreciated!
Apparently, the problem was that my object graph contained a circular reference (the ConnectedDevice had a reference to Device). I removed it from the EF model and everything is now working as expected.

SignalR Client - IHubProxy.On<> and Invoke<> accepting an interface

I am building a windows service that will act as a client to an existing site that's employing SignalR.
I have IHubProxy.On<> and IHubProxy.Invoke methods working when passing around concrete classes.
For example, this works:
hubProxy.On<MigrationRequest>("iSWindowsServiceRequest", request =>
MigrateData.Invoke(request));
And the MigrationRequest looks like this:
public class MigrationRequest : IISWindowsServiceRequest
{
public MigrateWhat What { get; set; }
public MigrationFor For { get; set; }
public Guid EntityFor_Id { get; set; }
}
Now, If i try this:
hubProxy.On<IISWindowsServiceRequest>("iSWindowsServiceRequest", request =>
Handshake.HandleRequest(request));
my request is never picked up.
what I was hoping to achieve was creating single pub-sub methods, rather than one for each concrete class that this service would accept.
Is it possible to pass in an interface into the On<>() methods?
The same goes for the Invoke<>() - if the object I am passing contains any properties that are of an interface, the call never makes it.
so this will not work:
public class ISWindowsServiceResponse
{
public IISWindowsServiceRequest OriginalRequest { get; set; }
public bool Success { get; set; }
public string Message { get; set; }
}
but this will
public class ISWindowsServiceResponse
{
public MigrationRequest OriginalRequest { get; set; }
public bool Success { get; set; }
public string Message { get; set; }
}
Where I work, we spent a lot of time trying to figure out a way to get SignalR hubs to serialize interfaces. In the end, we wound up having to extract real objects (real classes and structs, not behind an interface) to send over the wire. There is no way to tell SignalR how to serialize an interface.

Serializing a List of Interfaces using the DataContractSerializer

I have a class and there are some nested classes within it. I serialize it and send it to the wcf service using a method with no problems. Here's the class;
public class ComputerDTO
{
[DataMember]
public ComputerTypeDTO Type { get; set; }
[DataMember]
public string ComputerName { get; set; }
[DataMember]
public MonitorDTO Monitor { get; set; }
}
Here's the method;
public void Check()
{
Computer c = new Computer();
ISystemInfoOperations cli = GetServiceClient();
Mapper.CreateMap<Monitor, MonitorDTO>();
Mapper.CreateMap<IHardwarePart, IHardwarePartDTO>();
Mapper.CreateMap<Computer, ComputerDTO>()
.ForMember(s => s.Hardware, m => m.MapFrom(q => Mapper.Map<List<IHardwarePart>, List<IHardwarePartDTO>>(q.Hardware)));
Mapper.AssertConfigurationIsValid();
ComputerDTO dto = Mapper.Map<Computer, ComputerDTO>(c);
string sendComputerInfo = cli.SendComputerInfo(dto);
}
But I have also a list of interface to be sent. So I change the code like below and get an error.
public class ComputerDTO
{
[DataMember]
public ComputerTypeDTO Type { get; set; }
[DataMember]
public string ComputerName { get; set; }
[DataMember]
public MonitorDTO Monitor { get; set; }
[DataMember]
public List<IHardwarePartDTO> Hardware { get; set; }
}
public interface IHardwarePartDTO
{
[DataMember]
string Name { get; set; }
[DataMember]
HardwarePartTypeDTO PartType { get; set; }
}
Inside of hardware is getting filled in the project. But if I try to send it, I get this famous error :
Type
'Proxy'
with data contract name
'_x0030__Culture_x003D_neutral_PublicKeyToken_x003D_null_x003E_:http://schemas.datacontract.org/2004/07/Proxy%3CSystemInfo.DTO.IHardwarePartDTO_SystemInfo.DTO_Version=1.0.0'
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.
The DataContractSerializer needs to know about the concrete types that is might return. An interface cannot be serialized, as it cannot be deserialized (how can you create an instance of an interface without a concrete implementation).
The simple resolution is to add KnownTypes attribute like below:
[KnownType(typeof(your hardware dto concrete type here))]
public class ComputerDTO
{
[DataMember]
public ComputerTypeDTO Type { get; set; }
[DataMember]
public string ComputerName { get; set; }
[DataMember]
public MonitorDTO Monitor { get; set; }
[DataMember]
public List<IHardwarePartDTO> Hardware { get; set; }
}
You can add as many known type attributes as you like.
Slightly more complex is the ServiceKnownTypes attribute. This is very similar but you would add it to your service class.
Other than that you can use a data contract resolver - but this is very complicated and would take a while to explain.
EDIT: 18/02/2013 15:11
You may also need to look at you Automapper as its currently going to create proxies in your Hardware list - and proxies cannot be serialized. You need to tell automapper what to serialize them to - for example:
Mapper.CreateMap<Monitor, MonitorDTO>();
Mapper.CreateMap<Monitor, IHardwarePartDTO>().As<MonitorDTO>();
Mapper.CreateMap<Audio, AudioDTO>();
Mapper.CreateMap<Audio, IHardwarePartDTO>().As<AudioDTO>();
Mapper.CreateMap<CDROMDrive, CDROMDriveDTO>();
Mapper.CreateMap<CDROMDrive, IHardwarePartDTO>().As<CDROMDriveDTO>();
//you need entries like these for everythin that implements IHardwarePartDTO
This way automapper knows what it needs to create.

sending complex structures via WCF RIA services

I'm having a trouble with sending complex structure.
I have two classes. I send through ria services a list of messages, every message contains a list of classes describing people involved in conversation - MailInfo
public class Message
{
[Key]
public string Id { get; set;}
public string ParentId { get; set; }
public List<MailInfo> Email { get; set; }
}
public class MailInfo
{
[Key]
public string Address { get; set; }
}
To send a List of Message I use
[Query]
public IQueryable<Message> GetMessage() {return null;}
[Query]
public IQueryable<MailInfo> GetMailInfo() { return null; }
and eventually
[Invoke]
public List<Message> SomeMethod ()
{ return listofMessages; }
But I cannot have access to Email field of Message. Can I do something? Or just such complex structures are not supported in silverlight yet?
Actually I found out that you cannot send such class object properly. The point is that RIA services disable a setter for non-POCO objects of the class you are going to send.
You can see it in generated code .Web.g.cs.
The only beautiful solution I found out - is to send List EMail as a serialized string. So after that all of your fields in entity would be POCO and you finally get the object.
public class Message
{
[Key]
public string Id { get; set;}
public string ParentId { get; set; }
[Include]
public List<MailInfo> Email { get; set; }
}
public class MailInfo
{
[Key]
public string Address { get; set; }
}
Try using the attribute. If it is linked in your database it should get these for you.

Categories