I have a third party application that I'm interacting with via a WCF service that they're exposing. When my application is loaded, the WCF service is supposed to hook into the callbacks I've defined and give me data back. This is straight-forward in VB but I think my issue is syntax in accomplishing this in C#.
Their documentation states the following: Your user control will need to define an internal event with a signature that matches the event that our service is listening for.
Here are my declarations for the handler, as provided by this services' documentation:
public delegate void MyDel(ref string Param1, ref string Param2);
public event MyDel GetInfo;
The documentation then says that I should be able to call this event in the following fashion, and the data I need from the service will be inside of the output variable I pass in by reference:
string output = "";
string methodName = "SpecificAction"
// this is null and throws an exception
// i've tried wrapping it in an if != null block to no avail
GetInfo(ref methodName, ref output);
Console.WriteLine(output.ToString());
In VB the following works without issue:
Public Event GetInfo (ByRef EventName As String, ByRef XmlString As String)
Dim Output As String = ""
RaiseEvent GetInfo("SpecificAction", Output)
The reason that I think I'm doing something wrong with the C# syntax is, as I said, it seems to work in VB just fine. Any suggestions would be appreciated.
Update
So I'm calling this method from my controls' public constructor, which is failing. If I move this exact code inside of a button click handler, for instance, its returning the data that I expect. I'm guessing my program is initializing and hitting that call before their service has hooked in? Is there a way to wait for that to happen?
After seeing that the above code worked when I removed it from my constructor and placed it in a button click handler, I realized that the issue was probably that I was trying to access the data before the service had hooked into it. By instead placing the code inside of my controls Load event, I was able to get back the data I needed.
Related
I have a Xamarin android application that has a main fragment activity (named Home) which hosts a view pager and then several fragments in the view pager.
The application gets data from a bluetooth device that passes the data via an event handler once I instantiate the class.
BTScanner scanner = new BTScanner();
scanner.onScanData += BTScanner_onScanData;
The issue is, I need this event handler to be active on two of the fragments in my view pager, when that page is active. In other words, I want to receive the scan data if I am on fragment1 or fragment2, However, I can't have it go to both at the same time, there is processing of the data received and the processing is different based on which fragment you are receiving the scan data in.
What I have so far is I created a custom interface on the activity and implemented it in the fragments. It will allow me to call a method on the fragments when the view pager switches pages. Based on these methods, I can de-init the event handler on one page and init it on the other. Here is an example on the fragment activity:
private void ViewPager_PageSelected(object sender, ViewPager.PageSelectedEventArgs e)
{
int position = (int)e.Position;
ICustomFragmentLifecycleForPager fragmentToResume = (ICustomFragmentLifecycleForPager)adapter.InstantiateItem(viewPager, position);
fragmentToResume.onResumePagerFragment(previousActiveFragment);
ICustomFragmentLifecycleForPager fragmentToPause = (ICustomFragmentLifecycleForPager)adapter.InstantiateItem(viewPager, previousActiveFragment);
fragmentToPause.onPausePagerFragment();
previousActiveFragment = position;
}
Therefore, with this, I have it working as needed because when I implement the interface on the fragments, I get onPausePagerFragment called on the fragment I can de-init, and an onResumePagerFragment on the fragment I can init.
All that said, the issue I am having is actually on first startup. On first startup, I am setting the fragment to show first and when I do that, the
ViewPager_PageSelected
is not called initially, thus not calling my custom interface methods to init or de-init the scanner.
One thing I tried already is to put a method call in the onCreate of the activity (also tried it in onStartup and onResume) that would in theory only be called one time when the application starts and would then check which fragment is active at startup and force the interface methods to fire appropriately. However, this feels clunky and is not working properly. In addition to not working properly, I am also getting null exceptions in the fragment, when the interface method does fire because I force it to in onCreate of the activity, the method that is called by the interface on the fragment, onResumePagerFragment, returns a null for the activity here:
var activity = (Home)Activity;
This worked before and continues to work in other places in the code so I suspect that this is happening because the activity has not fully started yet before the interface calls the method on the fragment and it attempts to get a reference to the activity. Again, I tried doing this in onResume and onStart on the activity but I still get a null.
With all that said, what is the best way in general to handle a scenario like mine where I have the main activity which starts but then is nothing more than a fragment/view pager container and I need to have one instance to the event handler active on a fragment at a time? Should I even need to do an interface or rather use a static class? If I use a static class, I know how to get the instance of the class on each but how do you then create the event handler AND make sure to un-register is as well when another fragment grabs the instance?
Thanks!
Mike
I could not show you C# code, but below my answer could give you a hint.
https://stackoverflow.com/a/30554102/361100
Note that Android natively provides EventBus and Xamarin I found is MessageBus component alternatively.
Secondly, you can make Service so that the service is act as a delegator of all data communication whenever events are fired.
In conclusion, we could think Fragment does not gurantee to give same fragment when it restored and especially it is garbage-collected at any time when it's used with ViewPager.
Sorry for stupid question,
I just want to pass a JOSN string to the webpage in the webbrowser from my VB/C# code,
and can the javascript in webpage call the VB/C# method through some interface ?
Just like android javascript interface, many thanks
If I understand you correctly,
webBrowser2.ObjectForScripting = new ScriptClass();
webBrowser2.DocumentText = "<html><script>window.external.Test('hello')</script></html>";
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class ScriptClass
{
public void Test(string msg)
{
MessageBox.Show(msg);
}
}
So you're using a WebBrowser control and need to call a JavaScript method within the page it shows? Yeah, you can do this. It's not on the WebBrowser itself, but the HtmlDocument object, exposed by the WebBrowser's Document property, has an InvokeScript() method group, which will allow you to programatically invoke any ECMAScript-compliant method within the DOM of the page, optionally passing a series of parameters as an Object array.
That, in turn, can be used to trigger a call from JavaScript to a JSON web service (which you expose in your main CLR program, and told the page about by passing it the info via InvokeScript()). This is basic JSON/AJAX client-server scripting, all wrapped up into a single program talking to itself. It's not the most efficient way to get things done, but if you already have these layers that get the job done, and just want to release a self-contained app, it works.
I am developing an gui application in c# that uses a dll. This dll contains several common functions, like validation of properties.
However, I need to validate the properties of an object with a function like this:
public static bool validate(MyObject object)
{
bool success = true;
// some validation
if(!valid(object.property))
{
// log to database, this works
log("property is not valid"); // log to database, this works
// how can I do this?
sendMessageToForm("property is not valid");
success = false;
}
return success;
}
Additionally, validate() must return a boolean value, not a string of messages
how can I send a message to a form through a dll?
You need to add the reference of the dll in your project after that add the namespace of the dll in your class later on declare the object of the class and call the validate message and pass the parameter for validate.
If what you have shown here is the code inside your dll, I'm assuming you want to update the form from inside your dll.
The way to do that is for your dll class to publish an event, let's say ValidationError event, that will also carry with it as EventArgs the message you want to display on the form.
Then, on your form, where you instantiate the object from your dll class, you would also have to attach a listener for that event.
MyClassInDll myObject=new MyClassInDll();
myObject.ValidationError+=new EventHandler<ValidationErrorMessage>(YourMethodThatDisplaysTheMessagesOnTheForm);
Then you can use the object to call if (myObject.Validate(someOtherObject)) which will return a boolean, while still triggering the event that sends the error messages to your form.
public static bool validate(MyObject object, out message)
That will give you an output message string that can be set from where validate is called.
This is rather weird issue that I am facing with by WCF/Silverlight application. I am using a WCF to get data from a database for my Silverlight application and the completed event is not triggering for method in WCF on some systems. I have checked the called method executes properly has returns the values. I have checked via Fiddler and it clearly shows that response has the returned values as well. However the completed event is not getting triggered. Moreover in few of the systems, everything is fine and I am able to process the returned value in the completed method.
Any thoughts or suggestions would be greatly appreciated. I have tried searching around the web but without any luck :(
Following is the code.. Calling the method..
void RFCDeploy_Loaded(object sender, RoutedEventArgs e)
{
btnSelectFile.IsEnabled = true;
btnUploadFile.IsEnabled = false;
btnSelectFile.Click += new RoutedEventHandler(btnSelectFile_Click);
btnUploadFile.Click += new RoutedEventHandler(btnUploadFile_Click);
RFCChangeDataGrid.KeyDown += new KeyEventHandler(RFCChangeDataGrid_KeyDown);
btnAddRFCManually.Click += new RoutedEventHandler(btnAddRFCManually_Click);
ServiceReference1.DataService1Client ws = new BEVDashBoard.ServiceReference1.DataService1Client();
ws.GetRFCChangeCompleted += new EventHandler<BEVDashBoard.ServiceReference1.GetRFCChangeCompletedEventArgs>(ws_GetRFCChangeCompleted);
ws.GetRFCChangeAsync();
this.BusyIndicator1.IsBusy = true;
}
Completed Event....
void ws_GetRFCChangeCompleted(object sender, BEVDashBoard.ServiceReference1.GetRFCChangeCompletedEventArgs e)
{
PagedCollectionView view = new PagedCollectionView(e.Result);
view.GroupDescriptions.Add(new PropertyGroupDescription("RFC"));
RFCChangeDataGrid.ItemsSource = view;
foreach (CollectionViewGroup group in view.Groups)
{
RFCChangeDataGrid.CollapseRowGroup(group, true);
}
this.BusyIndicator1.IsBusy = false;
}
Please note that this WCF has lots of other method as well and all of them are working fine.... I have problem with only this method...
Thanks...
As others have noted, a look at some of your code would help. But some things to check:
(1) Turn off "Enable Just My Code" under Debug/Options/Debugging/General, and set some breakpoints in the Reference.cs file, to see whether any of the low-level callback methods there are getting hit.
(2) Confirm that you're setting the completed event handlers, and on the right instance of the proxy client. If you're setting the event handlers on one instance, and making the call on another, that could result in the behavior you're describing.
(3) Poke around with MS Service Trace Viewer, as described here, and see if there are any obvious errors (usually helpfully highlighted in red).
Likely there are other things you could check, but this will keep you busy for a day or so :-).
(Edits made after code posted)
(4) You might want to try defining your ws variable at the class level rather than the function. In theory, having an event-handler defined on it means that it won't get garbage collected, but it's still a little odd, in that once you're out of the function, you don't have a handle to it anymore, and hence can't do important things like, say, closing it.
(5) If you haven't already, try rebuilding your proxy class through the Add Service Reference dialog box in Visual Studio. I've seen the occasional odd problem pop up when the web service has changed subtly and the client wasn't updated to reflect the changes: some methods will get called successfully, others won't.
(6) If you're likely to have multiple instances of a proxy client open at the same time, consider merging them into one instance (and use the optional "object userState" parameter of the method call to pass the callback, so you don't run into the nasty possibility of multiple event handlers getting assigned). I've run into nasty problems in the past when multiple instances were stepping on each other, and my current best practice is to structure my code in such a way that there's only ever one client instance open at a time. I know that's not necessarily what MS says, but it's been my experience.
This issue is because of special characters in one of the fields returned from DB which browser was not able to render. After considerable debug n search over the web, was able to find this out. Used Regular expressions to remove these special characters in WCF, the new returned values from the method was successfully rendered in various browsers on different system. :)
Make sure you have checked 'Generate asynchronous operations' in your service reference. Right-click on the service reference and check the box. This solved it for me.
I have a plugin that creates an object that has an event. Is there a way for a seperate class to monitor this event, even though it does not have control of the object?
For example, I have a plugin that calls an object that uploads some data. When the data is uploaded, the event is triggered to say that this is so. In my client app, I want this to be notified when this event triggers so that it can do something.
The plugin and client will be in C#, and the event class is written in VB.net.
Would it simply be a case of the object notifying the plugin, and in turn, the plugin notifying the client app?
Is this possible?
Thanks.
EDIT (in response to request for code):
The code is fairly simple, it will be a case of in the DLL:
Object O = new Object();
O.CompleteEvent += (BLAH BLAH);
O.Run();
Now when run completes, it will trigger the CompleteEvent.
I want it to be noticed that this event has triggered within a completely different assembly that does not have the O object. The new assembly can monitor the event, however it will be outside the scope of the O object. I hope i'm explaining this okay?
As mentioned earlier, would it simply be a case of the dll then notifying the client assembly that the run is complete?
Events can be static or instance, just like any other class members. And you can subscribe static and instance methods to either type.