"Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host - wcf

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.

In my case the problem was that there was a readonly property. Add an empty set(); and solve my problem.

I had the same error when calling my WCF restfull service. The problem seemed to be caused by the datatype I was returning as a response.
I returned JSON and my response-object had a variable with datatype DateTime. When I replaced the DateTime with string, the problem got away and a proper response returned. Probably it will help someone who rans into the same problem.
Replace:
[DataMember]
public DateTime dateFrom {get;set;}
with this
[DataMember]
public string dateFrom {get;set;}

Related

NLog to WCF. Closing client throws SocketException on Server

I've been struggling with this problem for a whole day and do not know how to fix it. I have tried various things to resolve the issue but I am at a loss.
I have a project where I am attempting to use the LogReceiverServer from NLog to send and receive messages between 2 PCs. I followed this example here. Everything actually works fine, my WCF service starts up correctly, my client starts up correctly, even the sending of the message to log from client to server works. But, when I shut the client down, I get SocketExceptions thrown by the server for each message that was transmitted. I know this is due to the channel not being closed properly by the client. I cannot find where I must close the channel to prevent the exceptions being thrown by my server. I have read that to manually close the channel I must use
Channel.Close();
would that be correct and where would I put that?
I want to prevent these SocketExceptions. I have found this, but it does not seem to be the correct thing to do. Correct me if I am wrong, but would the solution not use the same principles?
Unless of course I am understanding this completely wrong...
Everything is done using the config files (App.Config and NLog.Config).
Here is my LogReceiverService Target from NLog.config:
<target xsi:type="LogReceiverService"
name="logreceiver"
endpointConfigurationName="LogReceiverClient"
endpointAddress="net.tcp://server:8888/NLogServices/LogReceiverServer/logreceiverserver" />
Here is my endpoint from my app.config:
<endpoint address="net.tcp://server:8888/NLogServices/LogReceiverServer/logreceiverserver"
binding="netTcpBinding"
bindingConfiguration="LogReceiverClient"
contract="NLog.LogReceiverService.ILogReceiverClient"
name="LogReceiverClient" />
Any help or advise would greatly be appreciated.
EDIT: Extended on problem description
OK, So first, here is the Service on my host pretty much as I got it from here:
/// <summary>
/// Log service server object that logs messages.
/// </summary>
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
public class LogReceiverServer : ILogReceiverServer
{
public void ProcessLogMessages(NLogEvents nevents)
{
var events = nevents.ToEventInfo("Client.");
foreach (var ev in events)
{
var logger = LogManager.GetLogger(ev.LoggerName);
logger.Log(ev);
}
}
}
I then created this class, where I inherit from LogReceiverWebServiceTarget and override protected virtual WcfLogReceiverClient CreateWcfLogReceiverClient(); method. It is exactly the same as is found on GitHub here, except that I registered on the ProcessLogMessagesCompleted event where I close the 'client':
[Target("wcftarget")]
public class WcfTarget : LogReceiverWebServiceTarget
{
protected override WcfLogReceiverClient CreateWcfLogReceiverClient()
{
WcfLogReceiverClient client;
if (string.IsNullOrEmpty(EndpointConfigurationName))
{
// endpoint not specified - use BasicHttpBinding
Binding binding;
if (UseBinaryEncoding)
{
binding = new CustomBinding(new BinaryMessageEncodingBindingElement(), new HttpTransportBindingElement());
}
else
{
binding = new BasicHttpBinding();
}
client = new WcfLogReceiverClient(binding, new EndpointAddress(EndpointAddress));
}
else
{
client = new WcfLogReceiverClient(EndpointConfigurationName, new EndpointAddress(EndpointAddress));
/*commenting this out causes multiple socket exceptions on host*/
client.ProcessLogMessagesCompleted += client_ProcessLogMessagesCompleted;
}
return client;
}
private void client_ProcessLogMessagesCompleted(object sender, AsyncCompletedEventArgs e)
{
WcfLogReceiverClient client = sender as WcfLogReceiverClient;
if (client.State == CommunicationState.Opened)
{
(sender as WcfLogReceiverClient).Close();
}
}
}
The Logger in NLog.config is:
<logger name="*" writeTo="logreceiver" minlevel="Info" />
So then if I try to log like this:
class Program
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private static void Main(string[] args)
{
logger.Info("foo");
}
}
my host gives prints this to Debug:
A first chance exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
A first chance exception of type 'System.ServiceModel.CommunicationException' occurred in System.ServiceModel.dll
Will this have any impact on performance of the host over a long period of time?
The problem has been resolved: https://github.com/NLog/NLog/commit/138fd2ec5d94072a50037a42bc2b84b6910df641

