SignalR Client - Handler for message that contains no event name? - c#

I am coding a SignalR Hub Client to get data from a web-service, and for one of the more important methods I am invoking on their server, the message I get back contains no "M: eventName" line of the sort I am using to handle the other message types (just "R:[Data] and I:[0]"). I can see the message data is all there when I enable Tracing, but how do I go about handling this with no eventName?
example:
`HubProxy.On<DataClass>("???event-name-here???", update => Console.WriteLine("OUTPUT");`
Message Trace:
23:02:34.9119843 - e1ef32d1-d374-4d7d-82b4-011d906cb096 - WS: OnMessage({"R":{"MarketName":null,"Nounce":136096,"Buys":[{"Quantity":1261.89236694,"Rate":0.00567987},{"Quantity":17.66436734,"Rate":0.00565000},{"Quantity":0.35424250,"Rate":0.00564585},{"Quantity":148.53138590,"Rate":0.00564100},{"Quantity":114.03031557,"Rate":0.00564000},{"Quantity":823.55802148,"Rate":0.00563998},{"Quantity":92.11307737,"Rate":0.00563997},{"Quantity":439.17714798,"Rate":0.00563990},{"Quantity":35.46237619,"Rate":0.00563978},{"Quantity":380.42279579,"Rate":0.00563777},{"Quantity":308.83819198,"Rate":0.00563600},{"Quantity":0.10951077,"Rate":0.00563433},{"Quantity":0.35548667,"Rate":0.00562609},{"Quantity":11.23857359,"Rate":0.00562082},{"Quantity":2.69321221,"Rate":0.00562011},{"Quantity":0.99414299,"Rate":0.00561891},{"Quantity":24.41591498,"Rate":0.00561500},{"Quantity":0.35673516,"Rate":0.00560640},{"Quantity":2.66949153,"Rate":0.00560500},{"Quantity":38.31222855,"Rate":0.00560000},{"Quantity":17.84436494,"Rate":0.00559000},{"Quantity":208.91357967,"Rate":0.00557050},{"Quantity":0.89792884,"Rate":0.00556837},{"Quantity":6.28868665,"Rate":0.00556555},{"Quantity":178.86139272,"Rate":0.00556301},{"Quantity":304.80171408,"Rate":0.00556300},{"Quantity":0.56409118,"Rate":0.00556122},{"Quantity":11.57184239,"Rate":0.00556069},{"Quantity":0.19164392,"Rate":0.00555933},{"Quantity":3.00000000,"Rate":0.00555560},{"Quantity":1579.01........

It looks like that message is not a client-invocation (what you are calling an "event") but the return value of a server call.
To use return values; use Invoke<T> instead of Invoke on the IHubProxy object.

Related

Setting up an HTTP endpoint for Azure EventGrid Webhook in my MVS Webapp?

I'm trying to create an Azure Eventgrid and Webhook response to send me inbound text messages from Azure communications services to my Azure hosted WebApp. Right now I'm having a really hard time finding documentation that shows how to create an endpoint within a Webapp controller to get the Azure webhook response to handshake and validate. I've created an endpoint within my controller that I believe should be catching the the data and processing it in a POST method, but it fails because of the arguments I'm trying to mimic. Any insight on this topic is appreciated.
I tried integrating a lot of what I found in these Docs into my app controller to try and get it to work, but I think I might be doing this all the wrong way since it says this code is for an Azure function??? I'm not entirely sure how those are used, but I tried integrating the same C# code into my controller. See Docs below:
https://learn.microsoft.com/en-us/azure/event-grid/receive-events
And here is the controller I have that is trying to imitate what I read in the docs I linked
[HttpPost("incoming")]
public async Task<IActionResult> GetFlightInfo([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest incoming,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string response = string.Empty;
BinaryData events = await BinaryData.FromStreamAsync(incoming.Body);
log.LogInformation($"Received events: {events}");
EventGridEvent[] egEvents = EventGridEvent.ParseMany(events);
foreach (EventGridEvent eventGridEvent in egEvents)
{
// Handle system events
if (eventGridEvent.TryGetSystemEventData(out object eventData))
{
// Handle the subscription validation event
if (eventData is SubscriptionValidationEventData subscriptionValidationEventData)
{
log.LogInformation($"Got SubscriptionValidation event data, validation code: {subscriptionValidationEventData.ValidationCode}, topic: {eventGridEvent.Topic}");
// Do any additional validation (as required) and then return back the below response
var responseData = new SubscriptionValidationResponse()
{
ValidationResponse = subscriptionValidationEventData.ValidationCode
};
return new OkObjectResult(responseData);
}
}
}
return new OkObjectResult(response);
}
I'd suggest to start by deploying and exploring the Azure Event Grid Viewer sample application according to the Handle SMS events for Delivery Reports and Inbound Messages tutorial.
This app is designed to consume any events generated by the Event Grid, including the SMS ones. The app utilizes SignalR, just as #roman-kiss suggests in his answer, to push the events in near real time to the user.
Once you get a good grasp of the whole flow, you can start adjusting the code to match your use case. A good first step would be adjusting the deserialization logic to take advantage of more specific models. You can get the sample JSON models for SMS events here and convert them to C#.

Response bindings for Functions with ActivityTrigger

I want to create a Durable Function that calls an Activity Function, and then returns a value using dotnet core in a v2 function app. The function will of course validate its input, so may return a successful value or it may return an invalid error: a 200 or a 400 in HTTP terms. My activity function will be something like this:
[FunctionName("MyFunc")]
public static async Task<object> Run(
[ActivityTrigger] string input,
ILogger log)
{
// return something like
return new { Status = "OK", Content = content };
}
What return type should I use for this? Should make my own DTO that would be a valid response, or is there a way of returning HttpResponse objects to the orchestrator?
I think there may be a simpler solution here. Have you considered returning a simple value if your verification passes, and throwing an exception handled by the orchestrator if your verification fails?
The ActivityTrigger binding handles both input and output. Per the docs on error handling, an activity function can return any sort of JSON-serializable object to the orchestrator, and unhandled exceptions thrown by an activity function are marshalled back to the orchestrator, where they can be handled by catch blocks.
Activity-orchestrator communication doesn't use HTTP requests and responses; it uses Azure Storage tables to record history events and Azure Storage queues to trigger activities to perform async work or wake up the orchestrator once some activity's async work has completed, respectively. Unless you specifically need an HttpResponse object somewhere in your orchestration, there's no need to wrap your activity's return value in one.

Asynchronous event execution using websockets

I have windows application that communicates to server via websockets, I use meteor server as server
and websockets4net for communication in client. when send some messages to server(json format).
server will respond to websocket in different order. I can keep track of messages sent to server.
In c# can we have produce consumer pattern, where I can store messageid and callback in dictionary
and execute callback when response recieved.
//<int, Action>(<messageid,Callback delegate>)
ConcurrentDictionary<int, Action> serverResponseCollection = new ConcurrentDictionary<int, Action>();
public send(JObject message,Action Callback)
{
socket.Send(message);
serverResponseCollection.Add(message.id,Callback);
}
void socket_MessageReceived(object sender, MessageReceivedEventArgs e)
{
//server response contains message id
//get callback function and execute
var callbackObj = serverResponseCollection[e.id];
Callback();
}
You can add a field called "Method" to the json object and set its value to the name of operation you are performing while creating a request message.
message.Add("Method", "GetUser");
The serve will also add "Method" field in the response with the same value the client has sent in the request.
And then in your response handler you can parse the value of Method field to know which operation you need to perform. And you will also get rid from mapping the message ids with callbacks.

Invalid request handling in OData

Im writing an OData webservice with C# and I need some advice on how to handle invalid requests? An example of an error would be if a customer requested a service on an item they no longer own. I would idealy like to report back to the customer exactly why it is invalid as there are multiple possible reasons.
Many thanks
I would recommend using FaultContracts as part of the OperationContract. You can define them just like DataContracts, and handle exceptions just like a custom exception.
[OperationContract]
[FaultContract(typeof(ItemNotOwned))]
Item GetItem(int ItemId);
You would define ItemNotOwned as a seperate contract definition.
Check it out on MSDN: http://msdn.microsoft.com/en-us/library/ms733841.aspx#Y323
Just throw an exception with the message containing that information. The exception will be serialized to the response sent to the client. If you don't care about the response status code, any exception will do and the client will recieve 500 (Internal Server Error). If you want a specific status code throw an instance of DataServiceException.
Look at using QueryInterceptors and ChangeInterceptors
http://robbincremers.me/2012/01/24/wcf-rest-service-with-odata-and-entity-framework-with-client-context-custom-operations-and-operation-interceptors/

WCF-Capturing the full HTTP response

I'm using WCF to call a method on a Java web service (using basicHttp with <security mode="Transport">). The service returns some HTML back instead of a SOAPFault. WCF seems to implement some odd truncating of the content returned in the exception, so I can't see the entire error.
Is there a way to get the entire response? Perhaps some configuration I can change to pull back more then 660 bytes? I tried turning on service tracing, but it doesn't seem to capture the entire response. I'm unable to use Fiddler or Charles, because the service is using two-way SSL and it's on a secure network. Here's the exception:
The content type text/html of the response message does not match the content type of the binding (text/xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 660 bytes of the response were: '<html><head><title>Server - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </he
It seems that an exception occurred on the server side. When exception occurs with httpBinding, HTTP status becomes 404 - NotFound.
It might be as a result of:
Incorrect signature of calling method and actual method, or order of parameters
Failure to serialize or deserialize the result
Some failure with SSL configuration/keys
Internal exception within WCF
In order to eliminate all the above try connecting to it using plain .NET client without SSL. Then add a level of complexity each time.
Hope this helped
Have you set IncludeExceptionDetailInFaults = True in ServiceDebugBehavior?
That might help.
You can try to capture outgoing SOAP request and send that request through HttpWebRequest class. This should allow you capturing whole response.

Categories