Reputation: 19903
In a solution, I added a "WCF Service Library". No problem with the default method. I added one :
In the interface :
[ServiceContract]
public interface ISecurityAccessService
{
[OperationContract]
string GetData(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
[OperationContract]
CompositeUser ListUser();
}
[DataContract]
public class CompositeUser
{
List<User> _listUser = new List<User>();
[DataMember]
public List<User> ListUser
{
get { return _listUser; }
set { _listUser = value; }
}
}
The interface implementation, the dataaccess iw working, I tested the DataService and no problem.
public class SecurityAccessService : ISecurityAccessService
{
public CompositeUser ListUser()
{
DataAccess.DataService service = new DataAccess.DataService();
CompositeUser compositeUser = new CompositeUser();
compositeUser.ListUser = service.ListUser();
return compositeUser;
}
}
When I execute and try to invoke, I receive this error message : *An error occurred while receiving the HTTP response to http://localhost:8732/Design_Time_Addresses/WcfServiceLibrary/ISecurityAccessService/. 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.*
The App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service name="WcfServiceLibrary.SecurityAccessService">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8732/Design_Time_Addresses/WcfServiceLibrary/ISecurityAccessService/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address ="" binding="wsHttpBinding" contract="WcfServiceLibrary.ISecurityAccessService">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Update 1
I made a working sample with database access. I just don't understand something in the "PersonService" class, why I have to make this loop. Solution is welcome.
Download 40ko .rar full example
Upvotes: 1
Views: 1072
Reputation: 16224
I faced this problem again today. A long time ago I had the same problem, but I had forgotten the cause and it took me some time to sort it out toady.
In my case, it was a looping serialization problem. One table has a column which is a foreign key to another column in the same table. So all I had to do was to click the work surface of the dbml file and change the Serialization Mode to Unidirectional.
If yours is a Linq to Sql situation, and the error message is the one shown above, you might want to check whether it is the same cause as mine.
Upvotes: 0
Reputation: 32936
your User
class needs to be marked with the DataContract
attribute and its methods with the DataMember
attribute. It may also need to be marked as a KnownType
in the CompositeUser
class so that it is included in the types for the service. You can do that like so:
[DataContract]
[KnownType(typeof(User))]
public class CompositeUser
{
...
}
you'll be able to tell what the issue is from the logs. Either you'll get a 'cannot be serialized' message, in which case you need to add the [DataContract]
attribute or it will be 'type was not expected' in which case you'll also need to add the [KnownType]
attribute
If you enable tracing in your service you'll be able to get more details of what the problem was. Add something like this in the config file:
<configuration>
<system.diagnostics>
<trace autoflush="true"/>
<sources>
<source name="System.ServiceModel" switchValue="Verbose">
<listeners>
<add name="sdt" type="System.Diagnostics.XmlWriterTraceListener" initializeData="D:\wcfLog.svcLog"/>
</listeners>
</source>
</sources>
</system.diagnostics>
</configuration>
also setting <serviceDebug includeExceptionDetailInFaults="True" />
will allow more detail about the error to be returned in the service exception which might also help.
EDIT
From the comments below it seems the User
class is a Linq to SQL generated class. I don't think you should be sending this class across the wire. WCF deals with messages not in serializing types with behaviour, so you should create a DTO which represents the data in your User
class that will be needed on the client and send this DTO out from the service contract. Even if you do send the User class as it is, when it gets to the client it won't have the context to still be connected to the DB.
Upvotes: 2