wcf callback + save session not operationcontext - wcf

I'm new to stackoverflow however I use it everyday. Today I need you because I dont get this info anywhere.
My question is:
I want to make a service with callback to clients but I dont want to callback in the function they call in the service. (something like subscriber/publisher)
I want to save the callback instance.
Then I want a service calling a function in my service that will trigger the callbacks(like this: callbacks.PrintMessage("Message"));)
Saving the callback instance in a static list in a static class.
When calling the callback.function() Im getting this error: "you are using Disposed object"
because Im getting the instance with this: OperationContext.Current.GetCallbackChannel<"callback interface">
What can I do to save that callback instances?
Thanks a lot.
Pedro
CODE:
//FUNCTION IN MY SERVICE
public void Subscribe()
{
var callback = OperationContext.Current.GetCallbackChannel<IMonitoringWebServiceCallback>();
callbacks.Add(callback);
callback = OperationContext.Current.GetCallbackChannel<IMonitoringWebServiceCallback>();
AlarmCallbackSingleton.Instance.AddCallback(callback);
//callback.PrintString("String"); //HERE IT WORKS! BUT I DONT WANT CALL HERE!
alarmInfoHandler = new AlarmInfoEventHandler(AlarmInfoHandler);
NewAlarmInfo += alarmInfoHandler;
}
//FUNCTION IN THE SAME SERVICE CALLED BY OTHER CLIENT
public void PublishAlarm(string alarm)
{
AlarmInfoEventArgs e = new AlarmInfoEventArgs();
e.Alarm = alarm;
NewAlarmInfo(this, e);
}
public void AlarmInfoHandler(object sender, AlarmInfoEventArgs e)
{
List<IMonitoringWebServiceCallback> callbacks = AlarmCallbackSingleton.Instance.GetCallbacks();
//EVERYONE THAT SUBSCRIBED SHOULD EXECUTE THIS (HERE I GET THE DISPOSED ERROR)
callbacks.ForEach(x => x.ShowString("String!"));
}

Ok. I got it! The answer to this question is as simple as this:
When you subscribe to the service you need to save somewhere(List etc..) the OperationContext and not the callback object.
Then when the PublishAlarm is called by another client the event is triggered and you need to get OperationContext of all clients that subscribe.
I saved that objetcs in a static List(singleton class) just for the example.
Then:
public void AlarmInfoHandler(object sender, AlarmInfoEventArgs e)
{
var operation = AlarmCallbackSingleton.Instance.operationContext
var callback = operation.GetCallbackChannel<IMonitoringWebServiceCallback>();
callback.ShowAlarm(); //function you want to call
}
Hope this can help!

Related

WebClient synchronous call does not return from within a filter stack trace

In a Spring Gateway API I have a filter which calls a class to make a call to another API using WebClient. If I make the same call from say a controller the call returns. However when this webclient call is made from within the Filter stack it never returns. I am trying to make this call synchronously. I cannot use the block() method because Reactive classes error.
Here is the method in question:
public void doPost() {
ApiResponse<Void> response = webClientBuilder.build().post()
.uri("http://localhost:8080")
.retrieve()
.bodyToMono(new ParameterizedTypeReference<ApiResponse<Void>>() {})
.block();
}
I am very new to WebClient and need someone to tell me how I can synchronously make this call. I have tried another variation which is toFuture().get() instead of the last line but this also does not return.
It get the below error:
java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-4
My mistake it is an authentication filter that this is being run from:
public class AuthServiceAuthenticationManager implements ReactiveAuthenticationManager {
private final MyClient myClient;
#Override
public Mono<Authentication> authenticate(Authentication authentication) {
//Below line does not return using my webclient
myClient.post();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), new ArrayList<GrantedAuthority>());
return Mono.just(token);
}
}
As I mentioned in comment, the reason is simple - you and blocking doPost is called from the reactive flow. WebClient is a non-blocking client and as you are using it from the ReactiveAuthenticationManager you could keep the whole flow reactive.
Solution:
Remove block() from the doPost and return Mono.
public Mono<ApiResponse<Void>> doPost() {
return webClientBuilder.build().post()
.uri("http://localhost:8080")
.retrieve()
.bodyToMono(new ParameterizedTypeReference<ApiResponse<Void>>() {})
}
Construct reactive flow in AuthServiceAuthenticationManager.
Logic of authenticate is not really clear but based on your example it could look like
public Mono<Authentication> authenticate(Authentication authentication) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), new ArrayList<>());
return doPost()
.thenReturn(token);
}

Actors ReceiveAsync method unable to POST data to the listener

