I've already implemented integration with Selenium -- Testrail. Everything was correct until today when I'm keep receiving:
OneTimeSetUp: System.InvalidCastException : Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'Newtonsoft.Json.Linq.JArray'.
Here is the line of code where it fails:
JArray getListOfAllActiveTestRun = (JArray)client.SendGet($"get_runs/{ProjectId}");
As I'm assuming I need to have a JArray to use it later inside foreach loop (Full code view)
if (RunId == null)
{
JArray getListOfAllActiveTestRun = (JArray)client.SendGet($"get_runs/{ProjectId}");
foreach (JObject testRun in getListOfAllActiveTestRun)
{
bool isCompleted = Convert.ToBoolean(testRun["is_completed"]);
string lastTestRunId = testRun["id"].ToString();
string lastSuiteId = testRun["suite_id"].ToString();
int failedTestCount = testRun["failed_count"].Value<int>();
int untestedTestCount = testRun["untested_count"].Value<int>();
if (!isCompleted && lastSuiteId.Equals(SuitId) && failedTestCount > 0 || !isCompleted && lastSuiteId.Equals(SuitId) && untestedTestCount > 0) // we are checking that there is not finished testRun with suitId equal to this and failed tests and untested tests
{
RunId = lastTestRunId;
break;
}
}
}
Checked the solutions and most of the time I was facing option with JsonConvert.DeserializeObject but I'm not sure if this is correct hint in my case.
Edit (JSON)
"runs":
{
"id":2874,
"suite_id":878,
"name":"[ENV: TEST] [BACKOFFICE] Automation Test Run - [20:02:55 PM]",
"description":null,
"milestone_id":null,
"assignedto_id":null,
"include_all":true,
"is_completed":false,
"completed_on":null,
"config":null,
"config_ids":[
],
"passed_count":171,
"blocked_count":0,
"untested_count":1,
"retest_count":0,
"failed_count":3,
"custom_status1_count":0,
"custom_status2_count":0,
"custom_status3_count":0,
"custom_status4_count":0,
"custom_status5_count":0,
"custom_status6_count":0,
"custom_status7_count":0,
"project_id":19,
"plan_id":null,
"created_on":1631901776,
"updated_on":1631901776,
"refs":null,
"created_by":124,
"url":"ssss"
}
I've been encountering the same problem starting from today as well -- it seems like there's been a change in TestRail's API.
From TestRail's API reference: "...These bulk endpoints will no longer return an array of all entities, but will instead return an object with additional pagination fields and an array of up to 250 entities."
Source: https://www.gurock.com/testrail/docs/api/reference/runs#getruns
Related
I am trying input some validation in C#.
I have a LIST of JSON Object, and I want to add a validation that will check for a value of certain key and make sure they are all same in all the JSON object in the array.
LIST -
subtitles = [{ frameRate : '25', dropFrame: False}, { frameRate : '25', dropFrame: False}, { frameRate : '25', dropFrame: False}, { frameRate : '23', dropFrame: False}]
I want to add validation that will loop through every object and make sure that the value of the key frameRate is same through the array.
This is what i tried to do - I created a aempty list and then tried to push all the frameRates and then looped through it and compared the value with previous one.
List<string> subtitleSegmentsFrameRates = new List<string>();
foreach (var subtitle in segmentSubtitles)
{
subtitleSegmentsFrameRates.Add(subtitle.frameRate);
}
for (int i = 0; i < subtitleSegmentsFrameRates.Count; i++) {
if (i != 0) {
if (subtitleSegmentsFrameRates[i] != subtitleSegmentsFrameRates[i - 1]) {
throw new CustomException("Frame Rates arocss segments do not match.");
}
}
}
Is there a better way to do this ?
You can compare all the items against the first one after parsing input to JArray and linq All method
var jArray = JArray.Parse(subtitles);
bool allSame = jArray.All(j => j["frameRate"].Value<string>() == jArray[0]["frameRate"].Value<string>());
j["frameRate"] is type of JToken that's why to convert to string .Value<string>() is invoked over it.
Another way which is also suggested by #John:
bool same = jArray.Select(j => j["frameRate"].Value<string>()).Distinct().Count() == 1
Check this fiddle - https://dotnetfiddle.net/5xOJB5
First of all convert your json string into JArray and use .All() to check you have same value for frameRate property of all elements.
using System;
using Newtonsoft.Json.Linq;
using System.Linq;
...
var validFrameRate = JArray.Parse(subtitles) //Convert an Sub titles to JArray
.All(x => x.Value<string>("frameRate") == "25"); //Check all frame rates are same or not.
Console.WriteLine(validFrameRate ? "Same frameRate in all elements" : "Different FrameRate in all elements");
.Net Fiddle
JArray is an array of JToken, to get actual value you need to convert JToken to its actual type. Here we used .Value<string>() to get value of frameRate property of JToken
I'm currently working on an ASP.NET Web API .NET Framework 4.7.2. I try to alter some JSON data in my service class. I try to add a new object after every 2nd object in my JArray.
I thought about manipulating the JSON data, rather then concrete objects because the received data will most likely be dynamic data. I'm using the library JObject, but I'm getting some error without any real exception messages.
My received JSON structure looks like that:
{ "data" : [
{"IsPlaceholder": 0, "Name" : "Test1", "Size" : 2 },
{"IsPlaceholder": 0, "Name" : "Test2", "Size" : 3 },
{"IsPlaceholder": 0, "Name" : "Test3", "Size" : 1 }
]}
My service class looks like that:
public class MyService : IMyService
{
public async Task<JObject> UpdateInformationAsync(JObject coolData)
{
// Random placeholder, new placeholder object after 2nd
var placeholder = JObject.FromObject(new PlaceholderVm());
var cnt = 0;
foreach (JObject c in coolData["data"] as JArray)
{
if (cnt % 2 == 0)
{
coolData["data"][cnt].AddAfterSelf(placeholder);
}
cnt++;
}
return coolData;
}
}
My placeholder view model looks like that:
public class PlaceholderVm
{
public int IsPlaceholder => 1;
public string Name => "Placeholder";
public float Size { get; set; } = 0;
}
When I try to add a placeholderVm to my JArray, it works fine the first time, but on the 2nd iteration it throws an error without exception message.
Do you know how I can add a new JObject on nth position to my JArray?
This is because you are mutating the underlying collection while looping through it in the foreach. This is the reason you'll often times see folks initialize a new List<T> when doing operations like this, to avoid this error.
It actually yields this exception :
Run-time exception (line 21): Collection was modified; enumeration operation may not execute.
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
The easiest way around it is to simply create a new collection and place things where you want them to go. In your case, this may look like :
var jObject = new JObject();
JArray jArray = new JArray();
foreach (JObject c in coolData["data"] as JArray)
{
jArray.Add(c);
if (cnt % 2 == 0)
{
jArray[jArray.Count - 1].AddAfterSelf(placeholder);
}
cnt++;
}
jObject.Add("data", jArray);
Here's a .NET Fiddle
I am trying to decipher the correct syntax for using JObject Parse when I need to have one of the values set by a variable. This is for using Algolia to push a new object to my search index.
songIndexHelper.PartialUpdateObject(JObject.Parse(#"{""ApprovalFL"":"true",
""objectID"":"'+Accepted.Value+'"}"));
I receive Accepted.Value from my function argument. For example, Accepted.Value could equal something like 98. Also, true should be formatted as boolean instead of a string. The above is my attempt. How should I fix my syntax?
I'm following this documentation from Algolia: https://www.algolia.com/doc/api-reference/api-methods/partial-update-objects/
For more context, here is the above line in the function:
public ActionResult Index(int? Accepted, int? Denied)
{
var accountInfo = EntityDataAccess.GetAccountInfoByUserID(User.Identity.GetUserId());
if(accountInfo == null || accountInfo.AdminFL == false || accountInfo.LabelFL == true)
{
return RedirectToAction("Index", "Home");
}
else
{
if(Accepted != null)
{
EntityDataAccess.AcceptSong(Accepted.Value);
var songIndexHelper = HttpContext.Application.Get("SongIndexHelper") as IndexHelper<SongAlgoliaModel>;
songIndexHelper.PartialUpdateObject(JObject.Parse(#"{""ApprovalFL"":""true"",
""objectID"":""Accepted.Value""}"));
}
This should produce what you are looking for:
String json = "{\"ApprovalFL\":true,\"objectID\":" + Accepted.Value.ToString() + "}";
which is:
{"ApprovalFL":true,"objectID":98}
songIndexHelper.PartialUpdateObject(JObject.Parse(#"{""ApprovalFL"":""true"",
""objectID"":""Accepted.Value""}"));
should be:
songIndexHelper.PartialUpdateObject(JObject.Parse(#"{""ApprovalFL"":true,
""objectID"":" +Accepted.Value+ "}"));
The key is to use + to concatenate in the value of Accepted, and not wrap true in quotes.
Another approach I would suggest is not using strings at all. Consider an approach like:
var bob = new { ApprovalFL = true, objectID = Accepted.Value};
var obj = JObject.FromObject(bob);
songIndexHelper.PartialUpdateObject(obj);
I got a simple IEnumerable with some data in my debugging session for StockSearchList. How do I convert to a List but ToList is not accespted.
public IEnumerable<StockSearchItemViewModel> StockSearchList
{
get
{
if (string.IsNullOrEmpty(_stockSearchFilter))
return _stockSearchList;
var filterLower = _stockSearchFilter.ToLower();
return _stockSearchList.Where(x => { var symbolLower = x.Symbol.ToLower(); return (symbolLower.StartsWith(filterLower) || symbolLower.StartsWith(filterLower)); });
}
}
In another method i got:
List<StockTickerData> ssl = new List<StockTickerData>();
ssl = StockSearchList<StockTickerData>.ToList();
But I get build error of:
Error 4 The property 'xxxx.StockViewModel.StockSearchList' cannot be used with type arguments .... stockviewmodel.cs 838 19
How do I convert ssl to a be list from the values in StockTickerData
Thanks
It is just a simple syntax error, the right code:
List<StockTickerData> ssl = StockSearchList.ToList();
i new to MVC and LINQ and i am learning how to use AngularJs and MVC for a new project that i have been assigned. So i am learning these technologies through an online video.The tutor uses code first approach, so Visual Studio Creates all the necessary files and a database that matches the tutors models, i on the other hand already have a database and i created the Api's to perform REST operations against the DB. So when i run this code below
public IEnumerable<Todo> GetTodos()
{
return Models.DbStoredProcModel.GetAllTodos.GetAllTodoEntryStoredProcedure();
}
it return a Json output like this
So up to this point, my json output matches with the video tutorial even though our code approach is different. So the tutor, using this piece of code he wrote
Tutors Code:
public IEnumerable<Todo> GetTodos(string q= null,string sort = null, bool desc = false, int ? limit = null, int offset =0)
{
var result = ((IObjectContextAdapter)db).ObjectContext.CreateObjectSet<Todo>();
IQueryable<Todo> items = string.IsNullOrEmpty(sort)
? result.OrderBy(o => o.Priority)
: result.OrderBy(String.Format("it. {0} {1}", sort, desc ? "DESC" : "ASC"));
if (!string.IsNullOrEmpty(q) && q != "undefined")
items = items.Where(t => t.Text.Contains(q));
if (offset > 0) items = items.Skip(offset);
if (limit.HasValue) items = items.Take(limit.Value);
return items;
}
it will allow him to perform Search and Sort operations on the data returned.
now here is my own code trying to code trying to do the same.
public IEnumerable<Todo> GetTodos(string q= null,string sort = null, bool desc = false, int ? limit = null, int offset =0)
{
var result = Models.DbStoredProcModel.GetAllTodos.GetAllTodoEntryStoredProcedure( );
IQueryable<Todo> items = string.IsNullOrEmpty(sort)
? result.OrderBy(o => o.Priority)
// i get the error on the line below
: result.OrderBy(String.Format("it. {0} {1}", sort, desc ? "DESC" : "ASC"));
if (!string.IsNullOrEmpty(q) && q != "undefined")
items = items.Where(t => t.Text.Contains(q));
if (offset > 0) items = items.Skip(offset);
if (limit.HasValue) items = items.Take(limit.Value);
return items;
}
however, i get an error saying that
Error:The type arguments for method 'System.Linq.Enumerable.OrderBy<TSource,TKey>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,TKey>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
How do i fix this?
Change
result.OrderBy(String.Format("it. {0} {1}", sort, desc ? "DESC" : "ASC"))
to
result.OrderBy<Todo,string>(String.Format("it. {0} {1}", sort, desc ? "DESC" : "ASC"))
for a more clear error message.
The underlying issue is perhaps that
result.OrderBy(String.Format("it. {0} {1}", sort, desc ? "DESC" : "ASC"))
doesn't have a meaningful interpretation in the context of your application. It looks like dynamic linq to me, requiring references that pull in alternative OrderBy definitions than the ones you will have referenced.
My suggestion would be to check the namespaces referenced by the tutorial (in the project references and at the top of this file), in case you have missed any.