Calling a WCF method from a WPF client does nothing - c#

I have a very simple WCF service running that has a single method that returns an enum based on the result of the method.
I have tested this WCF service through a very simple console app both locally and over the internet to my server and both work perfectly fine. However once I use the, literally exact, code in my WPF application calling the method does nothing. No exception, no timeout. Testing it locally with a breakpoint at the start of the WCF method I found it does not even reach that far when calling it from WPF.
Both service reference configurations that were generated in the app.config are identical between the console and WPF application.
Edit: Had hoped to not need to put as much code in here but I'll just dump the whole thing.
In WPF the code is being called from a button in a dialog. This button triggers an Coroutine call using Caliburn.Micro. The WCF call is then being called in the Execute method from the Coroutine.
public IEnumerator<IResult> SendReport()
{
var result = new Coroutines.SubmitNewExceptionIssueResult(Exception, UserNotes, Character);
yield return result;
if (result.Result == ErrorReportResult.OK)
TryClose();
else
// TODO
}
public class SubmitNewExceptionIssueResult : IResult
{
public event EventHandler<ResultCompletionEventArgs> Completed;
private ErrorReporterClient _client = new ErrorReporterClient();
private Exception _exception { get; set; }
private string _userNotes { get; set; }
private Character _character { get; set; }
public ErrorReportResult Result { get; private set; }
public SubmitNewExceptionIssueResult(Exception ex, string userNotes, Character character)
{
_exception = ex;
_userNotes = userNotes;
_character = character;
}
public void Execute(ActionExecutionContext context)
{
Result = _client.SendErrorReport(JsonConvert.SerializeObject(_exception, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
}),
_userNotes,
JsonConvert.SerializeObject(_character, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
}));
Completed(this, new ResultCompletionEventArgs());
}
}

The cause was indeed threading of some sort. While not happy with the implementation it now works.
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, new System.Action(() => { /* send report code */ }));

Related

WCF for windows phone 8.1 silverlight

