I am trying to refresh my listview when an item is removed from it, but every time it gives me this error:
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: index.
Before updating the ObservableCollection, I do this:
Groups = new ObservableCollection<RequestGroups>();
And then I fill it with this:
var temp = (JArray)resultJson["data"];
JArray jarr = temp;
foreach (JObject contents in jarr.Children<JObject>())
{
Requests obj = new Requests();
obj.Id = (int)contents["id"];
Client c = new Client();
c.address = contents["address"].ToString();
c.phone = contents["phone"].ToString();
c.name = contents["user"].ToString();
obj.Client = c;
obj.Date = contents["date"].ToString();
obj.Duration = contents["duration"].ToString();
obj.DurationText = "Duración: "+contents["duration"].ToString()+"h";
obj.Price = "$" + contents["price"].ToString();
String[] cDate = obj.Date.Split(' ');
String cHour = cDate[1]+" "+cDate[2];
obj.Hour = cHour;
String[] date = cDate[0].Split('-');
String title = months[date[1]] + " " + date[0];
obj.Title = title;
bool flag = false;
foreach(RequestGroups rqG in Groups){
if(rqG.Title.Equals(title)){
rqG.Add(obj);
flag = true;
}
}
if(!flag){
RequestGroups rq = new RequestGroups(title, date[1] + "-" + date[0]);
rq.Add(obj);
Device.BeginInvokeOnMainThread(() =>
{
Groups.Add(rq);
});
}
}
This is where I remove the items:
private async Task UpdateRequest(int status,int idEvent)
{
HttpClient hTTPClient = new HttpClient();
var client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(60);
client.BaseAddress = new Uri(Utils.baseUrl);
Dictionary<string, string> dataToSend = new Dictionary<string, string>();
dataToSend.Add("session", Utils.loginKey);
dataToSend.Add("eventId", idEvent+"");
dataToSend.Add("status", status.ToString());
string jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(dataToSend, new KeyValuePairConverter());
var contentVar = new StringContent(jsonData, Encoding.UTF8, "application/json");
try
{
HttpResponseMessage response = await client.PostAsync("/UpdateEvent", contentVar);
var result = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
string contents = await response.Content.ReadAsStringAsync();
var resultJson = JObject.Parse(result);
if ((int)resultJson["status"] == 0)
{
await base.DisplayAlert((string)resultJson["msg"], "", "OK");
return;
}
else if ((int)resultJson["status"] == 1)
{
//I'm currently trying to reload the whole view, before this was calling the method above.
await this.mainPage.Navigation.PushAsync(new NavigationPage(new MasterMenu.MainPage()));
await getRequests();
}
else
{
await base.DisplayAlert("Error procesando la solicitud, intente más tarde", "", "Ok");
return;
}
}
}
catch (Exception ex)
{
Debug.WriteLine("Error update request: {0}", ex);
}
await Task.Delay(1);
}
If I leave it like that, UI will not update. Please help me, as I've been struggling with this issue for 2 days now. It happens exclusively on iOS.
The issue was fixed after updating iOS. The problem was caused because of a buggy iOS version that had problems indexing objects. After updating, everything ran as smoothly as usual. If anyone runs into this issue (exclusively on iOS), try updating both iOS and Xamarin Forms.
Related
Im trying to get the Messages from a Youtube Livestream, works, but i dont get new Messages. The NextPageToken is included.
Sometimes i get new messages, but it takes arround 5-10min.
Youtube Chat Sending works also fine.
Any Idea?
This is from the Docs: https://developers.google.com/youtube/v3/live/docs/liveChatMessages/list
private async Task GetMessagesAsync(string liveChatId, string nextPageToken, long? pollingIntervalMillis)
{
liveChatId = "EiEKGFVDVUQ3WGNXTk92SlpvaHFMM3dZTi1uZxIFL2xpdmU";
if (!updatingChat)
{
if (!string.IsNullOrEmpty(liveChatId))
{
newMessages = true;
var chatMessages = youTubeService.LiveChatMessages.List(liveChatId, "id,snippet,authorDetails");
var chatResponse = await chatMessages.ExecuteAsync();
PageInfo pageInfo = chatResponse.PageInfo;
newMessages = false;
if (pageInfo.TotalResults.HasValue)
{
if (!prevCount.Equals(pageInfo.TotalResults.Value))
{
prevCount = pageInfo.TotalResults.Value;
newMessages = true;
}
}
if (newMessages)
{
Messages = new List<YouTubeMessage>();
foreach (var chatMessage in chatResponse.Items)
{
string messageId = chatMessage.Id;
string displayName = chatMessage.AuthorDetails.DisplayName;
string displayMessage = chatMessage.Snippet.DisplayMessage;
string NextPagetoken = chatResponse.NextPageToken;
YouTubeMessage message = new YouTubeMessage(messageId, displayName, displayMessage);
if (!Messages.Contains(message))
{
Messages.Add(message);
string output = "[" + displayName + "]: " + displayMessage;
Console.WriteLine(time + output);
}
}
}
await GetMessagesAsync(liveChatId, chatResponse.NextPageToken, chatResponse.PollingIntervalMillis);
}
}
updatingChat = false;
await Task.Delay(100);
}
public async Task YouTubeChatSend(string message)
{
try
{
LiveChatMessage liveMessage = new LiveChatMessage();
liveMessage.Snippet = new LiveChatMessageSnippet()
{
LiveChatId = "EiEKGFVDVUQ3WGNXTk92SlpvaHFMM3dZTi1uZxIFL2xpdmU",
Type = "textMessageEvent",
TextMessageDetails = new LiveChatTextMessageDetails() { MessageText = message }
};
var insert = this.youTubeService.LiveChatMessages.Insert(liveMessage, "snippet");
var response = await insert.ExecuteAsync();
if (response != null)
{
}
}
catch
{
Console.WriteLine("Failed to chat send");
}
}
Here is my code. It's been over a month I'm trying to add calendars in Outlook but nothing is working :( please help. The function AcquireTokenByAuthorizationCodeAsync never completes. And the token.Result is always null
string authority = ConfigurationManager.AppSettings["authority"];
string clientID = ConfigurationManager.AppSettings["clientID"];
Uri clientAppUri = new Uri(ConfigurationManager.AppSettings["clientAppUri"]);
string serverName = ConfigurationManager.AppSettings["serverName"];
var code = Request.Params["code"];
AuthenticationContext ac = new AuthenticationContext(authority, true);
ClientCredential clcred = new ClientCredential(clientid, secretkey);
//ac = ac.AcquireToken(serverName, clientID, clientAppUri, PromptBehavior.Auto);
//string to = ac.AcquireToken(serverName, clientID, clientAppUri, PromptBehavior.Auto).AccessToken;
var token = ac.AcquireTokenByAuthorizationCodeAsync(code, new Uri("http://localhost:2694/GetAuthCode/Index/"), clcred, resource: "https://graph.microsoft.com/");
string newtoken = token.Result.AccessToken;
ExchangeService exchangeService = new ExchangeService(ExchangeVersion.Exchange2013);
exchangeService.Url = new Uri("https://outlook.office365.com/" + "ews/exchange.asmx");
exchangeService.TraceEnabled = true;
exchangeService.TraceFlags = TraceFlags.All;
exchangeService.Credentials = new OAuthCredentials(token.Result.AccessToken);
exchangeService.FindFolders(WellKnownFolderName.Root, new FolderView(10));
Appointment app = new Appointment(exchangeService);
app.Subject = "";
app.Body = "";
app.Location = "";
app.Start = DateTime.Now;
app.End = DateTime.Now.AddDays(1);
app.Save(SendInvitationsMode.SendToAllAndSaveCopy);
I have experienced this issue when I call the AcquireTokenByAuthorizationCodeAsync using result instead of using await key words and all these code was in a asynchronously controller in the MVC.
If you are in the same scenario, you can fix this issue by two ways:
1.Always using the async, await like code below:
public async System.Threading.Tasks.Task<ActionResult> About()
{
...
var result =await ac.AcquireTokenByAuthorizationCodeAsync(code, new Uri("http://localhost:2694/GetAuthCode/Index/"), clcred, resource: "https://graph.microsoft.com/");
var accessToken = result.AccessToken;
...
}
2.Use the synchronization controller:
public void About()
{
...
var result =ac.AcquireTokenByAuthorizationCodeAsync(code, new Uri("http://localhost:2694/GetAuthCode/Index/"), clcred, resource: "https://graph.microsoft.com/").Result;
var accessToken = result.AccessToken;
...
}
I am trying to get response from an API on few GET and POST calls, whenever i try to get Response from a web API POST it gives an System.NullReferenceException: Object reference not set to an instance of an object.. I am using PostAsync to get response. It works absolutely fine on my local machine but is returning NULL response on deployment machine.
#region API_CALL
System.Net.Http.HttpClient Client = new System.Net.Http.HttpClient();
string CompleteURL = URL.Trim() + URL_FromJSON.Trim();
#region URL Construct For GET Requests
CompleteURL = GetURL(ParameterValue, CallType_FromJSON, CompleteURL);
#endregion URL Construct For GET Requests
string URLContent = string.Empty;
Client.BaseAddress = new System.Uri(CompleteURL);
byte[] cred = UTF8Encoding.UTF8.GetBytes(ClientID.Trim() + Constants.APIConstants.ColonConnector + ClientPass.Trim());
string Encoded = Convert.ToBase64String(cred);
Client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(Constants.APIConstants.AuthTypeBearer, accessToken);
Client.DefaultRequestHeaders.Host = IPAddress.Trim();
CacheControlHeaderValue val = new CacheControlHeaderValue();
val.NoCache = true;
Client.DefaultRequestHeaders.CacheControl = val;
Client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(Constants.APIConstants.ContentType));
Client.DefaultRequestHeaders.Add(Constants.APIConstants.LicenseKey, LiscenseKEY);
Client.DefaultRequestHeaders.Add(Constants.APIConstants.PostmanToken, PostmanToken);
//client.DefaultRequestHeaders.Add(Constants.APIConstants.AccessToken, accessToken);
System.Net.Http.HttpContent Content = new StringContent(JSONData, UTF8Encoding.UTF8, Constants.APIConstants.ContentType);
// Only for debug purpos:
LogManager.Logger.Invoke(LogLevels.TraceDetail, Source, "Request to API: " + JSONData, Request.ActorID);
HttpResponseMessage Message = new HttpResponseMessage();
if (CallType_FromJSON == Constants.HttpMethod.Post)
{ Message = Client.PostAsync(CompleteURL, Content).Result; }
else if (CallType_FromJSON == Constants.HttpMethod.Get)
{ Message = Client.GetAsync(CompleteURL, HttpCompletionOption.ResponseContentRead).Result; }
string Description = string.Empty;
#region Response Logging
try
{
LogManager.Logger.Invoke(LogLevels.TraceDetail, Source, "Response from API: " + Message.Content.ReadAsStringAsync().Result, Request.ActorID);
}
catch(Exception EX)
{
LogManager.Logger.Invoke(LogLevels.TraceError, Source, "Exception while logging response from API" + EX.ToString()+"Stack: "+EX.StackTrace, Request.ActorID);
}
#endregion Response Logging
if (Message.IsSuccessStatusCode)
{
string Result = Message.Content.ReadAsStringAsync().Result;
ResponseJson = Result;
Description = Result;
}
else
{
try
{
string Result1 = Message.Content.ReadAsStringAsync().Result;
LogManager.Logger.Invoke(LogLevels.TraceInfo, Source, "Failed: ... Recieved JSON: " + Result1, Request.ActorID);
}
catch { }
return new TransactionResponse() { Response = Constants.ResponseCodes.Error };
}
#endregion API_CALL
break;
}
TransactionResponse Response = new TransactionResponse();
Response.Response = ResponseJson;
return Response;
}
catch (Exception Ex)
{
LogManager.ExpLogger.Invoke(Source, Ex, Request.ActorID);
return new TransactionResponse() { Response = Constants.ResponseCodes.Error };
}
the object : Message is null after execution of Message = Client.PostAsync(CompleteURL, Content).Result
Try reading as string asynch with the in the reach of postasynch, use it with the same block of code it works,
if (CallType_FromJSON == Constants.HttpMethod.Post)
{ Message = Client.PostAsync(CompleteURL, Content).Result; }
else if (CallType_FromJSON == Constants.HttpMethod.Get)
{ Message = Client.GetAsync(CompleteURL, HttpCompletionOption.ResponseContentRead).Result; }
string Description = string.Empty;
example:
var = httpresult.content.readasstringasyhnc();
You can also typecast to any model you want her.
I'm trying to do a POST from one controller to another controller. Both controller's are from different projects. One project is serving to simulate the presentation layer (which I will call the test project here).
From the test project I'm trying to pass 2 simple string parameters to the other controller which I will call the process.
var values = new List<KeyValuePair<string, string>>();
values.Add(new KeyValuePair<string, string>("id", param.Id.Value));
values.Add(new KeyValuePair<string, string>("type", param.Type.Value));
var content = new FormUrlEncodedContent(values);
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("nl-NL"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string token = param.token.Value;
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = client.PostAsync("/api/Process/Product", content).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
return Request.CreateResponse(HttpStatusCode.OK, result);
}
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "fail");
}
And in the process controller, I'm trying to receive it like this:
[HttpPost]
public HttpResponseMessage Product(string id, string type)
{
return null;
}
But it never reaches this controller. I always get a "not found status code".
So how can I pass 2 simple parameters with HttpClient()?
Use Get instead of Post for simple type parameters.
using (var client = new HttpClient())
{
BaseAddress = new Uri(url);
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("nl-NL"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string token = param.token.Value;
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
// New code:
var response = await client.GetAsync( string.format("api/products/id={0}&type={1}",param.Id.Value,param.Id.Type) ).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
return Request.CreateResponse(HttpStatusCode.OK, result);
}
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "fail");
}
In the API side you can do like this.
[HttpGet]
public HttpResponseMessage Product(string id, string type)
{
return null;
}
When receiving a post you must specify [FromBody] in the parameters for the method to be called
[HttpPost]
public HttpResponseMessage Product([FromBody]string id, [FromBody]string type)
{
return null;
}
I'm not sure I am totally in love with it, but I used anonymous types and dynamics to handle this in the past... (Note the config differences for using PostAsJsonAsync(). I forgot these initially.)
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.PostAsJsonAsync("api/User/UpdateLastLogin", new { UserId = userId, ApplicationId = applicationId });
Receiving controller:
[HttpPost]
public void UpdateLastLogin([FromBody]dynamic model)
{
_userRepository.UpdateLastLogin((int)model.UserId, (int)model.ApplicationId);
}
In WebApiConfig.Register():
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
The other approach, which I passed on, is to create a completely new set of strongly types models for every one of these calls. I didn't want to, as I had a ton of them to make to a WebAPI.
Here is another example you can use for WinForms, WPF or Console apps
Client code
async Task<CalendarView> GetData(int month, int year, int deviceTypeID)
{
var result = new MSOCommon.CalendarView();
try
{
HttpClient client = new HttpClient();
var calendarRequest = new CalendarRequest()
{
Month = month,
Year = year,
DeviceTypeID = deviceTypeID,
UserInfo = Program.UserInfo
};
var url = Properties.Settings.Default.ServerBaseUrl + string.Format("/api/calendar/Calendar");
HttpResponseMessage response = await client.PostAsync(url, calendarRequest.AsJson());
if (response.IsSuccessStatusCode) // Check the response StatusCode
{
var serSettings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All
};
string responseBody = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<MSOCommon.CalendarView>(responseBody, serSettings);
}
else
{
logger.Error(Properties.Resources.DATACannotGetCalendar);
}
}
catch (Exception ex)
{
logger.Error(Properties.Resources.DATACannotGetCalendar + " " + ex.Message);
logger.Error(ex);
}
return result;
}
Controller server-side code
[HttpPost()]
public CalendarView Calendar(CalendarRequest calendarRequest)
{
logger.Info(string.Format("Get calendar for month {0} and year {1} ", calendarRequest.Month, calendarRequest.Year));
// TODO Check username
var result = new CalendarView();
using (var db = new MSOnlineEntities())
{
result = db.Calendars.Include("CalendarDetails")
.Where(x => x.CMonth == calendarRequest.Month && x.CYear == calendarRequest.Year && x.CDeviceTypeID == calendarRequest.DeviceTypeID).ToList()
.ConvertAll(x => new CalendarView
{
ID = x.ID,
CMonth = x.CMonth,
CYear = x.CYear,
CDays = x.CDays,
CDeviceTypeID = x.CDeviceTypeID,
ClosedAtTime = x.ClosedAtTime,
ClosedByUser = x.ClosedByUser,
IsClosed = x.IsClosed,
CalendarDetails = x.CalendarDetails.ToList().ConvertAll(d => new CalendarDetailView
{
ID = d.ID,
CalendarID = d.CalendarID,
MachineID = d.MachineID,
MachineName = d.DATA_MACHINE.Name,
D1 = d.D1 ?? -1,
D2 = d.D2 ?? -1,
D3 = d.D3 ?? -1,
D4 = d.D4 ?? -1,
D5 = d.D5 ?? -1,
D6 = d.D6 ?? -1,
D7 = d.D7 ?? -1,
D8 = d.D8 ?? -1,
D9 = d.D9 ?? -1,
D10 = d.D10 ?? -1,
D11 = d.D11 ?? -1,
D12 = d.D12 ?? -1,
D13 = d.D13 ?? -1,
D14 = d.D14 ?? -1,
D15 = d.D15 ?? -1,
D16 = d.D16 ?? -1,
D17 = d.D17 ?? -1,
D18 = d.D18 ?? -1,
D19 = d.D19 ?? -1,
D20 = d.D20 ?? -1,
D21 = d.D21 ?? -1,
D22 = d.D22 ?? -1,
D23 = d.D23 ?? -1,
D24 = d.D24 ?? -1,
D25 = d.D25 ?? -1,
D26 = d.D26 ?? -1,
D27 = d.D27 ?? -1,
D28 = d.D28 ?? -1,
D29 = d.D29 ?? -1,
D30 = d.D30 ?? -1,
D31 = d.D31 ?? -1
})
}).FirstOrDefault();
return result;
}
}
Use [HttpGet] instead of [HttpPost] on the server
HttpResponseMessage response =
await client.GetAsync(string.format("api/product?id={0}&type={1}",param.Id.Value,param.Id.Type);
The difference between my answer and the NMK's accepted answer is the ? instead of the /
This is what worked for me
How to ensure UploadStringCompletedEventHandler event has been executed successfully ? in following code you can see i am calling function UploadMyPOST with my lastreads parameter having some data. Now you can see i am saving a variable named response into the MyClassXYZ varialbe. in the extreme last you can see there is a event which invoked by the method UploadMyPost() is filling the server response into the response variable. Now here issue is UploadMyPost(lastreads) executes successfully but its invoked event does not executes. Even cursor do not go on that event by which i am not able to fill server response into the response variable. So Anyone know any approach by which i can wait until that event successfully execute and i could able to save server response ?
private async void MyMethod(MyClassXYZ lastreads)
{
await UploadMyPOST(lastreads);
MyClassXYZ serverResponse = response;
if (serverResponse.Book == null)
{
//Do Something.
}
}
private void UploadMyPOST(MyClassXYZ lastreads)
{
apiData = new MyClassXYZApi()
{
AccessToken = thisApp.currentUser.AccessToken,
Book = lastreads.Book,
Page = lastreads.Page,
Device = lastreads.Device
};
//jsondata is my global variable of MyClassXYZ class.
jsondata = Newtonsoft.Json.JsonConvert.SerializeObject(apiData);
MyClassXYZ responsedData = new MyClassXYZ();
Uri lastread_url = new Uri(string.Format("{0}lastread", url_rootPath));
WebClient wc = new WebClient();
wc.Headers["Content-Type"] = "application/json;charset=utf-8";
wc.UploadStringCompleted += new UploadStringCompletedEventHandler(MyUploadStringCompleted);
wc.UploadStringAsync(lastread_url, "POST", jsondata);
}
private void MyUploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
try
{
if (e.Error == null)
{
string resutls = e.Result;
DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(MyClassXYZ));
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(resutls));
response = (MyClassXYZ)json.ReadObject(ms);
}
else
{
string sx = e.Error.ToString();
}
}
catch(Exception exe)
{
}
}
//After Stephen suggession i used the HttpClient so i have written new code with the help of HttpClient. Code is building successfully but at run time cursor goes out from this method to the parent method where from its calling.
private async Task<string> UploadMyPOST(MyClassXYZ lastreads)
{
string value = "";
try
{
apiData = new LastReadAPI()
{
AccessToken = thisApp.currentUser.AccessToken,
Book = lastreads.Book,
Page = lastreads.Page,
Device = lastreads.Device
};
jsondata = Newtonsoft.Json.JsonConvert.SerializeObject(apiData);
LastRead responsedData = new LastRead();
Uri lastread_url = new Uri(string.Format("{0}lastread", url_rootPath));
HttpClient hc = new HttpClient();
//After following line cursor go back to main Method.
var res = await hc.PostAsync(lastread_url, new StringContent(jsondata));
res.EnsureSuccessStatusCode();
Stream content = await res.Content.ReadAsStreamAsync();
return await Task.Run(() => Newtonsoft.Json.JsonConvert.SerializeObject(content));
value = "kd";
}
catch
{ }
return value;
}
I recommend that you use HttpClient or wrap the UploadStringAsync/UploadStringCompleted pair into a Task-based method. Then you can use await like you want to in MyMethod.
Thank you Stephen Clear you leaded me in a right direction and i did POST my request successfully using HttpClient.
HttpClient hc = new HttpClient();
hc.BaseAddress = new Uri(annotation_url.ToString());
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, myUrl);
HttpContent myContent = req.Content = new StringContent(myJsonData, Encoding.UTF8, "application/json");
var response = await hc.PostAsync(myUrl, myContent);
//Following line for pull out the value of content key value which has the actual resposne.
string resutlContetnt = response.Content.ReadAsStringAsync().Result;
DataContractJsonSerializer deserializer_Json = new DataContractJsonSerializer(typeof(MyWrapperClass));
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(resutlContetnt.ToString()));
AnnotateResponse = deserializer_Json.ReadObject(ms) as Annotation;