SignalR, passing an object from the HUB to the Client (MVC C#) - c#

I've looked around at other questions but they don't seem to fully answer this question, I'm trying to pass an object via JSON to the client Javascript. I'm using Newtonsoft.Json to make the process easier, but I can't seem to recieve the object.
Here's the code:
When a connection is made, I call the Hub using start().done() in the client javascript:
//start comm with server
$.connection.hub.start().done(function () {
console.log('Grabbing playlist data');
Playlist.server.requestPlaylist();
});
This calls the following method, which is supposed to grab the object and pass it back:
public void requestPlaylist()
{
var playlistData = (from c in db.Playlist where c.ID > 0 select c).Include(h => h.Song).ToList();
Playlist player = new Playlist();
foreach (var item in playlistData)
{
player.ID = item.ID;
player.Profile = item.Profile;
player.Song.ID = item.Song.ID;
player.Song.name = item.Song.name;
player.upvotes = item.upvotes;
}
string jsonObject = JsonConvert.SerializeObject(player);
Clients.All.recievePlaylist(jsonObject);
}
SO here, I'm searching the database, getting the results and storing it into the playlist model, then using newtonsoft.json to convert the model into a json object (Its roughly the same principle they have as an example on their site).
The client javascript that is invoked from this is:
function recievePlaylist(jsonObject) {
console.log('test to recieve data: ' + jsonObject.ID + ' test.');
};
Now just for testing purposes I'm just logging out out to the console, but this come back with nothing:
"test to recieve data: test." is how it comes back.
What am I missing?

Because you convert the object to a string on the server before passing it to the client, the client receives a string. Your string representation of a json object doesnt have an ID property so the value will be "undefined".
On the client you can use this to convert the string to a json object:
jsonObject = JSON.parse(jsonObject);
Just add that line to the top of your recievePlaylist function.
Note: You shouldn't actually need to convert your server object to a json string on the server side. SignalR automatically converts your server side objects to json objects on the client.

If you call WebAPI and receive json response/result on client side (JavaScript/jQuery). The way is general for both SignalR or WebAPI in regards of parse jsone response and the use it as object.
var obj = jQuery.parseJSON( '{ "name": "John" }' );
alert( obj.name === "John" );

Related

Loop through a json response received from facebook graph api in c# and get the latest value. (then, store it in database in dot net core)

I'm using the graph API of facebook to get the permalink of facebook posts. But it seems the endpoint always returns an array of all the posted posts.
So, I need to take the response and loop through it and get only the latest value that is always the first pair in the response.
Here is the response I get using the graph explorer. I only need the first pair from data array i.e the permalink_url and the id so that I can store them separately in a database to embed posts in my website using the permalink.
{
"data": [
{
"permalink_url": "https://www.facebook.com/347775946439542/photos/a.348021906414946/358023508748119/?type=3",
"id": "347775946439542_358023508748119"
},
{
"permalink_url": "https://www.facebook.com/347775946439542/photos/a.348021906414946/350654269485043/?type=3",
"id": "347775946439542_350654269485043"
},
{
"permalink_url": "https://www.facebook.com/347775946439542/photos/a.348021906414946/350651839485286/?type=3",
"id": "347775946439542_350651839485286"
}
],
"paging": {
"cursors": {
"before": "QVFIUlRGODNTaFZAueEUxQ2VvcHlrMUw1MGE0U0FCblhZAY1hVbFBGUHhHdXlrSkgzSm0tb05pSGpFOXBYVG9EcnN5T21sQTgtYy1jSjhrZAW9WYmg5YmpVMXpQWTRLUkQ3ZA05PcEZAjUTNyV2VuV05hRG8yVlBaa3pia3dFTVRLU05nU0pU",
"after": "QVFIUlBHMG44ZAkxHdUsxb012bVlOQ0ZAfaDhHLUZA6VEt6MHd0QjJYZADlfZAVk2aExSdlJESUU2SlVDaVJsYzI4dnlmUllZASzhKd3Nkb09aa2ZAMRHZAFTGhMVHFoQ1hjNE5zNDJ2aV96UGtVQUpBeHE1b2xUTzk2SHZALLTZA1Y3pZAZAmJOMENS"
}
}
}
I did go through some questions on this that used newtonsoft but couldn't get it to work.
So any help on how to loop through this in C# (razor page) and then return them from a method. Thenafter I need to store both the permalink as well as the id in database.
Here is my method: Here _getPermalink has the endpoint I have to hit.
Also 'str' has the response which is shown below. I have to fetch the permalink and id from that.
public string GetPermalink()
{
WebClient client = new WebClient();
Stream data = client.OpenRead(_getPermalink);
StreamReader reader = new StreamReader(data);
string str = "";
str = reader.ReadLine();
data.Close();
return str;
}
When I call this endpoint from the method:string res = facebook.GetPermalink(); (Here facebook is just a constructor with values required for making the call to endpoint such as page id, access token,etc.)
The same response looks something like this.
{"data":[{"permalink_url":"https:\/\/www.facebook.com\/347775946439542\/photos\/a.348021906414946\/358023508748119\/?type=3","id":"347775946439542_358023508748119"},{"permalink_url":"https:\/\/www.facebook.com\/347775946439542\/photos\/a.348021906414946\/350654269485043\/?type=3","id":"347775946439542_350654269485043"},{"permalink_url":"https:\/\/www.facebook.com\/347775946439542\/photos\/a.348021906414946\/350651839485286\/?type=3","id":"347775946439542_350651839485286"}],"paging":{"cursors":{"before":"QVFIUlRGODNTaFZAueEUxQ2VvcHlrMUw1MGE0U0FCblhZAY1hVbFBGUHhHdXlrSkgzSm0tb05pSGpFOXBYVG9EcnN5T21sQTgtYy1jSjhrZAW9WYmg5YmpVMXpQWTRLUkQ3ZA05PcEZAjUTNyV2VuV05hRG8yVlBaa3pia3dFTVRLU05nU0pU
I'm relatively new with the concept of json object/arrays in C# and using newtonsoft. Any help and explanations are appreciated.
(PS: Is there a way to get the permalink and id of the Latest Posts ONLY, using the facebook graph api?)
Given the JSON data you posted, you can get the first permalink URL from it using the following one-liner:
string permalinkUrl = (string)JObject.Parse(json).SelectToken("data[0].permalink_url");
Demo: https://dotnetfiddle.net/SUgz51

Is it possible to call an Dynamics CRM action with a JSON request through a WebApi with IOrganizationService?

TL;DR:
I am calling a WebApi, the WebApi authenticates against the CRM and use the IOrganizationService, so my request is a JObject and not an Entity or EntityReference, it gives me this error:
Error: Type 'Newtonsoft.Json.Linq.JToken' is a recursive collection data contract which is not supported. Consider modifying the definition of collection 'Newtonsoft.Json.Linq.JToken' to remove references to itself.
Context:
I built a web application in angular and I built a WebApi so I can call some custom actions in CRM:
Angular APP | WebApi | OnPremise CRM
So, when I call the WebApi, there is a controller that turns my request into a OrganizationRequest:
Request for WebApi:
{
"ActionName": "custom_actionname",
"Parameters":
[
{
"Key": "EntityInputParameter1",
"Value": {"#odata.type":"Microsoft.Dynamics.CRM.any_entity"}
}
]
}
I read this request on my WebApi and turn that into a request for CRM
Request for CRM:
OrganizationRequest request = new OrganizationRequest("custom_actionname");
request.Parameters["EntityInputParameter1"] = {"#odata.type":"Microsoft.Dynamics.CRM.any_entity"} // This is a JObject
OrganizationResponse response = service.Execute(request);
When I make the request, it gives me the following error:
Error: Type 'Newtonsoft.Json.Linq.JToken' is a recursive collection data contract which is not supported. Consider modifying the definition of collection 'Newtonsoft.Json.Linq.JToken' to remove references to itself.
If I make the request directly to the action it works, but I cannot do that due security policies.
One option could be turn the request into a valid CRM request (parsing {"#odata.type":"Microsoft.Dynamics.CRM.any_entity} into a Entity type) but CRM has a lot of parsing escenarios and could be very complex.
Another option could be sending the request through web and stop using the IOrganizationService but I cannot change that.
I am making this question so anybody that has this error can find the "solution" because I searched a lot and nobody refers this behavior directly.
I am probably turning my InputEntityParameter into string, and I will send the JSON, so I can parse the JSON on my action, but I was looking if anybody else had this error or another approach.
I tested it on one of my Dev Environment with Entity as Parameter.
Below is the code I used in console application to fire Action with Entity as parameter. It ran successfully
var request = new OrganizationRequest("new_test");
//request.Parameters.Add("Target", xAccountReference);
request.Parameters.Add("Param2", "abc");
request.Parameters.Add("Param1", new Entity("account",Guid.Parse("2fe32f22-d01d-ea11-80fa-005056936c69")));
Service.Execute(request);
Below is the Javascript code which used CRM Webapi to execute Action with Parameter. Ignore the XRM.Webapi command but interesting for you would be passing parameters in webapi.
var parameters = {};
parameters.Param2 = "abcd";
var param1 = {};
param1.accountid = "2fe32f22-d01d-ea11-80fa-005056936c69"; //Delete if creating new record
param1["#odata.type"] = "Microsoft.Dynamics.CRM.account";
parameters.Param1 = param1;
var new_testRequest = {
Param2: parameters.Param2,
Param1: parameters.Param1,
getMetadata: function() {
return {
boundParameter: null,
parameterTypes: {
"Param2": {
"typeName": "Edm.String",
"structuralProperty": 1
},
"Param1": {
"typeName": "mscrm.account",
"structuralProperty": 5
}
},
operationType: 0,
operationName: "new_test"
};
}
};
Xrm.WebApi.online.execute(new_testRequest).then(
function success(result) {
if (result.ok) {
//Success - No Return Data - Do Something
}
},
function(error) {
Xrm.Utility.alertDialog(error.message);
}
);
I can confirm that you are mixing Webapi and orgservice call. You can definitely call Action from Webapi of Dynamics. I just used Postman to call Action and I was successful. Blog reference to use Postman for CRM webapi
Below Body as json in Postman and I get Action to run.
{
"Param1":"string test",
"Param2":{
"accountid":"b6b35fd0-b9c3-e311-88e2-00505693000c",
"#odata.type":"Microsoft.Dynamics.CRM.account"
}
}

Invaild Json Result through Web Api in angular js

I have build a http post web api in asp which return the following string in Json
RootObject rootObject = new RootObject()
{
status = "User Registered"
};
msg = JsonConvert.SerializeObject(rootObject);
Below is my angular js controller in which I am consuming that web api
.controller('signupCtrl', function($scope,$http,$ionicPopup,$state,$ionicHistory) {
$scope.signup=function(data){
var link = 'http://xxxxxxxxxxxxxxxxxxxxxx/api/Home/RegisterUser';
//using http post
//passing values to parameter
$http.post(link, {RegisterName : data.name, RegisterUserName : data.username, RegisterPassword : data.password , RegisterEmail: data.mail , RegisterMobile : data.mobile})
.then(function (res){ //if a response is recieved from the server.
$scope.response = res; //contains Register Result
console.log($scope.response);
});
}
})
With the above code I am getting following result in google chrome console
I am try to get that status only to match it value but I am unable to do so.
The doubt I am having is that json format
console.log(JSON.stringify($scope.response)) will do what you need.
If you're wanting those particular value, you can just access those and pass them to log.
console.log($scope.response.data['status']);
you get the json as :
$scope.response = res.data;
might be you require JSON.parse(res.data) or $.parseJSON(res.data) for getting json object

Error while deserializing Azure ServiceBus Queue message sent from node.js (azure sdk)

Here's my scenario:
I'm sending an Azure ServiceBus Queue message from Node.js using the node azure sdk like so:
var message = {
body: JSON.stringify({ foo: 'Bar' })
};
serviceBusService.sendQueueMessage('myQueue', message, function (error) {
if (!error) {
console.log('msessage sent');
}
});
I have a c# worker role that is listening to the Queue:
QueueClient Client = QueueClient.CreateFromConnectionString(connStr, QueueName);
Client.OnMessage((receivedMessage) =>
{
var body = receivedMessage.GetBody<string>();
});
When the GetBody method gets executed, i get the following error:
There was an error deserializing the object of type System.String. The input source is not correctly formatted
After some digging around, i found THIS article that helped me get a solution:
Client.OnMessage((receivedMessage) =>
{
var bodyJson = new StreamReader(receivedMessage.GetBody<Stream>(), Encoding.UTF8).ReadToEnd();
var myMessage = JsonConvert.DeserializeObject<MyMessage>(bodyJson);
});
If anyone has faced this issue and found a better solution, please let me know!
Thanks!
To anyone who found this question if they were getting this error from sending the message using Service Bus Explorer (like me).
Make sure you specify the correct message type in the drop down:
Thanks for the update, I was doing the reverse and this helped me. I thought I'd add to your solution for completeness. The DeserializeObject method needs the "MyMessage" class defining. In your original post, your JSON is:
{ foo: 'Bar' }
If we drop that into json2csharp (json2csharp.com) we now have the class required to complete your solution:
public class MyMessage
{
public string foo { get; set; }
}
Of course, the dependency is having Newtonsoft.Json package added to your Visual Studio solution:
Install-Package Newtonsoft.Json -Pre
Using the nuget package: Microsoft.Azure.ServiceBus
The following info is contained inside as as comment:
If a message is only being sent and received using this Microsoft.Azure.ServiceBus
client library, then the below extension methods are not relevant and should not be used.
If this client library will be used to receive messages that were sent using both WindowsAzure.Messaging client library and this (Microsoft.Azure.ServiceBus) library, then the Users need to add a User property Microsoft.Azure.ServiceBus.Message.UserProperties while sending the message. On receiving the message, this property can be examined to determine if the message was from WindowsAzure.Messaging client library and if so use the message.GetBody() extension method to get the actual body associated with the message.
---------------------------------------------- Scenarios to
use the GetBody Extension method: ----------------------------------------------
If message was constructed using the WindowsAzure.Messaging client library as
follows:
var message1 = new BrokeredMessage("contoso"); // Sending a plain string var
message2 = new BrokeredMessage(sampleObject); // Sending an actual customer object
var message3 = new BrokeredMessage(Encoding.UTF8.GetBytes("contoso")); // Sending
a UTF8 encoded byte array object await messageSender.SendAsync(message1); await
messageSender.SendAsync(message2); await messageSender.SendAsync(message3);
Then retrieve the original objects using this client library as follows: (By
default Microsoft.Azure.ServiceBus.InteropExtensions.DataContractBinarySerializer
will be used to deserialize and retrieve the body. If a serializer other than
that was used, pass in the serializer explicitly.)
var message1 = await messageReceiver.ReceiveAsync(); var returnedData1 = message1.GetBody();
var message2 = await messageReceiver.ReceiveAsync(); var returnedData2 = message1.GetBody();
var message3 = await messageReceiver.ReceiveAsync(); var returnedData3Bytes =
message1.GetBody(); Console.WriteLine($"Message3 String: {Encoding.UTF8.GetString(returnedData3Bytes)}");
------------------------------------------------- Scenarios to NOT use the GetBody
Extension method: ------------------------------------------------- If message
was sent using the WindowsAzure.Messaging client library as follows: var message4
= new BrokeredMessage(new MemoryStream(Encoding.UTF8.GetBytes("contoso"))); await
messageSender.SendAsync(message4); Then retrieve the original objects using this
client library as follows: var message4 = await messageReceiver.ReceiveAsync();
string returned = Encoding.UTF8.GetString(message4.Body); // Since message was
sent as Stream, no deserialization required here.
May it help you
With the latest Service Bus client libraries (.NET, JS, Java, Python), you can send message(s) using the JS library like this:
const serviceBusClient = new ServiceBusClient("<connectionstring>");
const sender = serviceBusClient.createSender("<queuename>");
await sender.sendMessages([{
body: {
title: "hello"
}
}]);
Note that .sendMessages takes a list as an input, even if you're just sending one message.
And get the body of the received message using .NET library like this:
await using var client = new ServiceBusClient("<connectionstring>");
ServiceBusReceiver receiver = client.CreateReceiver("<queuename>");
ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();
string body = receivedMessage.Body.ToString();
Console.WriteLine(body); //prints {"title":"hello"}

how to pass large json string to web service using [webinvoke]

I have a problem passing a large JSON string to a web service from the client side with a jQuery function. When the lenth of the string increases to 1000 characters, the web service throw an exception "Unspecified Network Error". Please let me know how to pass a large JSON value to a web service using [webinvoke].
Can we increase the size of url or whatever to fix this problem?
You can serialize your Json as object:
page.asp
var data1 = {
IdTest: ('<%= miAspVar %>'),
fono: telefono,
etc, etc
};
var strData = YAHOO.lang.JSON.stringify(data1)
callService(testLlamada, strData, EstadoLlamada, onError2);
function onError2(result) {
alert(result);
}
function EstadoLlamada(result) {
...
}

Categories