Background
Notification service has a Notify method which is invoked when an event occurs, so here Im creating the FloorActor and sending the message consisting data and post url to the Actor.
public class NotificationService
{
//HttpClient client = new HttpClient();
ActorSystem notificationSystem = ActorSystem.Create("NotificationSystem");
public void Notify(int clientID, FloorEventData data)
{
try
{
string postUrl = "http://localhost:6001";
FloorData floorData = new FloorData() { Data = data,PostURL=postUrl };
//This commented line of code post data and listener gets the POST request
//client.PostAsJsonAsync<FloorEventData>(postUrl, data);
//Create Floor Actor
var floorActor = notificationSystem.ActorOf<FloorActor>("floorActor");
floorActor.Tell(data);
}
catch (Exception exception)
{
//Log exception
}
}
}
ReceiveAsync method of the Floor Actor data just posts the event data to the specified URL.Framework used to implement Actor Model :Akka.Net
public class FloorActor : ReceiveActor
{
HttpClient client = new HttpClient();
public FloorActor()
{
ReceiveAsync<FloorData>(floorActor => client.PostAsJsonAsync<FloorEventData>(floorActor.PostURL, floorActor.Data));
}
}
Issue-
When I debugged the issue the code flow works as expected:-
1) When event occurs Notify method is invoked
2) Notify method creates the Floor Actor and sends the data
3) Floor Actor's ReceiveAsync method is called and the line of code is executed without any errors or exceptions.But the POST listener, doesn't get the POST data request, so not sure what is happening ?
Tried POST data directly from the Notify method its works, the listener gets the POST request.You can see this code snippet commented above in the Notify method.
So when I try to POST data from my Actor's Receive method, the Http listener does not get the request and there is no errors or exception.
Please let me know if I have to change anything?
ActorSystem should be treated as a singleton for your entire system. So put that instance in a static somewhere and reference it from there.
Also try to await on client.PostAsJsonAsync

Call OutgoingHeaders using NServiceBus.Host

Using NServiceBus 4.0.11
I would like to call
Bus.OutgoingHeaders["user"] = "john";
The Header Manipulation sample shows how to call it with a custom host.
I would like to call it while using the NServiceBus.Host.
So actually I would like to have a reference to the instance of the Bus, to call OutgoingHeaders on.
Tried IWantCustomInitialization but that gives me an exception when calling CreateBus in it. INeedInitialization isn't the way to go neither.
How should I call Bus.OutgoingHeaders["user"] = "john"; while using the NServiceBus.Host?
Reading your question makes me think that you want to add this header to a certain message that you want to send during initialization/startup or when handling a message. Usually, headers have a more generic behavior as they need to be applied to more than one message.
Instead of setting the header before sending the message you can also add the header via a message mutator or behavior.
Behavior
public class OutgoingBehavior : IBehavior<SendPhysicalMessageContext>
{
public void Invoke(SendPhysicalMessageContext context, Action next)
{
Dictionary<string, string> headers = context.MessageToSend.Headers;
headers["MyCustomHeader"] = "My custom value";
next();
}
}
Mutator
public class MutateOutgoingTransportMessages : IMutateOutgoingTransportMessages
{
public void MutateOutgoing(object[] messages, TransportMessage transportMessage)
{
Dictionary<string, string> headers = transportMessage.Headers;
headers["MyCustomHeader"] = "My custom value";
}
}
Documentation
See: http://docs.particular.net/nservicebus/messaging/message-headers#replying-to-a-saga-writing-outgoing-headers for samples.

How to cancel HttpClient GET Web request

Is it possible to cancel HttpClient GET web request in Windows 8. I am looking for a solution to cancel my web request if the user press back key from the page. In my app i am using a static class for creating web request.
Alos i am using MVVM Light, and static viewmodels inside the app.
In the current situation, even if the user press the back button,
the vm stay alive and the call back reaches and executes in the VM.
So i am looking for a solution to cancel the request on back press.
Try this
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
await HttpGetRequest();
}
public CancellationTokenSource cts = new CancellationTokenSource();
private async Task HttpGetRequest()
{
try
{
DateTime now = DateTime.Now;
var httpClient = new HttpClient();
var message = new HttpRequestMessage(HttpMethod.Get, "https://itunes.apple.com/us/rss/toppaidapplications/limit=400/genre=6000/json");
var response = await httpClient.SendAsync(message, cts.Token);
System.Diagnostics.Debug.WriteLine("HTTP Get request completed. Time taken : " + (DateTime.Now - now).TotalSeconds + " seconds.");
}
catch (TaskCanceledException)
{
System.Diagnostics.Debug.WriteLine("HTTP Get request canceled.");
}
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
cts.Cancel();
}
The answer by #Farhan Ghumra is correct. Since we have moved to .Net 6 just like to add the following to the answer.
After you’re completely done with the CancellationTokenSource, dispose it directly E.g use cts.Dispose() (because you’ll most likely be using this with UI code and needing to share it with click event handling code, which means you wouldn’t be able to dispose of it with a using block)
More information can be found here.

client object model - disable event firing

Is there a way to disable event firing when doing a list item update from the Managed Client Object Model?
In the server model, I do the below. However, I cannot find a way of doing the same on the Managed Client ObjectModel:
class DisabledEventsScope : SPItemEventReceiver, IDisposable
{ // Boolean to hold the original value of the EventFiringEnabled property
bool _originalValue;
public DisabledEventsScope()
{
// Save off the original value of EventFiringEnabled
_originalValue = base.EventFiringEnabled;
// Set EventFiringEnabled to false to disable it
base.EventFiringEnabled = false;
}
public void Dispose()
{
// Set EventFiringEnabled back to its original value
base.EventFiringEnabled = _originalValue;
}
}
using (DisabledEventsScope scope = new DisabledEventsScope())
{
// State-changing operation occurs here.
spItem.Update();
}
Thanks in advance.
You can not do it in client object model, see the MSDN documentation on the SP.List object: http://msdn.microsoft.com/en-us/library/ee554951. But you can develop custom web service which will be called from a client side and disable events' firing.