I'm having problem using wcf with wp8.1 silverlight. I countinously getting the error The contract 'IPhoneService' contains synchronous operations, which are not supported in Silverlight. Split the operations into "Begin" and "End" parts and set the AsyncPattern property on the OperationContractAttribute to 'true'. Note that you do not have to make the same change on the server. After I changed my syncronous method to async I'm still getting the same error (I updated the service reference.). Out of curiousity I tried to use it on a console app, and it works perfectly.
Previously I did get an another error that might have something to do with it. Adding a service reference generated an app.config file, but the app needed a ServiceReferences.ClientConfig, so I simply renamed it.
For now I changed back the WCF method to syncronous:
public int GetData()
{
return 12;
}
and on my MainViewModel (I'm using MVVMLight toolkit):
public void Load()
{
var client = new ServiceReference1.PhoneServiceClient();
client.GetDataCompleted += client_GetDataCompleted;
client.GetDataAsync();
}
void client_GetDataCompleted(object sender, ServiceReference1.GetDataCompletedEventArgs e)
{
Title = e.Result.ToString();
}
and i implemeneted before the async method like this, getting the same error anyway:
public IAsyncResult BeginGetData(AsyncCallback callback, object asyncState)
{
var msg = 12;
return new CompletedAsyncResult<int>(msg);
}
public int EndGetData(IAsyncResult r)
{
CompletedAsyncResult<int> result = r as CompletedAsyncResult<int>;
return result.Data;
}
class CompletedAsyncResult<T> : IAsyncResult
{
T data;
public CompletedAsyncResult(T data)
{ this.data = data; }
public T Data
{ get { return data; } }
#region IAsyncResult Members
public object AsyncState
{ get { return (object)data; } }
public WaitHandle AsyncWaitHandle
{ get { throw new Exception("The method or operation is not implemented."); } }
public bool CompletedSynchronously
{ get { return true; } }
public bool IsCompleted
{ get { return true; } }
#endregion
}
The problem was VS2013 RC2 version. The reference wasn't generated correctly. An update solved the problem

Error Reporting

I have a class that follows the Command Pattern.
It has 2 methods which are Execute, and CanExecute which checks whether to invoke Execute or not (they derive from ICommand).
CanExecute invokes a few methods that check that all required services are running, the version is correct, etc.
After CanExecute is invoked, it may fail and return false and I need to know why. Is it because of a bad version, services, missing file, etc.
What is the best strategy to know what is the problem
One option is whenever a required condition fails I can throw an exception that will describe the error in the message field. However the possibility that it will fail is expected and you shouldn't use exceptions for regular flow of control. So I'm really not sure.
Thank you.
You can use a collection of "reasons" that will tell the users of the class why CanExecute returned false. The reasons can be a simple IEnumerable<string>.
public bool CanExecute() {
var messages = new List<string>();
if (!Condition1) {
messages.Add("Missing Condition1");
}
...
Messages = messages;
return messages.Count == 0;
}
public IEnumerable<string> Messages { get; private set; }
Then, client code can show the collection of messages to end-users.
UPDATE:
You can also associate new commands with the messages to give the users ways to fix the problems found. In this case, instead of an IEnumerable<string>, you can create your own class that encapsulates that information:
public class Message {
public string Text { get; set; }
public ICommand Command { get; set; }
}
...
public bool CanExecute() {
var messages = new List<Message>();
if (!Condition1) {
messages.Add(
new Message {
Text = "Missing Condition1",
Command = new FixCondition1Command()
}
);
}
...
Messages = messages;
return messages.Count == 0;
}
public IEnumerable<Message> Messages { get; private set; }
UPDATE: Reworked based on feedback.
Since the UI needs the reasons CanExecute() returns false, two things come to mind:
Option 1: Add an enumerable message property to the command interface and populate it as needed during the call to CanExecute(). The UI could then interrogate the property as needed. If you go this route, make sure you clear out the contents of the property each call to CanExecute() so you don't lose track of state.
public interface ICommand
{
IEnumerable<string> Messages { get; }
bool CanExecute();
void Execute();
}
public class SomeCommand : ICommand
{
public IEnumerable<string> Messages { get; private set; }
public bool CanExecute()
{
var messages = new List<string>();
var canExecute = true;
if (SomeCondition)
{
canExecute = false;
messages.Add("Some reason");
}
if (AnotherCondition)
{
canExecute = false;
messages.Add("Another reason");
}
Messages = messages;
return canExecute;
}
public void Execute() { }
}
Option 2: Have CanExecute() return an object which contains the bool as well as an enumerable messages property. This makes it obvious that the messages only apply to that call of CanExecute(). However, depending on where/how you're implementing (e.g. data binding), this could complicate other scenarios more than you're looking for.
public class CanExecuteResult
{
public bool CanExecute { get; set; }
public IEnumerable<string> Messages { get; set; }
}
public interface ICommand
{
CanExecuteResult CanExecute();
void Execute();
}
public class SomeCommand : ICommand
{
public CanExecuteResult CanExecute()
{
var result = new CanExecuteResult { CanExecute = true };
var messages = new List<string>();
if (SomeCondition)
{
result.CanExecute = false;
messages.Add("Some reason");
}
if (AnotherCondition)
{
result.CanExecute = false;
messages.Add("Another reason");
}
result.Messages = messages;
return result;
}
public void Execute() { }
}
Obviously, the specifics of how you want to handle the interfaces, enumerable types, etc. is up to you. The code is just a representation of the idea.
Bool CanExecute()
{
if(!CheckXXX)
throw new Exception("CheckXXX function throws an exception")
if(!CheckYYY)
throw new Exception("CheckYYY function throws an exception")
if(!CheckZZZ)
throw new Exception("CheckZZZ function throws an exception")
return true; //everything is working fine
}

Testing IObservable 'dispatcher'

I have several different 'types' of incoming events, and I want to dispatch them to different IObservables, exposed as properties, but without subscribing multiple times to the underlying UDP.
public IObservable<TimeEvent> TimeEventChannel { get; private set; }
public IObservable<SpaceEvent> SpaceEventChannel { get; private set; }
Subject<TimeEvent> _TimeSubject = new Subject<TimeEvent>();
Subject<SpaceEvent> _SpaceSubject = new Subject<SpaceEvent>();
public EventDispatcher(IChannelListener listener)
{
TimeEventChannel = _TimeSubject;
SpaceEventChannel = _SpaceSubject;
listener.Data.Subscribe(SwitchEvent);
}
private void SwitchEvent(AbstractEvent e)
{
switch(e.EventType)
{
case EEventType.Time: _TimeSubject.OnNext(e as TimeEvent); break;
case EEventType.Space: _SpaceSubject.OnNext(e as SpaceEvent); break;
}
}
(listener.Data is an IObservable<AbstractEvent>).
The problem I'm having is trying to work out how to test this in isolation (without hooking up to UDP)
var spaceEvent = new SpaceEvent();
var udpSubject = new Subject<AbstractEvent>();
var mock = new Mock<IChannelListener>();
mock.SetupGet(listener => listener.Data).Returns(udpSubject);
var dispatcher = new EventDispatcher(mock.Object);
subject.OnNext(spaceEvent);
var result = dispatcher.SpaceEventChannel.SingleOrDefault();
As it stands, the test blocks on the last line, and I'm pretty sure it's because there's something I've fundamentally not grokked about how Subject works.
Question: What am I thinking wrong? How should I go about testing this particular use case? Am I implementing the Dispatcher backwards too?
Just in case, this is what the real ChannelListener currently looks like:
public ChannelListener(UdpClient udpClient, FrameInterpreter frameInterpreter)
{
Data = Observable.Defer(() =>
{
IPEndPoint ep = null;
return Observable.FromAsyncPattern<byte[]>(
udpClient.BeginReceive,
i => udpClient.EndReceive(i, ref ep)
)()
.Select(bytes => frameInterpreter.ParseFrame(bytes));
});
}
public IObservable<AbstractEvent> Data { get; private set; }
I think the problem is in the lines:
subject.OnNext(spaceEvent);
var result = dispatcher.SpaceEventChannel.SingleOrDefault();
Try replacing it with:
AbstractEvent result = null;
dispatcher.SpaceEventChannels.Subscribe(e => result = e);
subject.OnNext(spaceEvent);
// ...
The problem is that when you call subject.OnNext, it runs thru the "pipeline" * immediately*. Therefore, the next line's SingleOrDefault actually locks the text, because no value ever "arrives" to it.
The primary issue you have is simple. This line:
listener.Data.Subscribe(SwitchEvent);
Returns an IDisposable. Which immediately goes out of scope and is disposed. So SwitchEvent never fires. You just need to hold that IDisposable in an instance variable in the EventDispatcher class.
private IDisposable _subscription;
public EventDispatcher(IChannelListener listener)
{
TimeEventChannel = _TimeSubject;
SpaceEventChannel = _SpaceSubject;
_subscription = listener.Data.Subscribe(SwitchEvent);
}
I would also seriously consider changing EventDispatcher to accept an IObservable<AbstractEvent> rather than IChannelListener if that's all it really needs. You can imagine how much easier this would be to test too!

.NET Remoting Singleton memory leak, TCP, Marshal by Reference

I am using the simplest example of remoting that I could find, sharing an object between a windows service and a windows forms program (client), running on the same machine.
The service instantiates the object like this:
serviceConfigRemote = new serviceConfigDataRemote();
serverChannel = new TcpServerChannel(9090);
ChannelServices.RegisterChannel(serverChannel, false);
RemotingServices.Marshal(this.serviceConfigRemote, "ServiceConfigData");
The client establishes a connection like this:
TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, false);
configData = (serviceConfigDataRemote)Activator.GetObject(typeof(serviceConfigDataRemote), "tcp://localhost:9090/ServiceConfigData");
The idea is for the service to be able to make changes to some of the parameters of the object, for the client to be able to read those changes.
The object itself is:
public sealed class serviceConfigDataRemote : MarshalByRefObject
{
private bool myConnectedFlag;
private bool mySendingFlag;
private bool myUpdateFlag;
private string myClientConfiguration;
static readonly serviceConfigDataRemote instance = new serviceConfigDataRemote();
static serviceConfigDataRemote()
{
}
public serviceConfigDataRemote()
{
myConnectedFlag = false;
mySendingFlag = false;
myUpdateFlag = false;
myClientConfiguration = "";
}
public static serviceConfigDataRemote Instance
{
get
{
return instance;
}
}
public override object InitializeLifetimeService()
{
return (null);
}
public bool Connected
{
get { return myConnectedFlag; }
set { myConnectedFlag = value; }
}
public bool Sending
{
get { return mySendingFlag; }
set { mySendingFlag = value; }
}
public bool CheckForUpdates
{
get{return myUpdateFlag;}
set { myUpdateFlag = value; }
}
public string ClientConfiguration
{
get { return myClientConfiguration; }
set { myClientConfiguration = value; }
}
}
While the service is running by itself, the Mem Usage in Task Manager stays constant, even though the service is continually updating the object with status information. When the client is started, both begin to increase in Mem Usage, and never go down.
This is the problem that I referred to in My Previous Question about finding memory leaks.
It is appearing differently on different machines, some show no memory increases, but the machines that do will reliably reproduce this problem. Running .NET Memory Profiler shows that on the service, there is an ever increasing number of "New instances", with only one or two "Removed" in the tab Types/Resources where Namespace/System is Kernel and Name/Resource is HeapMemory. I'm still trying to learn how to use the Memory Profiler, so I apologize if this is the wrong information, and tip on where else I should be looking would also be appreciated.
This object is instantiated once, with just a couple of parameters to read and write, no file io, no allocating of memory that I can see, and yet my memory usage only appears to go up the moment I start a connection from the client to that object and read its values. Any and all input would be appreciated, as I would like to avoid pulling this code and replacing it with named pipes or similar, but I'm quickly approaching that point as my only option.
Shouldn't where your service instantiates the object,
serviceConfigRemote = new serviceConfigDataRemote();
look like
serviceConfigRemote = serviceConfigDataRemote.Instance;
instead?
At the very least, the way you have it, you're creating two different instances on the server side, one in the static instance member initializer to be used by the Instance property and another one via the new serviceConfigDataRemote() explicit construction. It may also serve you well to add a private constructor to that class so nothing else can instantiate the singleton other than the static initializer.
This may not be the solution to the ever-increasing memory, but it definitely appears to be something of an issue to address.
EDIT:
Here are a couple more tips I found scouring the 'nets:
Add [MTAThread] to the main method of the host service.
RemotingServices.Disconnect(this.serviceConfigRemote); when you're shutting down the host service.
Hope this may assist.
Have you tried using lazy instantiation on your Singleton. It's possible that it doesn't like the way you're instantiating it.
public sealed class serviceConfigDataRemote : MarshalByRefObject
{
private bool myConnectedFlag;
private bool mySendingFlag;
private bool myUpdateFlag;
private string myClientConfiguration;
static serviceConfigDataRemote instance;
static serviceConfigDataRemote()
{
}
public serviceConfigDataRemote()
{
myConnectedFlag = false;
mySendingFlag = false;
myUpdateFlag = false;
myClientConfiguration = "";
}
public static serviceConfigDataRemote Instance
{
get
{
if (instance == null)
{
lock (new Object())
{
if (instance == null)
{
instance = new serviceConfigDataRemote();
}
return instance;
}
}
return instance;
}
}
public override object InitializeLifetimeService()
{
return (null);
}
public bool Connected
{
get { return myConnectedFlag; }
set { myConnectedFlag = value; }
}
public bool Sending
{
get { return mySendingFlag; }
set { mySendingFlag = value; }
}
public bool CheckForUpdates
{
get { return myUpdateFlag; }
set { myUpdateFlag = value; }
}
public string ClientConfiguration
{
get { return myClientConfiguration; }
set { myClientConfiguration = value; }
}
}
Since the only OS you are seeing this bug in is XP, there are a couple possible issues.
XP has a incoming connection limit of 10 (on pro) or 5 (on home) , and this could play a part in the issue.
Ensure that all service packs/patches are installed. I know this may be a corny and cliche answer to any problems, but the fact this issue only appears in XP implies it is OS related.
Also, not sure how you're using the service, but Windows XP is a desktop OS, not a server OS. If you intend the service to be a server of some type, you really should be using 2000/2003/2008 etc, especially since it only has issues on XP.

