The error code is absolutely terrible, ERR_CONNECTION_RESET has a host of causes and the causes that I found on other questions were related to having too small of a MaxRequestLength for large web service calls. The data I was returning was only a couple of kB though, so this couldn't be the issue.
Here is my interface code
[WebGet(RequestFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "GetReportByID?ReportID={ReportID}")]
[OperationContract]
UsageReport GetReportByID(int ReportID);
This was the implementation
public UsageReport GetReportByID(int ReportID)
{
return new UsageReport(ReportID);
}
And this was the class code for UsageReport
[DataContract]
public class UsageReport
{
[DataMember]
List<UsageItem> RL;
public UsageReport(int reportID)
{
RL = new List<UsageItem>();
using (SqlDataReader dr = DBUtility.ExecuteReader(cmd, "DBString"))
{
while (dr.Read())
{
ItemNumber = dr["ItemID"] as int? ?? 0;
RL.Add(new UsageItem(ItemNumber));
}
dr.Close();
}
}
public class UsageItem
{
int ItemNumber;
public UsageItem(int ItemNumber)
{
this.ItemNumber = ItemNumber;
}
}
The problem was my UsageItem class, I was missing the necessary DataContract and DataMember fields.
[DataContract]
public class UsageItem
{
[DataMember]
int ItemNumber;
public UsageItem(int ItemNumber)
{
this.ItemNumber = ItemNumber;
}
}
I'd like to add a solution related to a case where WCF is used on the server side:
Add diagnostics to web.config (taken from here):
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.diagnostics>
<sources>
<source name="System.Net" switchValue="Verbose">
<listeners>
<add name="SystemNetTrace"/>
</listeners>
</source>
<source name="System.ServiceModel" switchValue="Verbose, ActivityTracing" propagateActivity="true">
<listeners>
<add name="wcftrace" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging" switchValue="Verbose, ActivityTracing">
<listeners>
<add name="wcfmessages" />
</listeners>
</source>
<source name="System.Runtime.Serialization" switchValue="Verbose">
<listeners>
<add name="wcfmessages" />
</listeners>
</source>
</sources>
<sharedListeners>
<add name="SystemNetTrace" type="System.Diagnostics.TextWriterTraceListener" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, Callstack" initializeData="C:\Traces\System_Net.txt" />
<add name="wcftrace" type="System.Diagnostics.XmlWriterTraceListener" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, Callstack" initializeData="C:\Traces\WCFTrace.svclog" />
<add name="wcfmessages" type="System.Diagnostics.XmlWriterTraceListener" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, Callstack" initializeData="C:\Traces\WCFMessages.svclog" />
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>
</configuration>
Reproduce the error, then go to the trace folder (C:\Traces, in this example). There will be 2 svclog files there: WCFMessages.svclog and WCFTrace.svclog.
Open the file named WCFMessages.svclog. A "Microsoft Service Trace Viewer" window will open, showing errors with a red color.
If no errors are displayed, open WCFTrace.svclog, and the errors (in red) would be there.
In my case, it was a System.Runtime.Serialization error because of a lack of DataContract attribute.
Related
I've made a basic WCF Service Library and created one method called GetResult(). I've set up WCF trace logging to log Warnings to a file. This is correctly logging all exceptions thrown except, for some strange reason, System.Exception itself. For instance, this logs fine:
[OperationContract]
public string GetResult()
{
// exception is logged in file:
throw new DivideByZeroException();
// or
// throw new ApplicationException();
// or
// throw new FileNotFoundException();
// or anything else, it seems
}
But this does not log anything:
[OperationContract]
public string GetResult()
{
// exception is not logged!
throw new Exception();
// or
// throw new Exception("my message");
}
In the latter case, the log file doesn't even get created. If it already exists then it doesn't get written to.
What am I doing wrong?
Here is my app.config setup:
<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging" switchValue="Warning">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
<source name="System.ServiceModel" switchValue="Warning">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
<source name="System.Runtime.Serialization" switchValue="Warning">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
</sources>
<trace autoflush="true" />
<sharedListeners>
<add initializeData="c:\temp\logs\wcf.svclog"
type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
name="ServiceModelTraceListener"
traceOutputOptions="Timestamp" />
</sharedListeners>
</system.diagnostics>
I have created a WCF service with 2 methods :
[ServiceContract(Namespace = "")]
[SilverlightFaultBehavior]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MyDataService
{
[OperationContract]
public IQueryable<object> Service1()
{
PivotData pivot = new PivotData();
IQueryable<object> list = pivot.GeneratePivotData();
return list;
}
[OperationContract]
public string Service2()
{
return "hello";
}
}
The Service2 works perfectly fine. However , service1 returns the dreaded
"the remote server has returned an error : not found"
I believe it has to do with the return type IQueryable<object> , but I don't know what I should change to make it work. I tried List<string> , ObservableCollection<object> and a few others but to no avail.
What should I do the get my data back to the client ?
Thanks
depending on the question and conversation with Aron.
I supposed it is a WCF-Ria Services If so please retag the question, otherwise you may ignore this answer.
Try the below code.
Beside if you use ria services. you should use , [Association("FK_assos_name", "field", "field")] [Include] for complex properties and your base class should have at least one [Key] attributed field. Such as ID.
[OperationContract]
public BaseClass[] ServiceMethod1()
{
PivotData pivot = new PivotData();
IQueryable<object> list = pivot.GeneratePivotData();
return list.ToArray();
}
If you still get errors trace it;In your web.config add the lines below. Then open WcfDetailTrace.svclog with svclog viewer. Red parts will show you what goes wrong.
<system.diagnostics>
<trace autoflush="true">
<listeners>
</listeners>
</trace>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="sdt"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "WcfDetailTrace.svclog" />
</listeners>
</source>
</sources>
We are having problems with a WCF services call that is leaking memory. In our research we think we are calling the service correctly and handling errors that come back from it appropriately. We have even confirmed this with MSDN articles and sample WCF code obtained from a MS web site.
Here is a sample of the code that causes the leak. On the SaveAssociation call, the code on the other side throws an exception. This causes the channel to enter the faulted state. The first catch statement catches the exception (SystemException) and calls Abort() on the client which should immediately abort the session and close the client connection. However, watching this process run this code over and over in a loop we just see the memory used by the process climb and climb.
var client = new FrameworkServiceReference.MAServiceClient();
// Get User domain name
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "password";
OperationContextScope a1 = new OperationContextScope(client.InnerChannel);
MessageHeader<string> customHeaderAppID = new MessageHeader<string>("Account Management");
System.ServiceModel.Channels.MessageHeader a2 = customHeaderAppID.GetUntypedHeader("application", "http://www.ma.com");
OperationContext.Current.OutgoingMessageHeaders.Add(a2);
try
{
client.SaveAssociation(association);
client.Close();
}
catch (SystemException se)
{
client.Abort();
}
catch (Exception ex)
{
client.Abort();
}
Here is the error we receiveā¦
System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: Object reference not set to an instance of an object. (Fault Detail is equal to An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
System.NullReferenceException: Object reference not set to an instance of an object.
at Multiview.Business.Core.CoreObject.ValidateItem(String Item, String Value)
at Multiview.Business.Core.User.UpdateUser()
at Multiview.Business.Core.User.Save()
at Multiview.Core.ServiceLibrary.MultiviewService.SaveCRMUser(User user, Guid CRMGuid)
at SyncInvokeSaveCRMUser(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
at System.ServiceMode...).
What can be done to stop this leak?
If memory on the server goes up, check the server log. Probably the object you return has a circular reference. This means that when it is returned, the server will throw a stack overflow when serializing the object.
Try to configure your service with:
IncludeExceptionDetailInFaults=true
And create some logs (server and client side):
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Error, ActivityTracing" propagateActivity="true">
<listeners>
<add name="xml" />
</listeners>
</source>
<source name="CardSpace">
<listeners>
<add name="xml" />
</listeners>
</source>
<source name="System.IO.Log">
<listeners>
<add name="xml" />
</listeners>
</source>
<source name="System.Runtime.Serialization">
<listeners>
<add name="xml" />
</listeners>
</source>
<source name="System.IdentityModel">
<listeners>
<add name="xml" />
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xml" type="System.Diagnostics.XmlWriterTraceListener" initializeData="C:\t\mylog.svclog" />
</sharedListeners>
</system.diagnostics>
If you have a problem with memory leaks you should start with some memory profiler and find which objects are living in your memory. That will lead you to the source of leakage.
You can start with the fact that OperationContextScope is disposable.
Assume I have a config file which looks like this:
...
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Warning,ActivityTracing" propagateActivity="true">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="LogServer.svclog" type="System.Diagnostics.XmlWriterTraceListener" name="ServiceModelTraceListener" />
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>
When using this config file every activity the caller performs against the service and each corresponding message that's sent to the service will be logged in the svclog file. Everything fine so far.
If I modify the 3rd line from the above listing to <source name="System.ServiceModel" switchValue="Warning" propagateActivity="true"> (the ActivityTracing is removed) then only those activities are logged that are at least labeled level warning. But it's still every message logged...
So is there a way to only log those message that correspond to those activities that are at least warnings? Those messages that succeeded aren't very interesting in that moment, but those messages that belong to the unsuccessful activities are!
Edit
To filter messages beyond the options below you may want to look into writing your own TraceSource.
Below is one I am using for a project. You could easily customize it to filter out the messages you want or perhaps hide activity if it is not in DEBUG, etc.
class DB : TraceSource
{
public DB(string name) : base(name)
{
}
public DB(string name, SourceLevels sourceLevels) : base (name, sourceLevels)
{
}
public void Log(object value)
{
WriteLine(value);
}
public void Error(object value)
{
WriteLine(value, TraceEventType.Error);
}
public void Error(RecordingResponseData errorResponse)
{
string errorMessage = "[Error] Code: "+errorResponse.ErrorCode +" Message: "+errorResponse.ErrorMessage;
WriteLine(errorMessage, TraceEventType.Error);
}
public void Warn(object value)
{
WriteLine(value, TraceEventType.Warning);
}
public void WriteLine(object value, TraceEventType type = TraceEventType.Information)
{
TraceEvent(type, 0, value.ToString());
}
}
Original
Your options are:
Critical
Error
Warning
Information
ActivityTracing
Verbose
All
Or a combination there of. If you have it set to Warning but are still getting too many messages then you may want to try Error or Critical.
ref: https://msdn.microsoft.com/en-us/library/ms733025%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
There's a switchValue available for the System.ServiceModel.MessageLogging trace switch as well. Just add that attribe to that source element and set it to Warning also and you will only see messages logged that are related to warnings.
Get rid of System.ServiceModel.MessageLogging source to get rid of logging messages to resolve "still every message logged".
I want to write CustomTraceListener which writes all data to SQL Server DB.
Here's the stub for it:
public class SqlTraceListener : TraceListener
{
public SqlTraceListener()
: base()
{ }
public SqlTraceListener(String name)
: base(name)
{ }
protected override string[] GetSupportedAttributes()
{
List<string> attributes = new List<string>();
attributes.Add("connectionString");
attributes.Add("actionFilter");
attributes.Add("hostFilter");
return base.GetSupportedAttributes();
}
public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
{ }//Other empty methods...
}
In overridden method TraceData I want to catch SOAP messages sent to my WCF service. But when I check what is in "data" parameter I get this: (sorry for posting xml as pictures - it seems SO editor doesn't allow some xml keywords in posts):
But according to standard XmlWriterTraceListener I should get this:
How to configure TraceListener not to eliminate SOAP messages?
My config is here:
<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="xml"/>
<add name="sql"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="C:\logs\StockPriceService.svclog" type="System.Diagnostics.XmlWriterTraceListener" name="xml"/>
<add type="SqlTraceListener.SqlTraceListener, SqlTraceListener" name="sql"/>
</sharedListeners>
<trace autoflush="true"/>
Is there any reason you're not using the out of the box database trace listener? See: Enterprise Library Database Trace Listener?.