Newbie, please bear with me as I just started yesterday with WCF.
I am using Northwind for the data and only added Customers, Orders, Order Details and Products to the model, so nothing fancy.
When I launch the application and invoke Test, and set a breakpoint, the value for products is there and it completes without error. If I then try to invoke GetMaxQuantityByOrderID(10248), I get the error listed at bottom. Why would Test() work and the same method WITHIN Test() NOT work? I even added another (Test1(), exact same as Test except it returns string: x.ProductName, which correctly displays Queso Cabrales). It seems odd that a method that is being called within another works, but calling it directly causes an exception.
Another issue I have is that the IEnumerable GetOrders() works only if I add .ToList(). Without it (or with .AsEnumerable()), I get an error (The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.), even though lazy loading is set to False. What is the logic behind this?
IServiceTest.cs
using System.Collections.Generic;
using System.ServiceModel;
namespace WcfTestServiceLibrary
{
[ServiceContract]
public interface IServiceTest
{
[OperationContract]
IEnumerable<Orders> GetOrders();
[OperationContract]
IEnumerable<Customers> GetCustomers();
[OperationContract]
Customers GetCustomerByID(string customerID);
[OperationContract]
Orders GetOrderByID(int id);
[OperationContract]
IEnumerable<Order_Details> GetOrderDetailsByOrderID(int id);
[OperationContract]
Order_Details GetMaxQuantityByOrderID(int id);
[OperationContract]
void Test();
}
}
ServiceTest.cs
using System.Collections.Generic;
using System.Linq;
namespace WcfTestServiceLibrary
{
public class ServiceTest : IServiceTest
{
public IEnumerable<Orders> GetOrders()
{
using (var ctx = new NWEntities())
{
return (from o in ctx.Orders.Include("Order_Details.Products").Include("Customers")
select o).ToList();
}
}
public IEnumerable<Customers> GetCustomers()
{
using (var ctx = new NWEntities())
{
return (from c in ctx.Customers
select c);
}
}
public Customers GetCustomerByID(string customerID)
{
return (from c in GetCustomers()
where c.CustomerID == customerID
select c).FirstOrDefault();
}
public Orders GetOrderByID(int id)
{
IEnumerable<Orders> orders = GetOrders();
return (from o in orders
where o.OrderID == id
select o).FirstOrDefault();
}
public IEnumerable<Order_Details> GetOrderDetailsByOrderID(int id)
{
return GetOrderByID(id).Order_Details;
}
public Order_Details GetMaxQuantityByOrderID(int id)
{
Orders order = GetOrderByID(id);
return order == null ? null : order.Order_Details.OrderByDescending(x => x.Quantity).FirstOrDefault();
}
public void Test()
{
const int orderID = 10248;
var oq = GetMaxQuantityByOrderID(orderID);
var x = oq.Products;
}
}
}
Error:
An error occurred while receiving the HTTP response to http://localhost:8732/Design_Time_Addresses/WcfTestServiceLibrary/Service1/. 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.ClientReliableChannelBinder`1.RequestClientReliableChannelBinder`1.OnRequest(TRequestChannel channel, Message message, TimeSpan timeout, MaskingMode maskingMode)
at System.ServiceModel.Channels.ClientReliableChannelBinder`1.Request(Message message, TimeSpan timeout, MaskingMode maskingMode)
at System.ServiceModel.Channels.ClientReliableChannelBinder`1.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 IServiceTest.GetMaxQuantityByOrderID(Int32 id)
at ServiceTestClient.GetMaxQuantityByOrderID(Int32 id)
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 had a very similar issue as you did. I found out that the Entity Framework proxy that wraps around your POCO classes is by default serialized by the WCF serializer, which cannot be deserialized on the client side since the client is not aware of the EF proxy wrapper. There were two solutions that I found. The first is to set ContextOptions.ProxyCreationEnabled to false. This prevents the EF from creating proxies for your POCO objects. The second was to instruct the WCF DataContractSerializer on the server side to use the ProxyDataContractResolver to serialize as just the POCO.
The second option can be found at http://msdn.microsoft.com/en-us/library/ee705457.aspx. Since I have just discovered these solutions I can't say which I would recommend as a general practice, although I lean to the latter, since the EF queries may be re-used by other callers from time to time that may want the objects returned with the appropriate EF proxies. Anyhow I know that's late to this question, but I hope that helps others who come across this issue.
Its the .Inculde in your LINQ-Statement.
I believe the reason for this is the basicaly resulting infinite datastructure pointing to and from "one" side to the "many" side of your relationship.
This you can observe by unfolding your datastructure, setting a breakpoint at the result of your .Include query statement in the debugger...
Observation: Orders --> many Products, each product--> Order--> many Products and so forth
I guess wcf runns into that and gets cought up in that.
To break this chain of, you can simply avoid the pointing back in your data transfer object by adding the ignoreDataMember Attribute
In the Many-Side of your relationship... In your case the Product....
[IgnoreDataMember] public Order OrderFatherElement { get; set; }
This way WCF will stop the serializingattempt when reaching that childnode
@microsoft.... some potential for a fix?
Greets,
Kieredin Garbaa
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With