I use Visual Studio 2010 and MS SQL Server 2005. I'm new to WCF and I'm trying to learn while developing a small task managing application.
At the moment I have a solution with two console applications inside it - the WCF service - a client connecting to the WCF service to test out my code
The WCF service connects to a db using LINQ to SQL. I've implemented an OperationContract which inserts something into the db behind the WCF service and it works. I've implemented an OperationContract which returns a GUID from the WCF service to the client and that works too.
When I try to retrieve a list of List from the WCF service it fails with the following error:
"An error occurred while receiving the HTTP response to localhost:8000/TaskerTest/Service/operations. 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
InnerException: The underlying connection was closed: An unexpected error occurred on a receive.
My Contracts (the first two work. GetLists is the problem):
[ServiceContract(Namespace = "http://Tasker_Server")]
public interface IOperations {
[OperationContract]
string CreateList(string listName, string text);
[OperationContract]
string UpdateList(int idList, string listName, string text);
[OperationContract]
List<ToDoList> GetLists();
}
The implementation:
public List<ToDoList> GetLists() {
Guid token = OperationContext.Current.IncomingMessageHeaders.GetHeader<Guid>("token", "ns");
int? userID = CheckCache(token);
if (userID != null) {
List<ToDoList> lst = DBAccess.GetListsByUserId(userID.Value);
return lst;
}
else
return null;
}
The DB access code:
public static List<ToDoList> GetListsByUserId(int idCredential) {
TaskerModelDataContext tmdc = new TaskerModelDataContext();
List<ToDoList> lists = tmdc.ToDoLists.Where(entry => entry.id_Credential == idCredential).ToList<ToDoList>();
return lists;
}
And the client code (the WCF service is added as a Service Reference to the client project):
TaskerService.LoginClient test2 = new LoginClient();
string username = "usr1", password = "psw1";
test2.ClientCredentials.UserName.UserName = username;
test2.ClientCredentials.UserName.Password = password;
Guid result = Guid.Empty;
try {
result = test2.CheckCredentials(username, password);
Console.WriteLine("Login OK!");
}
catch (Exception e) {
Console.WriteLine(e.Message);
}
TaskerService.OperationsClient client = new OperationsClient();
using(OperationContextScope contextScope = new OperationContextScope(client.InnerChannel)) {
Guid testToken = result; Console.WriteLine(testToken.ToString());
MessageHeader<Guid> mhg = new MessageHeader<Guid>(testToken);
MessageHeader untyped = mhg.GetUntypedHeader("token", "ns");
OperationContext.Current.OutgoingMessageHeaders.Add(untyped);
client.GetLists();
}
client.Close();
The client fails with the above exception on: client.GetLists();
I can provide any additional details as needed by readers.
UPDATE
I've turned tracing on with
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="sdt"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "SdrConfigExample.e2e" />
</listeners>
</source>
</sources>
</system.diagnostics>
Then I've run Microsoft Service Trace Viewer on the generated log and got the following error:
There was an error while trying to serialize parameter . The InnerException message was 'Type 'System.DelegateSerializationHolder+DelegateEntry' with data contract name 'DelegateSerializationHolder.DelegateEntry:http://schemas.datacontract.org/2004/07/System' is not expected
I've now added [DataContract] to the "ToDoList" class in my dbml file and now I don't receive an exception. I get the correct number of results in my client BUT the contents of each class seem to be empty.
My database classes were auto-generated using a dbml file (LINQ to SQL).
After I've added a [DataContract()] attribute to the ToDoList class in "TaskerModel.designer.cs" (the auto generated file) I didn't receive an exception anymore but the classes I retrieved on the client only had default values for each member.
I then added [DataMember()] attributes to all the members of ToDoList class AND added
[ServiceKnownType(typeof(ToDoList))]
to
[ServiceContract(Namespace = "http://Tasker_Server")]
public interface IOperations {
[OperationContract]
string CreateList(string listName, string text);
[OperationContract]
string UpdateList(int idList, string listName, string text);
[OperationContract]
List<ToDoList> GetLists();
}
And now it works. Don't know if there's an easier way to do it but it works now. If anybody knows of a better way to do this I would appreciate a comment.
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