I am trying to get the below working from https://github.com/simplefx-ltd/simplefx-api
Request:
{
"H":"quotessubscribehub",
"M":"getLastPrices",
"A":[["BTCUSD","LTCUSD","ETHUSD","TLRY.US","GWPH.US"]],
"I":0
}
hub - quotessubscribehub
method - getLastPrices
arguments:
0 - list of instruments - ["BTCUSD","LTCUSD","ETHUSD","TLRY.US","GWPH.US"]
My first attempt in c# is as follows;
[Command]
public async void LiveTrades()
{
var trades = new List<String>() { "BTCUSD", "LTCBTC" };
var hubConnection = new HubConnection("https://webquotes-v3.simplefx.com/signalr/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("quotessubscribehub");
hubConnection.Headers.Add("H", "quotessubscribehub");
hubConnection.Headers.Add("M", "getLastPrices");
hubConnection.Headers.Add("A", trades.ToString());
hubConnection.Headers.Add("I", "0");
stockTickerHubProxy.On<LiveSymbols>("getLastPrices", stock => TradePrice = stock.R.Data.ToString());
await hubConnection.Start();
}
I'm not 100%, but maybe the arguments list is causing me the main problem.
Any help would be gratefully accepted.
Many thanks
Scott
**Edit:
Looks like I have the list of instruments correct now.
var trades = new List<String>() { "BTCUSD", "LTCBTC" };
string output = new JavaScriptSerializer().Serialize(trades);
returns
["BTCUSD","LTCBTC"]
Connection seems good, but not returning any items to me. Will keep trying
This solved it.
var trades = new List<String>() { "BTCUSD", "LTCBTC" };
await hubConnection.Start();
var returnValue = await stockTickerHubProxy.Invoke<R>("getLastPrices", trades);
Related
I'am trying to test persistence actor, but behavior is wierd.
My tested actor:
public class PredictionManager : ReceivePersistentActor
{
public override string PersistenceId => _persistanceId;
public PredictionManager(string persistenceId)
{
_persistanceId = persistenceId;
Command<AddPredictionRequest>(OnPrediction);
Recover<SnapshotOffer>(x => OnRecover((PredictionManagerState)x.Snapshot), x => x.Snapshot is PredictionManagerState);
}
private void OnPrediction(AddPredictionRequest request)
{
/* some code */
_state.Add(request);
SaveSnapshot(_state);
}
private void OnRecover(PredictionManagerState state)
{
foreach(var request in state.RequestMap)
{
OnPrediction(request.Value);
}
}
}
My state save all messages and deletes them after manager actor recieve some message. When I try to debug my test, Recover function called first and after this called OnPrediction. My question is - how it's possible? If data stores in momory, why it have SnapshotOffer? Also I have tried to generate new percistenceId from Guid.NewGuid() but it doesn't work.
public void AddPrediction_PassToChild_CreateNewManager_PassToChild()
{
var sender = CreateTestProbe(Sys);
var persistanceId = "AddPrediction_PassToChild_CreateNewManager_PassToChild";
var props = Props.Create(() => new PredictionManager(Mock.Of<IEventBus>(), persistanceId));
var predictionManager = ActorOf(props);
var message = new PredictionManager.AddPredictionRequest(Props.Create(() => new ChildTestActor(sender.Ref)),
new StartPrediction<IPredictionParameter>("a", 1, "a", new Param() ));
//Act
predictionManager.Tell(message, sender);
sender.ExpectMsg<string>(x => x == "ok", TimeSpan.FromSeconds(15));
Sys.Stop(predictionManager);
predictionManager = Sys.ActorOf(props);
sender.ExpectMsg<string>(x => x == "ok", TimeSpan.FromSeconds(15));
Sys.Stop(predictionManager);
}
I found out that default storage for snapshots is LocalStorage not MemoryStorage. So it stores snapshots in files, and this is why it has SnapshotOffer after app restart. But I still can't get why Guid.NewGuid() as persistanceId is not working.
I would like to build an app that i'll use for myself so i'm targeting the simple authentification through Token.
I had my token from Discog and i know it works because i tried it in a third party app.
I'm using DiscogClient which seems to be the most popular client.
I'm following the Sample usage in the following way :
var tokenInformation = new TokenAuthenticationInformation("My token"); // i'm using my real token of course
//Create discogs client using the authentication
var discogsClient = new DiscogsClient.DiscogsClient(tokenInformation);
var discogsSearch = new DiscogsSearch()
{
artist = "Michael Jackson"
};
//Retrieve observable result from search
var observable = discogsClient.Search(discogsSearch);
I dont have any exception when i run that code, but if i look at the observable var in debug mode, there is no result whatsoever.
I'm lost and am seeking help.
Thanks in advance
ok so this is how i made it work, sound simple but i'm not used to thread programming.
var tokenInformation = new TokenAuthenticationInformation("My token"); // i'm using my real token of course
{
//Create discogs client using the authentication
var discogsClient = new DiscogsClient.DiscogsClient(tokenInformation);
var discogsSearch = new DiscogsSearch()
{
artist = "Michael Jackson"
};
await SearchDis(discogsClient, discogsSearch);
}
then the function
private async static Task SearchDis (DiscogsClient.DiscogsClient dc, DiscogsSearch ds)
{
var res = await dc.SearchAsync (ds);
}
I am trying to build a small app in C# to retrieve suggested meeting times from the Microsoft Graph API. After authenticating, I call graphClient.HttpProvider.SendAsync(t); to hopefully get suggested meeting times. However, stepping through with breakpoints everything seems to go fine until that call and then the FindMeetingTimes request content is empty/null.
Calling with: eventsService.RunAsync();
internal async Task RunAsync()
{
try
{
// Create request object
var findMeetingTimeRequest = new FindMeetingTimeRequestModel
{
Attendees = new List<AttendeeBase>
{
new AttendeeBase
{
EmailAddress = new EmailAddress {Address = "myaddress#domain.com" },
Type = AttendeeType.Required
}
},
LocationConstraint = new LocationConstraint
{
IsRequired = true,
SuggestLocation = false,
Locations = new List<LocationItemModel>
{
new LocationItemModel{ DisplayName = "A116", Address = null, Coordinates = null }
}
},
TimeConstraint = new TimeConstraintModel
{
TimeSlots = new List<TimeSlotModel>
{
new TimeSlotModel
{
Start = new DateTimeValueModel
{
Date = "2018-03-23",
Time = "08:00:00",
TimeZone = "Central Standard Time"
},
End = new DateTimeValueModel
{
Date = "2018-03-23",
Time = "09:00:00",
TimeZone = "Central Standard Time"
}
}
}
},
MeetingDuration = new Duration("PT1H"),
MaxCandidates = 99,
IsOrganizerOptional = false,
ReturnSuggestionHints = false
};
GraphServiceClient graphClient = SDKHelper.GetAuthenticatedClient();
var t = graphClient.Me.FindMeetingTimes(findMeetingTimeRequest.Attendees, findMeetingTimeRequest.LocationConstraint, findMeetingTimeRequest.TimeConstraint, findMeetingTimeRequest.MeetingDuration, findMeetingTimeRequest.MaxCandidates, findMeetingTimeRequest.IsOrganizerOptional).Request().GetHttpRequestMessage();
await graphClient.AuthenticationProvider.AuthenticateRequestAsync(t);
var response = await graphClient.HttpProvider.SendAsync(t);
var jsonString = await response.Content.ReadAsStringAsync();
Console.WriteLine(jsonString);
return;
}catch(Exception ex)
{
Console.WriteLine(ex.Message);
return;
}
}
I'm sort of at a loss as to what to try next. I have looked through examples and there's only a handful out there so far that use GraphServiceClient/SDKHelper to authenticate. Could this be part of the problem?
I get both exceptions during await graphClient.HttpProvider.SendAsync(t);:
Exception thrown: 'Microsoft.Graph.ServiceException' in Microsoft.Graph.Core.dll
Exception thrown: 'System.NullReferenceException' in System.Web.dll
Update: Using both the reference in Michael's comment below and the original code with an empty argument list for FindMeetingTimes(), I'm getting a credentials exception:
"Code: ErrorAccessDenied\r\nMessage: Access is denied. Check credentials and try again.\r\n\r\nInner error\r\n"
Calling with
await eventsService.EventFindMeetingsTimes(graphClient);
public async System.Threading.Tasks.Task EventFindMeetingsTimes(GraphServiceClient graphClient)
{
try
{
User me = await graphClient.Me.Request().GetAsync();
// Get the first three users in the org as attendees unless user is the organizer.
var orgUsers = await graphClient.Users.Request().GetAsync();
List<Attendee> attendees = new List<Attendee>();
Attendee attendee = new Attendee();
attendee.EmailAddress = new EmailAddress();
attendee.EmailAddress.Address = "name#domain.com";
attendees.Add(attendee);
// Create a duration with an ISO8601 duration.
Duration durationFromISO8601 = new Duration("PT1H");
MeetingTimeSuggestionsResult resultsFromISO8601 = await graphClient.Me.FindMeetingTimes(attendees,
null,
null,
durationFromISO8601,
2,
true,
false,
10.0).Request().PostAsync();
List<MeetingTimeSuggestion> suggestionsFromISO8601 = new List<MeetingTimeSuggestion>(resultsFromISO8601.MeetingTimeSuggestions);
}
catch (Exception e)
{
Console.WriteLine("Something happened, check out a trace. Error code: {0}", e.Message);
}
}
The account I'm using to log in works when I test with the GraphExplorer. Is it possible the credentials/token aren't being passed down through the web form and into the graph client?
SOLUTION: Graph Docs example <-- Provided by Michael helped set up the formatting correctly.
Find meeting times problem #559 <-- Tipped off by Marc that the permissions in the end needed updated and eventually solved my updated problem.
You forgot to set the HttpMethod before SendAsync(t). It is using GET instead of POST.
t.Method = System.Net.Http.HttpMethod.Post;
With that said, I agree with Mark. Use the built in functionality of the client library:
https://github.com/microsoftgraph/msgraph-sdk-dotnet/blob/dev/tests/Microsoft.Graph.Test/Requests/Functional/EventTests.cs#L88
Without more detail, it is difficult to determine what is going wrong here. That said, you should start with simplifying this code. That will at least reduce the number of moving parts:
var result = await graphClient.Me.FindMeetingTimes()
.Request()
.PostAsync();
if (!string.IsNullOrWhiteSpace(result.EmptySuggestionsReason))
{
Console.WriteLine(result.EmptySuggestionsReason);
}
else
{
foreach (var item in result.MeetingTimeSuggestions)
{
Console.WriteLine($"Suggestion: {item.SuggestionReason}");
}
}
If this fails, be sure to capture the entire exception and update your question.
I am having a scenario in CRM where I need to update multiple accounts values(text fields and option sets) with values from an external sql database table. How can I go about doing this using the execute multiple request. The requirement is to sync all the account data in CRM with our ERP data which comes from a sql table. This process needs to be automated so i opted to use a windows service that runs daily to update accounts that ar flagged for update in the external sql table. I am struggling to find the best approach for this,I tested this idea in a console application on DEV and here is my solution code below. My question is how can I do this better using ExecuteMultipleRequest request.
public static void UpdateAllCRMAccountsWithEmbraceAccountStatus(IOrganizationService service, CRM_Embrace_IntegrationEntities3 db)
{
List<C_Tarsus_Account_Active_Seven__> crmAccountList = new List<C_Tarsus_Account_Active_Seven__>();
//Here I get the list from Staging table
var crmAccounts = db.C_Tarsus_Account_Active_Seven__.Select(x => x).ToList();
foreach (var dbAccount in crmAccounts)
{
CRMDataObjectFour modelObject = new CRMDataObjectFour()
{
ID = dbAccount.ID,
Account_No = dbAccount.Account_No,
Account_Name = dbAccount.Account_Name,
Account_Status = Int32.Parse(dbAccount.Account_Status.ToString()),
Country = dbAccount.Country,
Terms = dbAccount.Terms
};
}
var officialDatabaseList = crmAccounts;
//Here I query CRM to
foreach (var crmAcc in officialDatabaseList)
{
QueryExpression qe = new QueryExpression();
qe.EntityName = "account";
qe.ColumnSet = new ColumnSet("accountnumber", "new_embraceaccountstatus");
qe.Criteria.AddCondition("statecode", ConditionOperator.Equal, 0);
qe.Criteria.AddCondition("accountnumber", ConditionOperator.NotIn, "List of acconts for example"
);
EntityCollection response = service.RetrieveMultiple(qe);
//Here I update the optionset value
foreach (var acc in response.Entities)
{
if (acc.Attributes["accountnumber"].ToString() == crmAcc.Account_No)
{
if (acc.Contains("new_embraceaccountstatus"))
{
continue;
}
else
{
acc.Attributes["new_embraceaccountstatus"] = new OptionSetValue(Int32.Parse(crmAcc.Account_Status.ToString()));
}
service.Update(acc);
}
}
}
}
I know this might not be the right approach, please advise me how to use ExecuteMultipleRequest or perhaps a different solution altogether.
Here is some helper methods I've used before to handle this:
public static ExecuteMultipleRequest MultipleRequest { get; set; }
private const int BatchSize = 250;
public static long LastBatchTime { get; set; }
private static void Batch(IOrganizationService service, OrganizationRequest request)
{
if (MultipleRequest.Requests.Count == BatchSize)
{
ExecuteBatch(service);
}
MultipleRequest.Requests.Add(request);
}
private static void ExecuteBatch(IOrganizationService service)
{
if (!MultipleRequest.Requests.Any())
{
return;
}
Log("Executing Batch size {0}. Last Batch was executed in {1}",MultipleRequest.Requests.Count, LastBatchTime);
var watch = new System.Diagnostics.Stopwatch();
watch.Start();
var response = (ExecuteMultipleResponse)service.Execute(MultipleRequest);
watch.Stop();
LastBatchTime = watch.ElapsedMilliseconds;
Log("Completed Executing Batch in " + watch.ElapsedMilliseconds);
WriteLogsToConsole();
var errors = new List<string>();
// Display the results returned in the responses.
foreach (var responseItem in response.Responses)
{
// A valid response.
if (responseItem.Fault != null)
{
errors.Add(string.Format(
"Error: Execute Multiple Response Fault. Error Code: {0} Message {1} Trace Text: {2} Error Keys: {3} Error Values: {4} ",
responseItem.Fault.ErrorCode,
responseItem.Fault.Message,
responseItem.Fault.TraceText,
responseItem.Fault.ErrorDetails.Keys,
responseItem.Fault.ErrorDetails.Values));
}
}
MultipleRequest.Requests.Clear();
if (errors.Any())
{
throw new Exception(string.Join(Environment.NewLine, errors));
}
}
You can then call this from your normal logic like so:
public static void UpdateAllCRMAccountsWithEmbraceAccountStatus(IOrganizationService service, CRM_Embrace_IntegrationEntities3 db)
{
List<C_Tarsus_Account_Active_Seven__> crmAccountList = new List<C_Tarsus_Account_Active_Seven__>();
//Here I get the list from Staging table
var crmAccounts = db.C_Tarsus_Account_Active_Seven__.Select(x => x).ToList();
foreach (var dbAccount in crmAccounts)
{
CRMDataObjectFour modelObject = new CRMDataObjectFour()
{
ID = dbAccount.ID,
Account_No = dbAccount.Account_No,
Account_Name = dbAccount.Account_Name,
Account_Status = Int32.Parse(dbAccount.Account_Status.ToString()),
Country = dbAccount.Country,
Terms = dbAccount.Terms
};
}
var officialDatabaseList = crmAccounts;
//Here I query CRM to
foreach (var crmAcc in officialDatabaseList)
{
QueryExpression qe = new QueryExpression();
qe.EntityName = "account";
qe.ColumnSet = new ColumnSet("accountnumber", "new_embraceaccountstatus");
qe.Criteria.AddCondition("statecode", ConditionOperator.Equal, 0);
qe.Criteria.AddCondition("accountnumber", ConditionOperator.NotIn, "List of acconts for example");
EntityCollection response = service.RetrieveMultiple(qe);
//Here I update the optionset value
foreach (var acc in response.Entities)
{
if (acc.Attributes["accountnumber"].ToString() == crmAcc.Account_No)
{
if (acc.Contains("new_embraceaccountstatus"))
{
continue;
}
else
{
acc.Attributes["new_embraceaccountstatus"] = new OptionSetValue(Int32.Parse(crmAcc.Account_Status.ToString()));
}
Batch(service, new UpdateRequest { Target = acc });
}
}
}
// Call ExecuteBatch to ensure that any batched requests, get executed.
ExeucteBatch(service)
}
Because it is 2013, and you need to sync records, you'll need to know if some previous records were already in CRM, because depending on that you'll need to send a bunch of Create's or Update's. I would do it in 2 batches of ExecuteMultiple:
1) One batch to execute a query to find which accounts need to be created / updated in CRM, depending on some matching field there.
2) Another batch which will use the previous one to generate all Create / Update operations in one go, depending on the responses you got from 1).
The issue is that they won't run in the same transaction, and that's something which was improved in 2016, as #Daryl said. There is also a new request in 2016 which might improve things even further, because you could merge the 2 batches into one: Upsert, therefore avoiding unnecessary roundtrips to the server.
Maybe this was inspired on Mongo Db's upsert concept which existed long time before? Who knows :)
If you just need to now how to perform an ExecuteMultipleRequest there are samples on the MSDN. Sample: Execute multiple requests.
The old code I've inherited for Twilio retrieves messages using the absolute PageNumber property of the MessageListRequest but according to the documentation this is obsolete and I should be using GetNextPage and GetPrevPage.
The API metadata shows this as obsolete with the message "Use GetNextPage and GetPreviousPage for paging. Page parameter is scheduled for end of life https://www.twilio.com/engineering/2015/04/16/replacing-absolute-paging-with-relative-paging".
Are there any examples of this usage? I couldn't find any in the documentation except in one of the API test methods and I'm not sure how well I can get to processing multiple pages with this example as a guide.
public class Foo : TwilioBase
{
public string Bar { get; set; }
}
public class FooResult : TwilioListBase
{
public List<Foo> Foos { get; set; }
}
[Test]
public void ShouldGetNextPage()
{
IRestRequest savedRequest = null;
FooResult firstPage = new FooResult();
firstPage.NextPageUri = new Uri("/Foos?PageToken=abc123", UriKind.Relative);
mockClient.Setup(trc => trc.Execute<FooResult>(It.IsAny<IRestRequest>()))
.Callback<IRestRequest>((request) => savedRequest = request)
.Returns(new FooResult());
var client = mockClient.Object;
var response = client.GetNextPage<FooResult>(firstPage);
mockClient.Verify(trc => trc.Execute<FooResult>(It.IsAny<IRestRequest>()), Times.Once);
Assert.IsNotNull(savedRequest);
Assert.AreEqual("/Foos?PageToken=abc123", savedRequest.Resource);
Assert.AreEqual(Method.GET, savedRequest.Method);
Assert.IsNotNull(response);
}
The old usage might look something like so:
var twilio = new TwilioRestClient(config.AccountSid, config.AuthToken);
var result = new List<Message>();
MessageResult tempResult;
int page = 0;
do
{
var request = new MessageListRequest();
request = new MessageListRequest { Count = 1000, DateSent = newestDate, DateSentComparison = ComparisonType.GreaterThanOrEqualTo, PageNumber = page++, To = config.FromNumber };
tempResult = twilio.ListMessages(request);
result.AddRange(tempResult.Messages);
} while (tempResult.NextPageUri != null);
Finally, I built the Twilio API 3.4.1.0 from the twilio-csharp GitHub project instead of NuGet since I need to update it to use the MessagingServiceSid which isn't included in the API yet.
Thanks for any pointers. I'll post a solution if I can figure it out on my own.
Actually, I got it to work now!
MessageResult messages = twilio.ListMessages(request);
do
{
if (messages.Messages != null)
{
foreach (var message in messages.Messages)
{
... process results
}
if (messages.NextPageUri != null)
{
messages = twilio.GetNextPage<MessageResult>(messages);
}
}
} while (messages.NextPageUri != null);
Did you try the example from the API Explorer?
https://www.twilio.com/console/dev-tools/api-explorer/sms/sms-mms-list
var twilio = new TwilioRestClient(AccountSid, AuthToken);
// Build the parameters
var options = new MessageListRequest();
var messages = twilio.ListMessages(options);
foreach (var message in messages.Messages)
{
Console.WriteLine(message.Body);
}
The helper library will automatically fetch from the API as you loop over the list until all records matching your criteria are processed.
You can limit the results with MessageListRequest.
Please give that a try and let me know how it goes.