Unity PUN RPC call from another class - c#

Trying to call a RPC from another class. But seems like It doesn't work. How can I fix this?
Using 3 RPC in same function. So I tried to call function without RPC in a RPC function(This RPC in same class so it works flawlessly) but it doesn't work either I suppose.
chambers[i].Bullet.Fire(muzzle);// Without RPC code:
photonView.RPC("chambers["+i+"].Bullet.Fire", RpcTarget.All, new object[] { muzzle });// With RPC
Made a Debug log in Fire function. So when it works I should see it. But when I press the button I get this log(By the way i dont get this in other RPC calls).
Sending RPC "chambers[0].Bullet.Fire" to target: All or player:.

Add photon view to the bullet, and call Fire directly on it.
chambers[i].Bullet.photonView.RPC("Fire", RpcTarget.All, new object[] { muzzle });

Related

Issue in calling script synchronously from webview2 in WPF

We have a WPF application using WebView2 where one of the flows need a call originating from the WPF app to call a JS function asynchronously. The JS function in turn will call a C# method in the Host Object Proxy class which would eventually need to call another JS function but this time the call would need to be synchronous. So the call flow is something like below:
C# code calls JS function async
JS function calls C# code in host
object proxy Host object proxy method in C# would call a JS function
synchronously
A sample workflow could be a Save button in the WPF app which calls some JS function which calls back to a C# method defined in the host object proxy which needs to do a dirty check in the JS layer and hence calls another JS function. The last JS function call needs to be synchronous as it is existing code where async/await pattern introduction will lead to lot of changes.
The method that we have been using to convert a asynchronous script execution call to synchronous in the WPF app is as below:
public static T WaitWithMessagePumping<T>(Task<T> asyncAction)
{
DispatcherFrame frame = new DispatcherFrame();
asyncAction.ContinueWith(t => frame.Continue = false);
Dispatcher.PushFrame(frame);
return asyncAction.GetAwaiter().GetResult();
}
This has worked well for calls which are originating from the WPF side.
But since the call in question is actually being invoked from JS (we can see a native to managed transition in the call stack), the applications stops responding when the code reaches the Dispatcher.PushFrame(frame) API call (seems to go into deadlock).
So essentially the issue is how do we call a script synchronously from C# when the call is originating in the context of a JS function calling a host object method?
simple project link which replicates the situation: Gitlab url
This has worked for me,
if your host object has a :
public void DoStuffAsync()
{
var tmp = WaitWithMessagePumping(webView2.ExecuteScriptAsync("box1.value = '123';");
}
Instead do this :
public void DoStuffAsync()
{
webView2.Dispatcher.InvokeAsync(() =>
{ var tmp = WaitWithMessagePumping(webView2.ExecuteScript("box1.value = '123'")));};
}
It works fine.

C# - WCF Message Inspector Doesn't Run

I'm working on refactoring a project that has about 5 different web services, and each web service had a ton of identical code, including adding a message inspector onto the client endpoint behaviors so we could see the request and response data.
Part of the refactoring was to come up with a cleaner model for the web services (e.g. one abstract base service model that did all the common setup, including the addition of the message inspector).
Now, when I make the service calls (invoked via reflection), the service call works perfectly fine, and if I add a breakpoint right after the response comes back, I can see that there are 3 behaviors added to the client's endpoint:
[0] Microsoft.VisualStudio.Diagnostics.ServiceModelSink.Behavior
[1] System.ServiceModel.Description.ClientCredentials
[2] MyProject.MyMessageInspector
...but the message inspector code doesn't seem to get called at all anymore. The inspector code is currently identical to the MSDN example here (except for the class name):
https://msdn.microsoft.com/en-us/library/ms733786(v=vs.110).aspx
The primary difference is that I'm now using generic methods for setting up the client, which looks like this:
...sanity checks, etc...
TClient client = Activator.CreateInstance(typeof(TClient), binding, new EndpointAddress(url)) as TClient;
ClientBase<TInterface> _clientBase = client as ClientBase<TInterface>;
...credentials, timeout, etc...
MyEndpointBehavior _inspector = new MyEndpointBehavior()
_clientBase.Endpoint.Behaviors.Add(_inspector);
Then, when I make a call, I use this code that is located in the new abstract base class (the original code did it this way, and so far the only difference is the use of generics):
ClientBase<TInterface> _clientBase = _client as ClientBase<TInterface>;
using (new OperationContextScope(_clientBase.InnerChannel))
{
// Get the method
MethodInfo mi = _client.GetType().GetMethod(APICall);
// Make the call and return the result if successful
object response = mi.Invoke(_client, APICallParameters);
return response;
}
Any ideas why this worked prior to the switchover to generic methods and not now?
I'm not sure why this made a difference, but I re-ordered the code to move the inspector addition to happen immediately after the client creation, so the code now looks like this:
...sanity checks, etc...
TClient client = Activator.CreateInstance(typeof(TClient), binding, new
EndpointAddress(url)) as TClient;
ClientBase<TInterface> _clientBase = client as ClientBase<TInterface>;
MyEndpointBehavior _inspector = new MyEndpointBehavior()
_clientBase.Endpoint.Behaviors.Add(_inspector);
...credentials, timeout, etc...
The inspector now seems to work as expected. Strange.

Selfhost Web API parameter passing

I have middle ware with different components interacting with each other. I'm building now a selfhost Web API using OWIN and .NET WebAPI to interact with 3rd parties. My problem is that I need to pass an object reference to my controller so when the controller is called via a GET or POST request it can call function of the passed object. Dependency injection is not helping me in this case cause I need to pass a reference of an existing object and not create a new one.
The WebAPI is created in the ExternalWebAPI class start function:
public virtual void Start()
{
server = WebApp.Start<WebAPIStartup>(url: baseAddress);
UpdateStatus("Active","True");
}
Right now my controller looks like this:
class TradesController:ApiController
{
TradeRequest PostTradeRequest(TradeRequest tradeRequest)
{
return tradeRequest;
}
}
What I want to be able to do is to pass a reference to the TradesController of the ExternalWebAPI class using thisso from TradesController I would be bale to call ExternalWebAPI functions. I looked into DI, but I haven't found a good way to do it since it important to pass the instance of the ExternalWebAPI class that has started up the WebAPI cause it has other methods and events that has to be called once the TradesController's PostTradeRequest is called.
I think you are going down the wrong path here. Your API should take data in and send data out. It should not hold references to anything or call functions on those references. Call you API for the data you need to update your local reference and then call the function on that object as needed.

SignalR Client in PartialView Not Receiving

I'm still getting the basics of SignalR down. I'd like to use it in different parts of my website, so I was thinking I could start the connection in the main layout, and add client methods in sub views.
As per this answer I have :
window.hub = $.connection.hub.start();
in my Layout.cshtml, and
window.hub.done(function () {
$.connection.notificationHub.server.joinScannerGroup(1);
alert("in sub view");
});
in my subview, which works. The hub is connected, and the method JoinScannerGroup() is called. However, if i try to add:
$.connection.notificationHub.client.scanReceived = function (text) {
alert("scan received");
};
anywhere in the javascript for the subview, it never gets called. Maybe I'm undertanding it wrong, but I'd like to connect on the mainpage, and then allow any subpages to receive client calls.
Also, if I move the $.connection.start() into the subview, it does work correctly. Am I understanding it wrong?
You need to either add all client hub methods before you call hub.start(), or you need to add at least one hub method before calling hub.start() (so SignalR will subscribe to the hub) and then add all other hub methods like this:
$.connection.notificationHub.on('scanReceived ', function (text) {
alert("scan received");
});
(also see documentation)

Fire and Forget (Asynch) ASP.NET Method Call

We have a service to update customer information to server. One service call takes around few seconds, which is normal.
Now we have a new page where at one instance around 35-50 Costumers information can be updated. Changing service interface to accept all customers together is out of question at this point.
I need to call a method (say "ProcessCustomerInfo"), which will loop through customers information and call web service 35-50 times. Calling service asynchronously is not of much use.
I need to call the method "ProcessCustomerInfo" asynchronously. I am trying to use RegisterAsyncTask for this. There are various examples available on web, but the problem is after initiating this call if I move away from this page, the processing stops.
Is it possible to implement Fire and Forget method call so that user can move away (Redirect to another page) from the page without stopping method processing?
Details on: http://www.codeproject.com/KB/cs/AsyncMethodInvocation.aspx
Basically you can create a delegate which points to the method you want to run asynchronously and then kick it off with BeginInvoke.
// Declare the delegate - name it whatever you would like
public delegate void ProcessCustomerInfoDelegate();
// Instantiate the delegate and kick it off with BeginInvoke
ProcessCustomerInfoDelegate d = new ProcessCustomerInfoDelegate(ProcessCustomerInfo);
simpleDelegate.BeginInvoke(null, null);
// The method which will run Asynchronously
void ProcessCustomerInfo()
{
// this is where you can call your webservice 50 times
}
This was something I whipped just to do that...
public class DoAsAsync
{
private Action action;
private bool ended;
public DoAsAsync(Action action)
{
this.action = action;
}
public void Execute()
{
action.BeginInvoke(new AsyncCallback(End), null);
}
private void End(IAsyncResult result)
{
if (ended)
return;
try
{
((Action)((AsyncResult)result).AsyncDelegate).EndInvoke(result);
}
catch
{
/* do something */
}
finally
{
ended = true;
}
}
}
And then
new DoAsAsync(ProcessCustomerInfo).Execute();
Also need to set the Async property in the Page directive <%# Page Async="true" %>
I'm not sure exactly how reliable this is, however it did work for what I needed it for. Wrote this maybe a year ago.
I believe the issue is the fact is your web service is expecting a client to return the response to, that the service call itself is not a one way communication.
If you're using WCF for your webservices look at http://moustafa-arafa.blogspot.com/2007/08/oneway-operation-in-wcf.html for making a one way service call.
My two cents: IMO whoever put the construct on you that you're not able to alter the service interface to add a new service method is the one making unreasonable demands. Even if your service is a publicly consumed API adding a new service method shouldn't impact any existing consumers.
Sure you can.
I think what you are wanting is a true background thread:
Safely running background threads in ASP.NET 2.0
Creating a Background Thread to Log IP Information

Categories