Using CallExternalMethodActivity/HandleExternalEventActivity in StateMachine

I'm attempting to make a StateMachine execute some database action between states.
So I have a "starting" state that uses CallExternalMethodActivity to call a "BeginExecuteNonQuery" function on an class decorated with ExternalDataExchangeAttribute. After that it uses a SetStateActivity to change to an "ending" state.
The "ending" state uses a HandleExternalEventActivity to listen to a "EndExecuteNonQuery" event.
I can step through the local service, into the "BeginExecuteNonQuery" function.
The problem is that the "EndExecuteNonQuery" is null.
public class FailoverWorkflowController : IFailoverWorkflowController
{
private readonly WorkflowRuntime workflowRuntime;
private readonly FailoverWorkflowControlService failoverWorkflowControlService;
private readonly DatabaseControlService databaseControlService;
public FailoverWorkflowController()
{
workflowRuntime = new WorkflowRuntime();
workflowRuntime.WorkflowCompleted += workflowRuntime_WorkflowCompleted;
workflowRuntime.WorkflowTerminated += workflowRuntime_WorkflowTerminated;
ExternalDataExchangeService dataExchangeService = new ExternalDataExchangeService();
workflowRuntime.AddService(dataExchangeService);
databaseControlService = new DatabaseControlService();
workflowRuntime.AddService(databaseControlService);
workflowRuntime.StartRuntime();
}
...
}
...
public void BeginExecuteNonQuery(string command)
{
Guid workflowInstanceID = WorkflowEnvironment.WorkflowInstanceId;
ThreadPool.QueueUserWorkItem(delegate(object state)
{
try
{
int result = ExecuteNonQuery((string)state);
EndExecuteNonQuery(null, new ExecuteNonQueryResultEventArgs(workflowInstanceID, result));
}
catch (Exception exception)
{
EndExecuteNonQuery(null, new ExecuteNonQueryResultEventArgs(workflowInstanceID, exception));
}
}, command);
}
What am I doing wrong with my implementation?
-Stan
I can't tell from the code snippet but make sure you are using the ExternalDataExchangeService to host your service and don't add you service directly to the runtime. The ExternalDataExchangeService is responsible for adding the required eventhandlers and turning the events into queued messages for the workflow.
I'm using ExternalDataExchangeService without code by changing my config file as shown here :

Categories

Resources