Package and publish Azure Cloud Service with unique Sql Azure connectionStrings

I have a .NET Web solution with an Azure Cloud Service project and a single webrole. I deploy it to the East coast West coast data/compute centers for failover purposes and have been asked to automate the deployment using Powershell MSBuild and Jenkins.
The problem is i need to change the Sql Azure database connectionString in the Web.config prior to packaging and publishing to each deployment. Seems simple enough.
I understand that the webrole properties Settings tab allows you to add custom configuration properties to each deployment with a type of either "string" or "Connection String" but it looks like the "Connection String" option applies to only Blob, Table or Queue storage. If I use the "String" and give it an Sql Azure connection string type it writes it out as an key/value pair and Entity Framework and the Membership Provider do not find it.
Is there a way to add a per-deployment connection string setting that points to Sql Azure?
Thanks,
David
Erick's solution is completely valid and I found an additional way to solve the problem so I thought I'd come back and put it up here since I had such trouble finding an answer.
The trick is getting the Entity Framework and any providers like asp.net Membership/profile/session etc... to read the connection string directly from the Azure service configuration rather than the sites web.config file.
For the providers I was able to create classes that inherit the System.Web.Providers.DefaultMembershipProvider class and override the Initialize() method where I then used a helper class I wrote to retrieve the connection string using the RoleEnvironment.GetConfigurationSettingValue(settingName); call, which reads from the Azure service config.
I then tell the Membership provider to use my class rather than the DefaultMembershipProvider. Here is the code:
Web.config:
<membership defaultProvider="AzureMembershipProvider">
<providers>
<add name="AzureMembershipProvider" type="clientspace.ServiceConfig.AzureMembershipProvider" connectionStringName="ClientspaceDbContext" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
Note the custom provider "AzuremembershipProvider"
AzuremembershipProvider class:
public class AzureMembershipProvider : System.Web.Providers.DefaultMembershipProvider
{
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
string connectionStringName = config["connectionStringName"];
AzureProvidersHelper.UpdateConnectionString(connectionStringName, AzureProvidersHelper.GetRoleEnvironmentSetting(connectionStringName),
AzureProvidersHelper.GetRoleEnvironmentSetting(connectionStringName + "ProviderName"));
base.Initialize(name, config);
}
}
And here's the helper class AzureProvidersHelper.cs:
public static class AzureProvidersHelper
{
internal static string GetRoleEnvironmentSetting(string settingName)
{
try
{
return RoleEnvironment.GetConfigurationSettingValue(settingName);
}
catch
{
throw new ConfigurationErrorsException(String.Format("Unable to find setting in ServiceConfiguration.cscfg: {0}", settingName));
}
}
private static void SetConnectionStringsReadOnly(bool isReadOnly)
{
var fieldInfo = typeof (ConfigurationElementCollection).GetField("bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
if (
fieldInfo != null)
fieldInfo.SetValue(ConfigurationManager.ConnectionStrings, isReadOnly);
}
private static readonly object ConnectionStringLock = new object();
internal static void UpdateConnectionString(string name, string connectionString, string providerName)
{
SetConnectionStringsReadOnly(false);
lock (ConnectionStringLock)
{
ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings["name"];
if (connectionStringSettings != null)
{
connectionStringSettings.ConnectionString = connectionString;
connectionStringSettings.ProviderName = providerName;
}
else
{
ConfigurationManager.ConnectionStrings.Add(new ConnectionStringSettings(name, connectionString, providerName));
}
}
SetConnectionStringsReadOnly(true);
}
}
The key here is that the RoleEnvironment.GetConfigurationSettingValue reads from the Azure service configuration and not the web.config.
For the Entity Framework that does not specify a provider I had to add this call to the Global.asax once again using the GetRoleEnvironmentSetting() method from the helper class:
var connString = AzureProvidersHelper.GetRoleEnvironmentSetting("ClientspaceDbContext");
Database.DefaultConnectionFactory = new SqlConnectionFactory(connString);
The nice thing about this solution is that you do not end up having to deal with the Azure role onstart event.
Enjoy
dnash
David,
A good option is to use the Azure configurations. If you right click on the Azure project, you can add an additional configuration. Put your connection string(s) in the correct configuration (e.g., ServiceConfiguration.WestCoast.cscfg, ServiceConfiguration.EastCoast.cscfg, etc).
In your build script, pass the TargetProfile property to MSBuild with the name of the configuration, and those settings will be built into the final cscfg.
Let me know if you run into any problems. I did the approach, and it took a few tries to get it working right. Some details that might help.
Erick

Error while using Linq "Include" method with Entity framework 4.1, Bug?

I am using SQL Azure as database with code first technique of Entity framework 4.1. I'm accessing EF from WCF as middle tier and providing the service reference to ASP.NET MVC 3.
The relational scenario in EF is A->B->C so as usual I tried to get A including B including C with few possibilities:
db.A.Include("B").Include("B.C")
db.A.Include("B").Include("C")
But in the Service itself running perfect. Since adding the reference to the web application it attempts to serialize and throws the exception below. I tried to make true-false lazy loading also without success.
"The underlying connection was closed: The connection was closed unexpectedly"
Stack Trace found:
at System.Net.HttpWebRequest.GetResponse() at
System.ServiceModel.Channels.HttpChannelFactory.
HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
I visited this page to resolve, and added the suggested attributes in web.config. Now I'm suddenly getting error:
The server did not provide a meaningful reply; this might be caused by
a contract mismatch, a premature session shutdown or an internal
server error
I thought it might be issue of some tag/atrribute mismatch in client and service web.configs but everything is right there. One thing I could not get to passing the List of objects with loading of its entire cllection properties, from wcf service to web application is found very heavy and low in performance. still facing the above issues to get the loaded list at web application in above explained architecture. can some body help here....
hey Thanks Kirk Broadhurst
, By this I could track the Issue. and searche around it. I got the solution. I added this class in my project
public class ReferencePreservingDataContractFormatAttribute : Attribute, IOperationBehavior
{
#region IOperationBehavior Members
public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
{
}
public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy)
{
IOperationBehavior innerBehavior = new ReferencePreservingDataContractSerializerOperationBehavior(description);
innerBehavior.ApplyClientBehavior(description, proxy);
}
public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch)
{
IOperationBehavior innerBehavior = new ReferencePreservingDataContractSerializerOperationBehavior(description);
innerBehavior.ApplyDispatchBehavior(description, dispatch);
}
public void Validate(OperationDescription description)
{
}
#endregion
}
class ReferencePreservingDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior
{
public ReferencePreservingDataContractSerializerOperationBehavior(OperationDescription operationDescription) : base(operationDescription) { }
public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
{
return CreateDataContractSerializer(type, name, ns, knownTypes);
}
private static XmlObjectSerializer CreateDataContractSerializer(Type type, string name, string ns, IList<Type> knownTypes)
{
return CreateDataContractSerializer(type, name, ns, knownTypes);
}
public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
{
return new DataContractSerializer(type, name, ns, knownTypes,
0x7FFF /*maxItemsInObjectGraph*/,
true/*ignoreExtensionDataObject*/,
true/*preserveObjectReferences*/,
null/*dataContractSurrogate*/);
}
}
}
And Added just : [ReferencePreservingDataContractFormat] as an attribute with the method definition where i wanted to use the "Include". thats it worked for me.
This might be helpful for other needy people.
This is a very common WCF exception and can be any number of things. There are hundreds of hits on StackOverflow for this problem.
https://stackoverflow.com/search?q=%22The+underlying+connection+was+closed%22
Are you new to WCF? Do any service calls work? It could be something as simple as maxMessageSize exceeded.
I'd suggest you implement logging on your service - add some diagnostics tags to your configuration file.
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\log\Traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>

