I am running .net application which fetches data from SQL database and displays on the form screen.
When I run the application in UAT, it works fine but in PROD, I am getting below exception
Query run fine on database but I am getting this exception.
PricingClinet.cs -
public async Task<SaveResponse> SaveAsync(Sheet sheet)
{
SaveResponse result = null;
try
{
var response = await _client.PostAsJsonAsync("Pricing/Save", sheet);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var jsonResult = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<SaveResponse>(jsonResult);
}
else
{
var errorMessage = string.Format("StatusCode: {0}\r\n{1}", response.StatusCode.ToString(), response.ReasonPhrase);
Logger.LogError(errorMessage);
result = new SaveResponse()
{
Success = false,
ErrorMessage = errorMessage
};
}
}
catch (Exception error)
{
Logger.LogError(error);
result = new SaveResponse()
{
Success = false,
ErrorMessage = ExceptionManager.RenderErrorMessage(error)
};
}
return result;
}
This error is hapenning in PROD only, not in UAT.
This is a timeout in a await _client.PostAsJsonAsync.
You need to confirm that your PROD configuration is correct e.g. points to the correct server.
If your configuration is correct then you need to either increase the timeout
(e.g. _client.Timeout = ...) or make the remote call faster (if it's in your control obviously).
Related
I’ve used RestSharp 106 in the past but now I’m trying to get a new project up and running with v107. I did a simple test below but I can’t get it to return any data so I must be missing something that I’m not understanding. I’ve put a breakpoint at the top of the method and can follow it all the way down until it makes the async call and then the app just quits. I see the initial logging but again nothing after the async call. I would have thought I would see some logging about the list count or even the “Application END” piece. Anyone have any ideas on what I’m doing wrong? I’ve kept but commented out some of the different things I’ve tried.
Link to the documentation I’m looking at.
https://restsharp.dev/intro.html#introduction
public async void Run()
{
_log.LogInformation("Application START");
try
{
var listPPC = new List<PriorPeriodCorrection>();
listPPC = await CallApi();
}
catch (Exception ex)
{
_log.LogError("Error: {0} | {1} | {2}", ex.Message, ex.StackTrace, ex.InnerException);
}
_log.LogInformation("Application END");
}
public async Task<List<PriorPeriodCorrection>> CallApi()
{
var listPPC = new List<PriorPeriodCorrection>();
var apiURL = "https://example.com";
var apiEndpoint = "api/payroll/getpriorpaycorrectiondata/from/2021-12-01/to/2021-12-07";
var proxyAddress = "http://example.com:9400";
var apiUsername = "someusername";
var apiPassword = "4PsaI69#tuv";
var options = new RestClientOptions(apiURL)
{
ThrowOnAnyError = true,
Timeout = 1000,
Proxy = new WebProxy(proxyAddress)
};
var client = new RestClient(options);
client.Authenticator = new HttpBasicAuthenticator(apiUsername, apiPassword);
var request = new RestRequest(apiEndpoint);
try
{
listPPC = await client.GetAsync<List<PriorPeriodCorrection>>(request);
//var response = await client.GetAsync<PriorPeriodCorrection>(request);
//var response = await client.GetAsync<List<PriorPeriodCorrection>>(request);
//var response = await client.GetAsync(request);
//if (!string.IsNullOrWhiteSpace(response.Content))
//{
// listPPC = JsonConvert.DeserializeObject<List<PriorPeriodCorrection>>(response.Content);
//}
//else
// _log.LogInformation("Response Content is Blank or NULL.");
}
catch (Exception ex)
{
_log.LogError("Error: {0} | {1} | {2}", ex.Message, ex.StackTrace, ex.InnerException);
}
_log.LogInformation("Response count: {0}", listPPC.Count);
return listPPC;
}
public async Task<List<usp_TeamMeetingGetAll_Result>> TeamsMeetingReportGetAll(bool activeOnly)
{
List<usp_TeamMeetingGetAll_Result> teamMeetingGetAllResults = _db
.usp_TeamMeetingGetAll(activeOnly)
.ToList();
IEnumerable<Task<usp_TeamMeetingGetAll_Result>> taskListQuery =
from teamMeetingGetAllResult in teamMeetingGetAllResults
select TeamsMeetingGet(teamMeetingGetAllResult);
List<Task<usp_TeamMeetingGetAll_Result>> taskList = taskListQuery.ToList();
usp_TeamMeetingGetAll_Result[] results = await Task.WhenAll(taskList);
return results.OrderBy(r => r.DisplayStartDate).ToList();
}
I'm trying to figure out why line 3 (the taskList assignment) takes 7-8 seconds to execute. Line 1 calls a stored proc and puts the results (26 rows, about 15 columns) in a list and takes about 1.5 seconds. Line 2 takes less than a millisecond. Line 4 takes about 4 seconds for all async tasks to complete.
Edit: Okay, thanks to the answers below I understand that:
List<Task<usp_TeamMeetingGetAll_Result>> taskList = taskListQuery.ToList();
is causing calls to TeamsMeetingGet. I should have checked that before.
TeamsMeetingGet is making a aync call to a web API, waiting for the results, populating some properties of the usp_TeamMeetingGetAll_Result object with the results, and passing it back.
public async Task<usp_TeamMeetingGetAll_Result> TeamsMeetingGet(usp_TeamMeetingGetAll_Result teamMeetingGetAllResult)
{
//OnlineMeeting onlineMeeting = await TeamsMeetingGet(teamMeetingGetAllResult.JoinWebUrl);
HttpClient client = GraphHelper.GetAuthenticatedHttpClient();
string request =
"users/xxxxxxxxxx/onlineMeetings?$filter=JoinWebUrl%20eq%20'" + HttpUtility.UrlEncode(teamMeetingGetAllResult.JoinWebUrl) + "'";
var response = await client.GetAsync(request);
var result = await response.Content.ReadAsStringAsync();
var jresult = JObject.Parse(result);
var onlineMeetings = jresult["value"].ToObject<OnlineMeeting[]>();
if (onlineMeetings[0].Id != null)
{
teamMeetingGetAllResult.NumAttendees = onlineMeetings[0].Participants.Attendees.Count();
teamMeetingGetAllResult.Subject = onlineMeetings[0].Subject;
//More assignments
}
else
{
teamMeetingGetAllResult.NumAttendees = 0;
teamMeetingGetAllResult.Subject = "";
}
return teamMeetingGetAllResult;
}
If I have 100 rows, I'd like to call TeamsMeetingGet 100 times simultaneously, instead of synchronously. Is this how I do it?
I asked for the GetAuthenticatedHttpClient code and got back:
public class GraphHelper
{
private static string _graphClientSecret = ConfigurationManager.AppSettings["graphClientSecret"];
private static string _graphClientId = ConfigurationManager.AppSettings["graphClientId"];
private static string _graphTenantId = ConfigurationManager.AppSettings["graphTenantId"];
public static HttpClient GetAuthenticatedHttpClient()
{
IConfidentialClientApplication app;
var clientId = _graphClientId;
var tenantID = _graphTenantId;
app = ConfidentialClientApplicationBuilder.Create(clientId)
.WithClientSecret(_graphClientSecret)
.WithAuthority(new Uri("https://login.microsoftonline.com/" + tenantID))
.Build();
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
AuthenticationResult result = null;
try
{
result = app.AcquireTokenForClient(scopes)
.ExecuteAsync().Result;
}
catch (MsalUiRequiredException ex)
{
// The application doesn't have sufficient permissions.
// - Did you declare enough app permissions during app creation?
// - Did the tenant admin grant permissions to the application?
throw ex;
}
catch (MsalServiceException ex) when (ex.Message.Contains("AADSTS70011"))
{
// Invalid scope. The scope has to be in the form "https://resourceurl/.default"
// Mitigation: Change the scope to be as expected.
throw ex;
}
catch (Exception ex)
{
throw ex;
}
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", result.AccessToken);
client.BaseAddress = new Uri("https://graph.microsoft.com/v1.0/");
return client;
}
}
So, I am using postman to test this post method and its working as expected when i am posting/uploading small size file, close to 1MB, but its throwing error when uploading bigger file, 8MB+.
Line where its throwing error:-
await Request.Form.Files[0].CopyToAsync(ms).ConfigureAwait(false);
Error:-
Request.Form.Files = 'Request.Form.Files' threw an exception of type 'System.InvalidOperationException'
Its a Net Core 3.1 Application.
Adding the complete code if anyone want to replicate it.
[HttpPost("File")]
[SAPolicy(SAPolicy.Admin, SAPolicy.ConsumerApp)]
public async Task<IActionResult> PostFile()
{
FileContractRequest fileContract = null;
try
{
if (Request.ContentLength > 0)
{
using (var ms = new MemoryStream())
{
await Request.Form.Files[0].CopyToAsync(ms).ConfigureAwait(false);
var data = ms.ToArray();
var newFileContract = new FileContractRequest()
{
ContentType = Request.Form.Files[0].ContentType,
Name = Path.GetFileName(Request.Form.Files[0].FileName),
Length = data.LongLength.ToString(),
CreationDate = DateTime.UtcNow,
Data = data
};
fileContract = newFileContract;
}
}
else
{
return new StandardResponse<FileContractResponse>(HttpStatusCode.NotAcceptable, null).Result;
}
}
catch (Exception ex)
{
throw ex;
}
var result = await _fileService.PostFile(fileContract).ConfigureAwait(false);
return new StandardResponse<FileContractResponse>(HttpStatusCode.OK, result).Result;
}
I looked in to couple of different blogs and could not find anything that helps me with my problem. Any help to fix this ? what i am missing here ?
Edit 1:-
I'm reading data from remote MongoDB realm which syncs to my local realm, but it seems I can't read from my local realm after sync.
This is the message I get when I try to read from my local realm:
Unable to open a realm at path '/data/user/0/com.companyname.appname/files/default.realm': Incompatible histories. Expected a Realm with no or in-realm history, but found history type 3 Path:Exception backtrace:\n<backtrace not supported on this platform>.
Here is my code:
private async Task<Realm> OpenRealm()
{
try
{
var user = App.realmApp.CurrentUser;
//if user is not logged on yet log on the user and sync
if (user == null)
{
var CurrentUser = await App.realmApp.LogInAsync(Credentials.Anonymous());
var config = new SyncConfiguration("Hirschs", CurrentUser);
_realm = await Realm.GetInstanceAsync(config);
return _realm;
}
else
{
return _realm = Realm.GetInstance();
}
}
catch (Exception ex)
{
await UserDialogs.Instance.AlertAsync(new AlertConfig
{
Title = "An error has occurred",
Message = $"An error occurred while trying to open the Realm: {ex.Message}"
});
// Try again
return await OpenRealm();
}
}
The problem here is that you are trying to create a new local realm in the same path where the synced realm already is.
I suppose that you would like to open the same realm synchronously (that is necessary if the device is offline). In this case you would just need to use the same configuration for both the sync and async calls, as reported in the documentation here.
You could do something like:
private async Task<Realm> OpenRealm()
{
try
{
var currentUser = App.realmApp.CurrentUser;
if (currentUser == null)
{
var currentUser = await App.realmApp.LogInAsync(Credentials.Anonymous());
var config = new SyncConfiguration("Hirschs", currentUser);
_realm = await Realm.GetInstanceAsync(config);
return _realm;
}
else
{
var config = new SyncConfiguration("Hirschs", currentUser);
_realm = Realm.GetInstance(config);
return _realm;
}
}
catch (Exception ex)
{
await UserDialogs.Instance.AlertAsync(new AlertConfig
{
Title = "An error has occurred",
Message = $"An error occurred while trying to open the Realm: {ex.Message}"
});
}
}
I had this piece of code that initially worked fine. However, After adding it to a class where I store my methods that are reused, it keeps failing. The exception that is caught states that the CancellationTokenSource has been Disposed. Can someone point me in the right direction?
I have tried creating a new client and Adding CancellationToken.None to the PutAsync() method from HTTPClient Class but it still fails with the CancellationTokenSource Disposed exception.
public async void AddProduct(Product product)
{
string storeId = "";
try
{
var storeData = JObject.Parse(Connect.Json).SelectToken("store").ToString();
var stores = JsonConvert.DeserializeObject<List<Store>>(storeData);
var store = stores[0];
storeId = store.Id;
store.Products.Add(product);
ProdInfo info = new Info();
foreach(Product p in store.Products)
{
info.AddedProducts = + p.Id;
}
var content = JsonConvert.SerializeObject(info);
using (Connect.Client)
using (var response = await Connect.Client.PutAsync(_url + "/stores/" + storeId, new StringContent(content)))
{
var cont = response.Content;
string result = await cont.ReadAsStringAsync();
if ((int)response.StatusCode == 200)
{
this.JobResult = result;
//this.JobResult = "Store has been successfully updated";
}
else
{
this.JobResult = result;
//this.JobResult = "Store was not updated!";
}
}
}
catch (Exception ex)
{
//this.JobResult = "Store has not been updated due to an error.";
this.JobResult = ex.Message;
}
}
I was able to solve this by simple removing 'using(Connect.Client)' from all of my methods. As #sellotape stated, They were disposing of the HttpClient before I was able to use it again. Thank you all for your contributions.