IEnumerable and WCF - yet again - wcf

OK... I've looked on the web and found two possible solutions to my issue of not being able to return an IEnumerable type in a .Net 4.0 WCF service.
See below link. This is exactly what I'm getting when I am executing the WCF Test Client tool and trying to invoke a method.
https://connect.microsoft.com/wcf/feedback/details/336696/ienumerable-t-serialization-bug
Mind you, to be sure there is nothing wrong with my web service, I am able to return a type of this object for a single record, just not an IEnumerable.
Both solutions that I have tried, shown below do not work for me. I get the same error. This is driving me crazy. I know what the issue is, followed steps to circumvent the issue, but I am still getting the same error.
How can I resolve this?
This is the first solution I tried: Note that I even tried removing the "ToList" and "ToArray" on the last statement in each of the methods because it's implied already.
Interface
[OperationContract]
IList<Priority> GetPriorities();
Method
public IList<Priority> GetPriorities()
{
YeagerTechEntities DbContext = new YeagerTechEntities();
IList<Priority> priority = DbContext.Priorities.Where(p => p.PriorityID > 0).ToList();
CloseConnection(DbContext);
return priority.ToList();
}
This is the second solution I tried:
Interface
[OperationContract]
Priority[] GetPriorities();
Method
public Priority[] GetPriorities()
{
YeagerTechEntities DbContext = new YeagerTechEntities();
Priority[] priority = DbContext.Priorities.Where(p => p.PriorityID > 0).ToArray();
CloseConnection(DbContext);
return priority.ToArray();
}
Here it is with a List instead of an IList which still doesn't work.
Interface
[OperationContract]
List<Priority> GetPriorities();
Method
public List<Priority> GetPriorities()
{
YeagerTechEntities DbContext = new YeagerTechEntities();
List<Priority> priority = DbContext.Priorities.Where(p => p.PriorityID > 0).ToList();
CloseConnection(DbContext);
return priority.ToList();
}
Notice that the below method works fine when retrieving just one object instead of a list.
[OperationContract]
Priority GetPriorityID(Int16 priorityid);
public Priority GetPriorityID(Int16 priorityid)
{
YeagerTechEntities DbContext = new YeagerTechEntities();
Priority priority = null;
var priorityEntity = (from p in DbContext.Priorities
where p.PriorityID == priorityid
select p).FirstOrDefault();
if (priorityEntity != null)
{
priority = new Priority();
priority.PriorityID = priorityEntity.PriorityID;
priority.Description = priorityEntity.Description;
CloseConnection(DbContext);
}
else
{
CloseConnection(DbContext);
throw new Exception("Priority " + priorityid + " not found!");
}
return priority;
}
The entire error msg from the wcf test client for the first method in this post is as follows. What is the resolution in order to be able to return a list of objects?
Failed to invoke the service. Possible causes: The service is offline or inaccessible; the client-side configuration does not match the proxy; the existing proxy is invalid. Refer to the stack trace for more detail. You can try to recover by starting a new proxy, restoring to default configuration, or refreshing the service.
An error occurred while receiving the HTTP response to http://localhost:8732/Design_Time_Addresses/YeagerTechWcfService/YeagerTechWcfService/. 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.
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ClientReliableChannelBinder1.RequestClientReliableChannelBinder1.OnRequest(TRequestChannel channel, Message message, TimeSpan timeout, MaskingMode maskingMode)
at System.ServiceModel.Channels.ClientReliableChannelBinder1.Request(Message message, TimeSpan timeout, MaskingMode maskingMode)
at System.ServiceModel.Channels.ClientReliableChannelBinder1.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Security.SecuritySessionClientSettings`1.SecurityRequestSessionChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at IYeagerTechWcfService.GetPriorities()
at YeagerTechWcfServiceClient.GetPriorities()
Inner Exception:
The underlying connection was closed: An unexpected error occurred on a receive.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
Inner Exception:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
Inner Exception:
An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
I modified my classes (see below), but am still getting the same exact error.
Surely, there must be someone who has tried this before where they get an object back from Entity Framework and want to pass it back as an IEnumerable. I'm very frustrated with this. Please help me out...
Based on my previous post, my classes are exactly the same with the following changes. I tried two methodologies.
Please refer to the first and second scenarios separately.
First scenario for Interface
I tried using just the Customer class and then an IEnumerable declaration of it.
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using YeagerTechModel;
namespace YeagerTechWcfService
{
//[ServiceKnownType(typeof(YeagerTechModel.Customer))]
[ServiceKnownType(typeof(IEnumerable<YeagerTechModel.Customer>))]
[ServiceContract]
public interface IYeagerTechWcfService
{
[OperationContract]
IEnumerable<Customer> GetCustomers();
[OperationContract]
Customer GetCustomerID(Int16 customerid);
It resides in my YeagerTechModel project in the same solution referenced by my web service (the other project in the same solution).
First scenario for Customer object
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace YeagerTechModel
{
[Serializable]
[DataContract]
public partial class Customer
{
public Customer()
{
this.Projects = new HashSet<Project>();
}
[DataMember]
public short CustomerID { get; set; }
[Required]
[StringLength(50)]
[DataType(DataType.EmailAddress)]
[DataMember]
public string Email { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Company { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string FirstName { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string LastName { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Address1 { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Address2 { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string City { get; set; }
[StringLength(2)]
[DataType(DataType.Text)]
[DataMember]
public string State { get; set; }
[StringLength(10)]
[DataType(DataType.Text)]
[RegularExpression(#"^\d{5}(-\d{4})?$")]
[DataMember]
public string Zip { get; set; }
[StringLength(12)]
[DataType(DataType.PhoneNumber)]
public string HomePhone { get; set; }
[StringLength(12)]
[DataType(DataType.PhoneNumber)]
[DataMember]
public string CellPhone { get; set; }
[StringLength(100)]
[DataType(DataType.Url)]
[DataMember]
public string Website { get; set; }
[StringLength(50)]
[DataType(DataType.EmailAddress)]
[DataMember]
public string IMAddress { get; set; }
[DataMember]
public System.DateTime CreatedDate { get; set; }
[DataMember]
public Nullable<System.DateTime> UpdatedDate { get; set; }
public virtual ICollection<Project> Projects { get; set; }
}
Second scenario for interface:
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using YeagerTechModel;
namespace YeagerTechWcfService
{
[ServiceContract]
public interface IYeagerTechWcfService
{
[OperationContract]
IEnumerable<Customer> GetCustomers();
[OperationContract]
Customer GetCustomerID(Int16 customerid);
Second scenario for Customer object
I have tried using just the Customer class and then an IEnumerable declaration of it at the bottom of this class.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace YeagerTechModel
{
[KnownTypeAttribute("KnownTypes")]
[Serializable]
[DataContract]
public partial class Customer
{
public Customer()
{
this.Projects = new HashSet<Project>();
}
[DataMember]
public short CustomerID { get; set; }
[Required]
[StringLength(50)]
[DataType(DataType.EmailAddress)]
[DataMember]
public string Email { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Company { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string FirstName { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string LastName { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Address1 { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Address2 { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string City { get; set; }
[StringLength(2)]
[DataType(DataType.Text)]
[DataMember]
public string State { get; set; }
[StringLength(10)]
[DataType(DataType.Text)]
[RegularExpression(#"^\d{5}(-\d{4})?$")]
[DataMember]
public string Zip { get; set; }
[StringLength(12)]
[DataType(DataType.PhoneNumber)]
public string HomePhone { get; set; }
[StringLength(12)]
[DataType(DataType.PhoneNumber)]
[DataMember]
public string CellPhone { get; set; }
[StringLength(100)]
[DataType(DataType.Url)]
[DataMember]
public string Website { get; set; }
[StringLength(50)]
[DataType(DataType.EmailAddress)]
[DataMember]
public string IMAddress { get; set; }
[DataMember]
public System.DateTime CreatedDate { get; set; }
[DataMember]
public Nullable<System.DateTime> UpdatedDate { get; set; }
public virtual ICollection<Project> Projects { get; set; }
static Type[] KnownTypes()
{
return new Type[] { typeof(IEnumerable<Customer>) };
}
}
I tried:
return customer;
return customer.ToList();
return customer.ToArray();
public IEnumerable<Customer> GetCustomers()
{
YeagerTechEntities DbContext = new YeagerTechEntities();
IEnumerable<Customer> customer = DbContext.Customers.Where(p => p.CustomerID > 0);
CloseConnection(DbContext);
return customer;
}
The problem seems to be a serialization issue when trying to pass back the Customer object which is part of an Entity Framework model. There has to be a documented way of passing back an object of this type which is derived from an Entity Framework model.
Where is it????
Here is the latest of what I tried and am still getting the same exact error....
namespace YeagerTechWcfService
{
[ServiceContract]
public interface IYeagerTechWcfService
{
[OperationContract]
List<Customer> GetCustomers();
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace YeagerTechModel
{
[Serializable]
[DataContract]
public partial class Customer
{
public Customer()
{
this.Projects = new HashSet<Project>();
}
[DataMember]
public short CustomerID { get; set; }
[Required]
[StringLength(50)]
[DataType(DataType.EmailAddress)]
[DataMember]
public string Email { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Company { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string FirstName { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string LastName { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Address1 { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string Address2 { get; set; }
[StringLength(50)]
[DataType(DataType.Text)]
[DataMember]
public string City { get; set; }
[StringLength(2)]
[DataType(DataType.Text)]
[DataMember]
public string State { get; set; }
[StringLength(10)]
[DataType(DataType.Text)]
[RegularExpression(#"^\d{5}(-\d{4})?$")]
[DataMember]
public string Zip { get; set; }
[StringLength(12)]
[DataType(DataType.PhoneNumber)]
public string HomePhone { get; set; }
[StringLength(12)]
[DataType(DataType.PhoneNumber)]
[DataMember]
public string CellPhone { get; set; }
[StringLength(100)]
[DataType(DataType.Url)]
[DataMember]
public string Website { get; set; }
[StringLength(50)]
[DataType(DataType.EmailAddress)]
[DataMember]
public string IMAddress { get; set; }
[DataMember]
public System.DateTime CreatedDate { get; set; }
[DataMember]
public Nullable<System.DateTime> UpdatedDate { get; set; }
public virtual ICollection<Project> Projects { get; set; }
}
public List<Customer> GetCustomers()
{
YeagerTechEntities DbContext = new YeagerTechEntities();
List<Customer> customer = DbContext.Customers.Where(p => p.CustomerID > 0).ToList();
return customer.ToList();
}

The answer was as simple as setting a property to false before making my EF call to the database.
DbContext.Configuration.ProxyCreationEnabled = false;
EF automatically generates a proxy class. Dynamic Proxies – They don’t play nice over the wire – Turn these off (ContextOptions.ProxyCreationEnabled == false).

Related

System.Data.SqlTypes.SqlNullValueException after I migrated to net5.0 from netcore 3.1

I'm getting this error on one of my fetch services
System.Data.SqlTypes.SqlNullValueException
HResult=0x80131931
Message=Data is Null. This method or property cannot be called on Null
values. Source=Microsoft.Data.SqlClient StackTrace: at
Microsoft.Data.SqlClient.SqlBuffer.get_Int32() at
Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable1.Enumerator.MoveNext() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at
Infrastructure.Data.Repository.Base.EfRepository1.List(ISpecification1
spec) in C:\mydir\master\src\DataTier\SMYLS.Data.Respository\Repository\Base\EfRepository.cs:line
88 at
ApplicationCore.Services.Items.ItemService.SearchItems(ItemSearchDataModel
searchModel) in C:\mydir\master\src\ServiceTier\SMYLS.Services\Items\ItemService.cs:line 202 at
Web.Controllers.Api.InvoiceController.GetItemList(ItemSearchDataModel
searchModel) in C:\mydir\master\src\Web\Controllers\Api\InvoiceController.cs:line 322 at
Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper
mapper, ObjectMethodExecutor executor, Object controller, Object[]
arguments) at
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State&
next, Scope& scope, Object& state, Boolean& isCompleted) at
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
This exception was originally thrown at this call stack:
[External Code]
Infrastructure.Data.Repository.Base.EfRepository.List(ApplicationCore.Interfaces.Repository.ISpecification)
in EfRepository.cs
ApplicationCore.Services.Items.ItemService.SearchItems(ApplicationCore.DTOs.Items.ItemSearchDataModel)
in ItemService.cs
Web.Controllers.Api.InvoiceController.GetItemList(ApplicationCore.DTOs.Items.ItemSearchDataModel)
in InvoiceController.cs
[External Code]
This happened after I migrated to net5.0. If I run my netcore3.1, there's no problem at all.
I've researched this error and mostly found errors that were caused when your model is expecting a required property but the database returns a null value. I checked my models but they seem fine (they work on 3.1 without any issue)
these are my model properties
public string Name { get; set; }
public string Description { get; set; }
public decimal Cost { get; set; }
public bool Active { get; set; }
public DateTime UpdatedDateUtc { get; set; }
public int UpdatedBy { get; set; }
public int ClinicId { get; set; }
public int? ServiceGroupId {get;set;}
public string ShortCode { get; set; }
public int? IndustryCodeId { get; set; }
public bool Subscription { get; set; }
public bool BlockBill { get; set; }
public decimal? DiscountPercentage { get; set; }
#nullable enable
public string? SubscriptionType { get; set; }
public virtual Clinic Clinic { get; set; }
public virtual SiteUser UpdatedByNavigation { get; set; }
public virtual ServiceGroup ServiceGroup { get; set; }
public virtual IndustryCode IndustryCode { get; set; }
public virtual ICollection<InvoiceItem> InvoiceItem { get; set; }
public virtual ICollection<DoctorPricing> DoctorPricing { get; set; }
public virtual ICollection<DoctorPricingHistory> DoctorPricingHistory { get; set; }
And these are my sample data from db
Still can't figure out why this is not working in net5.0
On quick glance, I’d suspect the ServiceGroup property, which has a return type of ServiceGroup, but corresponds to a nullable ServiceGroupId column in the database. I’d expect that the return type of the property would need to be ServiceGroup? to allow for nulls.
I’m not certain why that wasn’t throwing an exception in ASP.NET Core 3.x. My suspicion is that ASP.NET Core 5.x does a better job of enforcing nullability of reference types at runtime, thus raising awareness of a long-standing discrepancy in the data model.

I am using complex type as datamember of a datacontract

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; }
}

WCF Client Proxy object Creation Issue

I am using WCF service library where i return list. Then Create service reference in MVC-4 application. But Cant create proxy client object. Also i did configure service reference and set Collection type to System.Collections.Generic.List but still get problem.
Mu Code In Service Library is :
[ServiceContract]
public interface IStudent
{
// [WebGet(ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
List<Studentdata> GetData();
}
[DataContract()]
public class Studentdata
{
[DataMember()]
public string StudentId { get; set; }
[DataMember()]
public string FirstName { get; set; }
[DataMember()]
public string LastName { get; set; }
[DataMember()]
public Nullable<int> Age { get; set; }
[DataMember()]
public string Gender { get; set; }
[DataMember()]
public string Batch { get; set; }
[DataMember()]
public string Address { get; set; }
[DataMember()]
public string Class { get; set; }
[DataMember()]
public string School { get; set; }
[DataMember()]
public string Domicile { get; set; }
}
StudentDataAccess obj = new StudentDataAccess();
public List<Studentdata> GetData()
{
var query = obj.getalldata().ToList();
List<Studentdata> obj1 = query.ToList().ConvertAll(new Converter<BtDataLayer.Student, Studentdata>(Converter.ConvertEntStudentToWcfStudent));
return obj1;
}
StudentDataAccess obj = new StudentDataAccess();
is entity project class object
Please help me out for the same. Thanks in advance.

ADO.NET Entity Framework on Vs2012 + WCF = Error

First of all, thanks for reading my question.
I am developing a solution using VS 2012 using ADO.NET Entity Framework (5 i think, the latest version). All is working fine until I introduce a WCF service as a Business Layer (this is an assignment for school, I cannot scrap WCF from Business Layer).
The issue is that when I request data from the database. When I have a method that returns a string from the database, it works just fine (since its a primitive). But when it returns an Entity object (Such as Account), it all goes to hell.
Exception: (Yeah, its very vague).
An error occurred while receiving the HTTP response to http://localhost:8733/Services/AccountsManager. 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.
What I tried: I tried modifying the Entites.tt file to add the [DataContract] [DataMember] Attribute. This is because in the older versions of EF, it seemed to be doing it on its own. But I do not know if this is neccessary since it allows me to compile and does not complain that it is not serializable.
This is how it looks at first:
namespace CommonLayer
{
using System;
using System.Collections.Generic;
public partial class Account
{
public Account()
{
this.Transactions = new HashSet<Transaction>();
this.Transactions1 = new HashSet<Transaction>();
}
public System.Guid ID { get; set; }
public int Type { get; set; }
public string Name { get; set; }
public int Currency { get; set; }
public decimal Balance { get; set; }
public System.DateTime DateOpened { get; set; }
public Nullable<int> Duration { get; set; }
public string UserName { get; set; }
public virtual AccountType AccountType { get; set; }
public virtual Currency Currency1 { get; set; }
public virtual User User { get; set; }
public virtual ICollection<Transaction> Transactions { get; set; }
public virtual ICollection<Transaction> Transactions1 { get; set; }
}
}
How it looks after modification:
namespace CommonLayer
{
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
[DataContract] public partial class Account
{
public Account()
{
this.Transactions = new HashSet<Transaction>();
this.Transactions1 = new HashSet<Transaction>();
}
[DataMember] public System.Guid ID { get; set; }
[DataMember] public int Type { get; set; }
[DataMember] public string Name { get; set; }
[DataMember] public int Currency { get; set; }
[DataMember] public decimal Balance { get; set; }
[DataMember] public System.DateTime DateOpened { get; set; }
[DataMember] public Nullable<int> Duration { get; set; }
[DataMember] public string UserName { get; set; }
public virtual AccountType AccountType { get; set; }
public virtual Currency Currency1 { get; set; }
public virtual User User { get; set; }
public virtual ICollection<Transaction> Transactions { get; set; }
public virtual ICollection<Transaction> Transactions1 { get; set; }
}
}
Any pointers are greatly appreciated.
My WCF Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
namespace BusinessLayer
{
[ServiceContract]
interface IAccountsManager
{
[OperationContract]
List<CommonLayer.Account> GetAccounts(String UserName);
[OperationContract]
String GetData();
[OperationContract]
CommonLayer.Account GetAccount(String UserName);
}
class AccountsManager: IAccountsManager, IDisposable
{
public List<CommonLayer.Account> GetAccounts(String UserName)
{
return DataLayer.AccountsRepository.Instance.GetAccountList(UserName).ToList();
}
public String GetData()
{
CommonLayer.Account acc = this.GetAccounts("test").FirstOrDefault();
return acc.DateOpened.ToString();
}
public CommonLayer.Account GetAccount(String UserName)
{
return this.GetAccounts(UserName).FirstOrDefault();
}
public void Dispose()
{
DataLayer.AccountsRepository.Reset();
}
}
}
You need to use a DTO (Data Transfer Object) and map from your EF object to your DTO.
So the service might accept an object called MyDto looking like:
[DataContract]
public class MyDto {
[DataMember]
public int Id {get;set;}
}
and a static mapping class with methods
public static MyEntity Map(MyDto dto) {
return new MyEntity { Id = dto.Id };
}
public static MyDto Map(MyEntity entity) {
return new MyDto { Id = entity.Id };
}
You can then map as required so that the service can use the DTO and Entity Framework can use the Entity.
It seems that when the EF class has Navigation properties (like ICollection<Transaction> Transactions in your class) it will fails when being transferred over WCF.
After many searches I could not find any solution except mapping an EF class into equivalent DTO class that is exactly the same as the EF class except the Navigation propertis and the constructor (i.e. I have stripped all virtual propertis (like ICollection ones) and the ctor from the EF class and have created from that a new class called the same as my EF class plus Dto suffix (e.g. CustomerDto).
I've used AutoMapper to automatically map an EF object into Dto-equivalent one. E.g:
var customer = getCustomer(cid);
var customerDto = Mapper.Map<CustomerDto>(customer);
return customerDto;
My WCF contract includes
[OperationContract]
CustomerDto getCustomerData(int cid);
In addition I needed to do one time initialization of the Mapper. I've done it within Global.asax as follows:
Mapper.CreateMap<Customer, CustomerDto>();
What I have done is changed my Entities.Edmx file. Firstly, I deleted all (2) ".tt" files. Then i changed Code Generation Strategy from None to Default. This seemed to solve all my problems.

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