Self hosted Wcf serves wsdl but 404's when invoked - c#

I'm trying to self-host a singleton instance of a service and I'm obviously getting lost at a level of indirection...
I've got a base address of http://localhost:8050/. I'm not too bothered where the service endpoint is as long as it's predictable. For the moment, I'm trying to use /Manage/.
I'm able to browse to the base address and see a wsdl. If I scan through the wsdl, it points at /Manage/..
<wsdl:service name="EngineService">
<wsdl:port name="BasicHttpBinding_IEngineService" binding="tns:BasicHttpBinding_IEngineService">
<soap:address location="http://localhost:8050/Manage/"/>
</wsdl:port>
</wsdl:service>
When I consume the wsdl using the WcfTestClient, it lists all the correct methods, but calling any of them throw the following exception
System.ServiceModel.EndpointNotFoundException: There was no endpoint listening at http://localhost:8050/Manage that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.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 IEngineService.SupportedAgents()
at EngineServiceClient.SupportedAgents()
Inner Exception:
The remote server returned an error: (404) Not Found.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
Log messages show my instance methods never get called. The service doesn't enter a faulted state, it just looks like it's not there.
I'm listening as follows:
public static ServiceHost Listen<TServiceContract>(
TServiceContract instance,
int port,
string name
) {
//Added this for debugging, was previously just "name"
string endpoint = String.Format("http://localhost:{0}/{1}/", port, name);
var svcHost = new ServiceHost(
instance,
new Uri[] { new Uri(String.Format("http://localhost:{0}/", port)) });
/* Snip: Add a Faulted handler but it's never called */
ServiceEndpoint serviceHttpEndpoint = svcHost.AddServiceEndpoint(
typeof(TServiceContract),
new BasicHttpBinding {
HostNameComparisonMode = HostNameComparisonMode.WeakWildcard
}, endpoint); /*Using name instead of endpoint makes no difference beyond removing the trailing slash */
/* Snip: Add a ServiceDebugBehavior with IncludeExceptionDetailInFaults = true */
/* Snip: Add a ServiceMetadataBehavior with HttpGetEnabled = true */
try {
log.Trace("Opening endpoint");
svcHost.Open();
} catch () {
/* Lots of catches for different problems including Exception
* None of them get hit */
}
log.Info("Service contract {0} ready at {1}", typeof(TServiceContract).Name, svcHost.BaseAddresses.First());
return svcHost;
And calling the Listen() method as follows:
IEngineService wcfInstance = Resolver.Resolve<IEngineService>();
service = WcfHoster.Listen(wcfInstance, 8050, "Manage");
How can I track down what the problem is/debug further?
Additional info: The Service contract and minimal implementation:
[ServiceContract]
interface IEngineService {
[OperationContract]
List<string> Agents();
[OperationContract]
string Test();
[OperationContract]
List<string> SupportedAgents();
[OperationContract]
string Connect(string AgentStrongName, string Hostname);
}
And the implementation:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
class EngineService : IEngineService {
IAgentManager agentManager;
public EngineService(IAgentManager AgentManager) {
log.Debug("Engine webservice instantiating");
this.agentManager = AgentManager;
}
public string Connect(string AgentStrongName, string Hostname) {
log.Debug("Endpoint requested for [{0}], [{1}]", Hostname, AgentStrongName);
return agentManager.GetSession(AgentStrongName, Hostname);
}
public List<string> Agents() {
log.Debug("Current agents queried");
throw new NotImplementedException();
}
public List<string> SupportedAgents() {
log.Debug("Supported agents queried");
return agentManager.SupportedAgents().ToList();
}
public string Test() {
log.Warn("Test query");
return "Success!";
}
}
The test client can see the service and methods but throws the exception above when I click Invoke...
Edit: localhost resolves to IPv6 by default so I've tried using 127.0.0.1 explicitly at both ends. No difference.
I've tried taking the above code into a new project and get the same issue. Running the whole thing on someone else's machine didn't help either.
Service Trace viewer
Running a service trace on the server side, then examining the results in the viewer gives:
Failed to lookup a channel to receive an incoming message. Either the endpoint or the SOAP action was not found.
Config file: Since I need the executable to be able to make a decision about which Wcf service to present at runtime, I don't have any Wcf-related code in the config file.

This is probably a client / service binding mismatch. Please check the test client binding. You should also create a unit test by generating a proxy from the wsdl.
Ok. I have tried to reproduce your issue and I managed calling the host by removing "HostNameComparisonMode = HostNameComparisonMode.WeakWildcard" in order to get a default basichttp endpoint. Why do you need this?

Related

ESTES ShipmentTracking v1.1 Web Service, Error in deserializing body of reply message for operation 'shipmentTracking'

I am trying to develop a simple Windows Forms app to request tracking information from the latest version ESTES ShipmentTracking v1.1 web service. When I execute the Request, my program throws a System.ServiceModel.CommunicationException
I am using Visual Studio 2019 and .NET 4.6.2 C# Windows Forms application.
I configured a Connected Service using the Add Service Reference procedure and use the ESTES_Track namespace.
Here is my essential code:
ESTES_Track.EstesShipmentTracking_PortTypeClient trackClient = new EstesShipmentTracking_PortTypeClient();
trackClient.ClientCredentials.UserName.UserName = "MYUSERNAME";
trackClient.ClientCredentials.UserName.Password = "MYPASSWORD";
ESTES_Track.search trackSearch = new ESTES_Track.search();
trackSearch.requestID = "TRACK" + DateTime.Now.Ticks.ToString();
trackSearch.pro = "1710394802";
ESTES_Track.shipmentTrackingRequest trackRequest = new shipmentTrackingRequest(trackSearch);
ESTES_Track.shipmentTrackingResponse trackResponse = trackClient.shipmentTracking(trackRequest);
Communication Exception is:
Error in deserializing body of reply message for operation 'shipmentTracking'
There is an error in XML document (1, 575)
at System.ServiceModel.Dispatcher.XmlSerializerOperationFormatter.DeserializeBody(XmlDictionaryReader reader, MessageVersion version, XmlSerializer serializer, MessagePartDescription returnPart, MessagePartDescriptionCollection bodyParts, Object[] parameters, Boolean isRequest)
at System.ServiceModel.Dispatcher.XmlSerializerOperationFormatter.DeserializeBody(XmlDictionaryReader reader, MessageVersion version, String action, MessageDescription messageDescription, Object[] parameters, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeBodyContents(Message message, Object[] parameters, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.DeserializeReply(Message message, Object[] parameters)
at System.ServiceModel.Dispatcher.ProxyOperationRuntime.AfterReply(ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
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 EstesTests.ESTES_Track.EstesShipmentTracking_PortType.shipmentTracking(shipmentTrackingRequest request)
at EstesTests.ESTES_Track.EstesShipmentTracking_PortTypeClient.shipmentTracking(shipmentTrackingRequest request) in C:\tests\EstesTests\Connected Services\ESTES_Track\Reference.cs:line 1394
at EstesTests.Program.TrackTest() in C:\tests\EstesTests\Program.cs:line 49
-=-=-=- edit -=-=-=-
I can successfully process a Request and get a valid Response using SoapUI. This leads me to believe my problem is specific to my Visual Studio project.
My App.config file looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="estesrtshipmenttracking_base_ws_provider_soapws_EstesShipmentTracking_Binder">
<security mode="Transport">
<transport clientCredentialType="Basic"></transport>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://api.estes-express.com:443/ws/estesrtshipmenttracking.base.ws.provider.soapws:EstesShipmentTracking/estesrtshipmenttracking_base_ws_provider_soapws_EstesShipmentTracking_Port"
binding="basicHttpBinding" bindingConfiguration="estesrtshipmenttracking_base_ws_provider_soapws_EstesShipmentTracking_Binder"
contract="ESTES_Track.EstesShipmentTracking_PortType" name="estesrtshipmenttracking_base_ws_provider_soapws_EstesShipmentTracking_Port" />
</client>
</system.serviceModel>
</configuration>
-=-=-=- edit -=-=-=-
The reason I explicitly labeled this as "ESTES ShipmentTracking v1.1" is that I am quite sure the problem(s) I am having are likely specific to this particular web service. If someone already has a working code sample for using this web service, That might include the solution to my problem. Also, I am sure anyone else trying to develop a shipping client for ESTES will encounter this problem.
-=-=-=- conclusion -=-=-=-
I conclude that the XML content of the response messages does not adequately comply with the published v1.1 WSDL schema and that the deserialization exceptions are specific to this web service implementation version. I have not experienced this problem with the previous v1.0 version.
I experienced the same problem today and narrowed it down to a couple issues:
The eventTimeStamp is missing a colon in the timezone portion
Empty fields are missing xsi:nil
I wrote to tech support, but in the meanwhile was able to get it to work by manipulating the response with a custom message inspector as described here https://blogs.msdn.microsoft.com/dsnotes/2015/04/14/wcf-simple-way-to-modify-serialized-response/.
You can add it to your client like this:
trackClient.Endpoint.Behaviors.Add(new EstesTrackingEndpointBehavior());
Hopefully they can address this on their end. If other issues come up, you can add additional changes to the response in AfterReceiveReply:
using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Xml;
namespace EstesWebService {
public class EstesTrackingMessageInspector : IClientMessageInspector {
public void AfterReceiveReply(ref Message reply, object correlationState) {
var doc = new XmlDocument();
var ms = new MemoryStream();
var writer = XmlWriter.Create(ms);
reply.WriteMessage(writer);
writer.Flush();
ms.Position = 0;
doc.Load(ms);
//fix the XML
addNil(doc.SelectNodes(".//shipments"));
foreach (XmlNode node in doc.SelectNodes(".//eventTimeStamp"))
fixDateTimeFormat(node);
ms.SetLength(0);
writer = XmlWriter.Create(ms);
doc.WriteTo(writer);
writer.Flush();
ms.Position = 0;
var reader = XmlReader.Create(ms);
reply = Message.CreateMessage(reader, int.MaxValue, reply.Version);
}
public object BeforeSendRequest(ref Message request, IClientChannel channel) {
return null;
}
private void addNil(XmlNodeList nodes) {
foreach (XmlNode node in nodes) {
if (node.HasChildNodes)
addNil(node.ChildNodes);
else if (string.IsNullOrWhiteSpace(node.InnerText) && node.Attributes != null && node.Attributes.GetNamedItem("xsi:nil") == null) {
var attr = node.OwnerDocument.CreateAttribute("xsi", "nil", "http://www.w3.org/2001/XMLSchema-instance");
attr.Value = "true";
node.Attributes.SetNamedItem(attr);
}
}
}
private void fixDateTimeFormat(XmlNode node) {
if (node != null && !string.IsNullOrWhiteSpace(node.InnerText)) {
DateTimeOffset dt;
if (DateTimeOffset.TryParse(node.InnerText.Trim(), out dt))
node.InnerText = dt.ToString("O");
}
}
}
public class EstesTrackingEndpointBehavior : IEndpointBehavior {
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) {
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) {
clientRuntime.MessageInspectors.Add(new EstesTrackingMessageInspector());
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) {
}
public void Validate(ServiceEndpoint endpoint) {
}
}
}

WCF Client not able to connect on some machines

I have a simple self host WCF Service. I have this service running on remote server. I am able to communicate to service with client running on my machine(I am local admin).
But when I run same client on different machine(non admin) they are not able to communicate.
I monitored resource manager and I see two random local ports are being open at each time of service call and call back. So I cannot open specific ports.
Any Idea what could be the possible reason or firewall configuration change on other machines?
I am very new to WCF. Please pardon me if its a basic question.
WCF Server Code
namespace CService
{
class Program
{
static void Main(string[] args) {
Console.Title = "C Service";
// Step 1 of the address configuration procedure: Create a URI to serve as the base address.
Uri baseAddress = new Uri("http://" + GetServerIPPort.ServerIP + ":" + GetServerIPPort.Port + "/CService/Service");
// Step 2 of the hosting procedure: Create ServiceHost
ServiceHost selfHost = new ServiceHost(typeof(CSerice), baseAddress);
try
{
// Step 3 of the hosting procedure: Add a service endpoint.
selfHost.AddServiceEndpoint(typeof(ICService), new BasicHttpBinding(), "CService");
// Step 4 of the hosting procedure: Enable metadata exchange.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
// Step 5 of the hosting procedure: Start (and then stop) the service.
selfHost.Open();
Console.WriteLine("The Coemet Service is ready and its listening on {0}", baseAddress.AbsoluteUri.ToString() + ":" + baseAddress.Port.ToString());
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
// Close the ServiceHostBase to shutdown the service.
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occurred: {0}", ce.ToString());
selfHost.Abort();
}
}
}
I have generatedProxy object with help of this link http://msdn.microsoft.com/en-us/library/ms733133(v=vs.110).aspx
My client code snippet looks like this.
string serviceEndPointAddress = "http://" + GetServerIPPort.ServerIP + ":" + GetServerIPPort.Port + "/CService/Service/CService";
var remoteAddress = new System.ServiceModel.EndpointAddress(new Uri(serviceEndPointAddress));
object rawOutput;
using (var client = new CServiceClient(new BasicHttpBinding(), remoteAddress))
{
client.Endpoint.Binding.SendTimeout = new TimeSpan(0, 0, 0, 100);
try
{
rawOutput = client.GetData(Identifier, field, date);
}
catch (Exception e)
{
errorMsg = e.ToString();
}
}\n
Error trowed at "client.GetData(Identifier, field, date)"
System.Runtime.Serialization.InvalidDataContractException: Type 'System.Threading.Tasks.Task1[System.Object]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type)
at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type)
at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type)
at System.Runtime.Serialization.XsdDataContractExporter.GetSchemaTypeName(Type type)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.CreatePartInfo(MessagePartDescription part, OperationFormatStyle style, DataContractSerializerOperationBehavior serializerFactory)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.CreateMessageInfo(DataContractFormatAttribute dataContractFormatAttribute, MessageDescription messageDescription, DataContractSerializerOperationBehavior serializerFactory)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter..ctor(OperationDescription description, DataContractFormatAttribute dataContractFormatAttribute, DataContractSerializerOperationBehavior serializerFactory)
at System.ServiceModel.Description.DataContractSerializerOperationBehavior.GetFormatter(OperationDescription operation, Boolean& formatRequest, Boolean& formatReply, Boolean isProxy)
at System.ServiceModel.Description.DataContractSerializerOperationBehavior.System.ServiceModel.Description.IOperationBehavior.ApplyClientBehavior(OperationDescription description, ClientOperation proxy)
at System.ServiceModel.Description.DispatcherBuilder.BindOperations(ContractDescription contract, ClientRuntime proxy, DispatchRuntime dispatch)
at System.ServiceModel.Description.DispatcherBuilder.BuildProxyBehavior(ServiceEndpoint serviceEndpoint, BindingParameterCollection& parameters)
at System.ServiceModel.Channels.ServiceChannelFactory.BuildChannelFactory(ServiceEndpoint serviceEndpoint, Boolean useActiveAutoClose)
at System.ServiceModel.ChannelFactory.CreateFactory()
at System.ServiceModel.ChannelFactory.OnOpening()
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.ChannelFactory.EnsureOpened()
at System.ServiceModel.ChannelFactory1.CreateChannel(EndpointAddress address, Uri via)
at System.ServiceModel.ClientBase1.CreateChannel()
at System.ServiceModel.ClientBase1.CreateChannelInternal()
at System.ServiceModel.ClientBase`1.get_Channel()
at CServiceClient.GetData(String Identifier, String field, DateTime date)
In .NET 4.5, there is new support for task-based asynchronous operations in WCF. When you generate a proxy on your development machine using VS 2012 or later - it can include these by default.
Now the new machine that you are using is likely running on .NET 4.0 and as a result does not know what the heck to do with the task-based asynchronous operation - hence the exception.
It's a pretty simple fix, to support clients running .NET 4.0 you just need to do either of the following in Service Reference Settings:
Uncheck Allow generation of asynchronous operations
Select Generate asynchronous operations instead of Generate task-based operations
Special thanks goes to this blog post.
According to the exception you are passing an object that is not serializable. I suspect this is the Identifier in the following line of code:
rawOutput = client.GetData(Identifier, field, date);
According to the stack trace the CService is expecting two strings and a datetime:
System.ServiceModel.ClientBase`1.get_Channel() at
CServiceClient.GetData(String Identifier, String field, DateTime date)
If you need to pass a custom object (data transfer object) using WCF you should use the DataContractAttribute attribute for the class and the DataMemberAttribute for each member, like this:
[DataContract]
public class Identifier
{
[DataMember]
public string Id {get;set;}
}
I too was facing the same issue, when I created a WCF Service on framework 4.5 higher and was trying to deploy on the IIS 8(i.e App pool 4.0), the above steps didn't solved my issue, So I recreated my full solution from scratch in framework 4.0 and re-deployed it. While consuming the services, followed the above steps to uncheck "Allow generation of asynchronous operations" Resolved my problem.

Sending a XML File through WCF Fails

I've been trying to send a XML file from my WCF to my project without much luck. I have a Exception thrown from my program once the response is completed by WCF and sent to the Phone. I was hoping someone could please help me, as I have been looking around for an answer and found nothing. (The program uses XNA for a Windows Phone Applications)
[System.Net.WebException] {System.Net.WebException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound.
at System.Net.Browser.ClientHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
at System.Net.Browser.ClientHttpWebRequest.<>c__DisplayClasse.<EndGetResponse>b__d(Object sendState)
at System.Net.Browser.AsyncHelper.<>c__DisplayClass1.<BeginOnUI>b__0(Object sendState)
--- End of inner exception stack trace ---
at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
at System.Net.Browser.ClientHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)} System.Net.WebException
public string EndHighScoreList(System.IAsyncResult result) {
object[] _args = new object[0];
string _result = ((string)(base.EndInvoke("HighScoreList", _args, result)));
return _result;
}
IService.cs
[ServiceContract]
[XmlSerializerFormat]
public interface IService
{
[OperationContract]
void ParseScore(HighScore score);
[OperationContract]
string HighScoreList();
}
public class HighScore
{
[XmlElement]
public UInt32 m_rank;
[XmlAttribute]
public string m_name;
[XmlAttribute]
public UInt32 m_score;
}
Service.svc
public string HighScoreList()
{
XmlSerializer ser = new XmlSerializer(typeof(HighScore));
using (FileStream fs = new FileStream(HttpContext.Current.Server.MapPath("App_Data/Highscores.xml"), FileMode.OpenOrCreate))
{
return ser.Deserialize(fs).ToString();
}
}
Here's the requested code
void globalRecieve(object obj, DodgeService.HighScoreListCompletedEventArgs e)
{
try
{
string result = e.Result;
using (TextReader reader = new StringReader(result)){
XmlSerializer xml = new XmlSerializer(typeof(List<DodgeService.HighScore>));
foreach (DodgeService.HighScore sco in xml.Deserialize(reader) as List<DodgeService.HighScore>)
highScores.Add(sco);
}
}catch(Exception exception){
string error = exception.Message;
}
}
protected override void Initialize()
{
service = new DodgeService.ServiceClient("BasicHttpBinding_IService");
service.HighScoreListAsync(null);
service.HighScoreListCompleted += new EventHandler<DodgeService.HighScoreListCompletedEventArgs>(globalRecieve);
base.Initialize();
}
Personally I believe WCF sucks. The Configuration alone is a nightmare and if you change anything, you have to re-build your objects and any changes you've made you have to re-make.
You should migrate to ServiceStack. It handles everything for you. You only write the sending and receiving of business DTO objects. Sending and receiving files is basic stuff for it,
See this google search for several people asking similar questions but based on ServiceStack. Mythz is a project lead for ServiceStack and he answers their questions. It should get you started and you should see how EASY it is.
Just for future reference in case that google search doesn't give the same as I got, here is the search and first three responses;
"servicestack file upload"
Using ServiceStack to upload image files
How to use Servicestack PostFileWithRequest
ServiceStack client add attachment
The error says: "NotFound". It looks like the operation HighScoreList is not exposed / available at all. Try opening the path in your browser.
I kept having a Not Found error because, then the Windows Phone ran it was trying to connect to the service via LocalHost which wouldn't work as I needed it to connect to the development PC. The solution was to host the WCF service on a server and connect to the server or connect to the IP of the development PC.

.NET remoting service seemingly crashes, and stops responding to clients

I have a .NET Remoting service which works fine most of the time. If an exception or error happens, it logs the error to a file but still continues to run.
However, about once every two weeks the service stops responding to clients, which causes the client appication to crash with a SocketException with the following message:
A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
No exception or stack trace is written to our log file, so I can't figure out where the service is crashing at, which leads me to believe that it is somewhere outside of my code which is failing. What additional steps can I take to figure out the root cause of this crash? I would imagine that it writes something to an EventLog somewhere, but I am not super familiar with Windows' Event Logging system so I'm not exactly sure where to look.
Thanks in advance for any assistance with this.
EDIT: Forgot to mention, stopping or restarting the service does nothing, the service never responds. I need to manually kill the process before I can start the service again.
EDIT 2:
public class ClientInfoServerSinkProvider :
IServerChannelSinkProvider
{
private IServerChannelSinkProvider _nextProvider = null;
public ClientInfoServerSinkProvider()
{
}
public ClientInfoServerSinkProvider(
IDictionary properties,
ICollection providerData)
{
}
public IServerChannelSinkProvider Next
{
get { return _nextProvider; }
set { _nextProvider = value; }
}
public IServerChannelSink CreateSink(IChannelReceiver channel)
{
IServerChannelSink nextSink = null;
if (_nextProvider != null)
{
nextSink = _nextProvider.CreateSink(channel);
}
return new ClientIPServerSink(nextSink);
}
public void GetChannelData(IChannelDataStore channelData)
{
}
}
public class ClientIPServerSink :
BaseChannelObjectWithProperties,
IServerChannelSink,
IChannelSinkBase
{
private IServerChannelSink _nextSink;
public ClientIPServerSink(IServerChannelSink next)
{
_nextSink = next;
}
public IServerChannelSink NextChannelSink
{
get { return _nextSink; }
set { _nextSink = value; }
}
public void AsyncProcessResponse(
IServerResponseChannelSinkStack sinkStack,
Object state,
IMessage message,
ITransportHeaders headers,
Stream stream)
{
IPAddress ip = headers[CommonTransportKeys.IPAddress] as IPAddress;
CallContext.SetData("ClientIPAddress", ip);
sinkStack.AsyncProcessResponse(message, headers, stream);
}
public Stream GetResponseStream(
IServerResponseChannelSinkStack sinkStack,
Object state,
IMessage message,
ITransportHeaders headers)
{
return null;
}
public ServerProcessing ProcessMessage(
IServerChannelSinkStack sinkStack,
IMessage requestMsg,
ITransportHeaders requestHeaders,
Stream requestStream,
out IMessage responseMsg,
out ITransportHeaders responseHeaders,
out Stream responseStream)
{
if (_nextSink != null)
{
IPAddress ip =
requestHeaders[CommonTransportKeys.IPAddress] as IPAddress;
CallContext.SetData("ClientIPAddress", ip);
ServerProcessing spres = _nextSink.ProcessMessage(
sinkStack,
requestMsg,
requestHeaders,
requestStream,
out responseMsg,
out responseHeaders,
out responseStream);
return spres;
}
else
{
responseMsg = null;
responseHeaders = null;
responseStream = null;
return new ServerProcessing();
}
}
This is like trying to find out why nobody picks up the phone when you call a friend. And the problem is that his house burned down to the ground. An imperfect view of what is going on is the core issue, especially bad with a service because there is so little to look at.
This can't get better until you use that telephone to talk to the service programmer and get him involved with the problem. Somebody is going to have to debug this. And yes, it will be difficult, failing once every two weeks might not be considered critical enough. Or too long to sit around waiting for it to happen. Only practical thing you can do to help is create a minidump of the process and pass that to the service programmer so he's got something to poke at. If the service runs on another machine then get the LAN admin involved as well.
The issue was due to a deadlock caused in my code, if memory serves I had two locking objects and I locked one from inside the other, essentially making them wait for each other. I was able to determine this by hooking up a debugger to the remote service.

Random TimeoutException in client on many concurrent Async Calls

I have a TimeoutException problem, I am using C# 4.0 (can't upgrade to 4.5 anytime soon) and WCF. Note that I do not control the Server and cannot see the code and or technology that are used. The problem happens with different servers made by different people.
I send as many request as I can to many servers (let's say 10), one per server at any time. They go from 2 to 30 requests per second. Between 30 seconds to 5 minutes, I will get some TimeoutException :
exception {"The HTTP request to 'http://xx.xx.xx.xx/service/test_service' has exceeded the allotted timeout of 00:02:10. The time allotted to this operation may have been a portion of a longer timeout."} System.Exception {System.TimeoutException}.
Stack Trace :
Server stack trace:
at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeEndService(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 Device.EndTest(IAsyncResult result)
at DeviceClient.EndTest(IAsyncResult result) in ...
at TestAsync(IAsyncResult ar) in ...
The InnerException is :
[System.Net.WebException] {"The request was aborted: The request was canceled."} System.Net.WebException
at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)
Wireshark tells me that I do not even open a connection (no SYN). So this should be a client problem. I have many TIME_WAIT connections in TCPView
Using Sync calls is working, but not possible.
Note that in the following code example, there is one method call per server. (In my case, 10 concurrent TestAsync)
(in the real project, we use CCR instead of Semaphore, same result)
private void AsyncTest()
{
//GetServiceObject Will add custom bindings and more..
Client client = ClientBuilder.GetServiceObject();
while (true)
{
Semaphore semaphore = new Semaphore(0,1);
client.BeginTest(BeginTestCallback, new AsyncState
{
Client = client,
Semaphore = semaphore
});
semaphore.WaitOne();
}
}
private void BeginTestCallback(IAsyncResult asyncResult)
{
try
{
AsyncState state = asyncResult.AsyncState as AsyncState;
Client client = state.Client;
Semaphore semaphore = state.Semaphore;
Client.EndTest(asyncResult);
semaphore.Release();
}
catch (Exception e)
{
//Will catch the exception here because of Client.EndTest(asyncResult)
Debug.Assert(false, e.Message);
}
}
I tried with
ServicePointManager.DefaultConnectionLimit = 200;
ServicePointManager.MaxServicePointIdleTime = 2000;
As some post suggested, without success.
Even if I set really High Open, send, receive and close timeouts, it will do the same exception. WCF seems to be "stuck" at sending the request. The server continues to respond correctly to other requests.
Have any idea?
Also, If I do this (BeginTest in Callback instead of while(true)), it will never do the exception?!?!
private void AsyncTest()
{
//GetServiceObject Will add custom bindings and more..
Client client = ClientBuilder.GetServiceObject();
try
{
client.BeginTest(BeginTestCallback, new AsyncState
{
Client = client
});
}
catch (Exception e)
{
Debug.Assert(false, e.Message);
}
}
private void BeginTestCallback(IAsyncResult asyncResult)
{
try
{
AsyncState state = asyncResult.AsyncState as AsyncState;
state.Client.EndTest(asyncResult);
state.Client.BeginTest(BeginTestCallback, state);
}
catch (Exception e)
{
//No Exception here
Debug.Assert(false, e.Message);
}
}
After more testing, I found out that if the begin/end mechanism is not executed on the same thread pool, it will randomly do this behavior.
In the first case, "AsyncTest" was spawned within a new thread with ThreadStart and Thread. In the second case, only the first "begin" is called on the dedicated thread and since the problem occurs at random, there is a small chance that the exception would happen on first request. The other "begin" are made on the .net ThreadPool.
By using Task.Factory.StartNew(() => AsyncTest()) in the first case, the problem is gone.
In my real project, I still use CCR (and the CCR threadpool) to do everything until I have to call the begin/end.. I will use the .net threadpool and everything is working now.
Anyone have better explanation of why WCF doesn't like to be called on another threadpool?

Categories

Resources