WCF Client is unable to see endpoint but WCF Client can connect to base address

I get the following error when i try to consume my wcf service
Could not find endpoint element with name 'http://localhost:8080/Provider/basic' and contract 'Provider.IProvider' in the ServiceModel client configuration section
I can however connect to my base address through the WCF Test Client on http://localhost:8080/Provider
I've tried updating my service reference and that didn't work, Anyone know what is wrong with my setup
public ServiceHost ProviderServiceHost { get; set; }
private void StartProvider()
{
if (ProviderServiceHost != null)
Abort();
ProviderServiceHost = new ServiceHost(typeof(Provider), new Uri("http://localhost:8080/Provider"));
var binding = new BasicHttpBinding
{
Name = "basicBinding",
HostNameComparisonMode = HostNameComparisonMode.WeakWildcard,
Security = { Mode = BasicHttpSecurityMode.None }
};
var metadataBehavior = ProviderServiceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (metadataBehavior == null)
{
metadataBehavior = new ServiceMetadataBehavior { HttpGetEnabled = true };
ProviderServiceHost.Description.Behaviors.Add(metadataBehavior);
}
ProviderServiceHost.AddServiceEndpoint(typeof(IProvider), binding, "http://localhost:8080/Provider/basic");
ProviderServiceHost.Open();
}
My client is connecting like this
private static ProviderClient _proxy = new ProviderClient(http://localhost:8080/Provider/basic);
If i don't put in an address then i get this exception
Message "Could not find default endpoint element that references contract 'Provider.IProvider' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element." string
Are you using client side configuration? As it appears you're using the ClientBase proxy I expect you've used 'Add Service Reference...' and are just the default configuration file.
The overload that you're using is new ServiceClient(string endpointConfigurationName) - the string value represents a Name, not an Address. If you check your configuration file you should see a client section has been added:
<client>
<endpoint address="http://localhost:8080/Provider/basic"
binding="basicHttpBinding"
bindingConfiguration="basicBinding_IProvider"
contract="ServiceReference1.ITest"
name="basicBinding_IProvider" />
</client>
So if you change your Client constructor to use this Name property it should work better for you.
private static ProviderClient _proxy =
new ProviderClient("basicBinding_IProvider");
On the other hand if you are not using a configuration file and want to specify the address in code, you can use a different ClientBase constructor:
using System.ServiceModel;
// ...
_client = new ProviderClient(new BasicHttpBinding(),
new EndpointAddress("http://localhost:8080/Provider/basic"));
There are a number of different overloads in the ClientBase class (your ProviderClient) which allow you to specify various properties.

WCF service returns Error:System.Xml.Schema.XmlSchemaValidationException:

My application is accessing a WCF service hosted at the server.
When i try to call a Method with [WebInvoke] attribute the response returned is always "error".
All other methods with [WebGet] attribute are working fine.
The interface as in the reference.cs is
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="SyncService.IService")]
public interface IService
{
[WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)]
[System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="")]
[System.ServiceModel.FaultContractAttribute(typeof(DataSynchronization.SyncService.WebExceptionDetail), Action="Update", Name="WebExceptionDetail", Namespace="http://schemas.datacontract.org/xxx.WebServices")]
string Update(string mode, string data);
}
whenever i try to call the Update method of the service using the code
string response = objClient.Update("manual", string data);
the response obtained is "Error".and the log displays
Error -
"System.Xml.Schema.XmlSchemaValidationException:
The element 'providers' cannot contain
text. List of possible elements
expected: 'provider'". on calling
Update
The service is hosted in a remote server which i cannot debug either.