DeserializeObject for {
"15 Days": "675",
"180 Days": "8100",
"30 Days": "1350",
"60 Days": "2700",
"90 Days": "4050"
}
We can convert this json to dictionary. and this way around to handle this case. As we can directly deserialize to class object.
var test = "{ \"15 Days\": \"675\", \"180 Days\": \"8100\",
\"30 Days\": \"1350\", \"60 Days\": \"2700\", \"90 Days\":
\"4050\" }";
string [] json = test.Replace("{",
string.Empty).Replace("}", string.Empty).Split(',');
Dictionary<string, string> jsonDic = new Dictionary<string, string>();
for (int i = 0; i < json.Length; i++)
{
string[] jsonItem = json[i].Split(':');
jsonDic.Add(jsonItem[1], jsonItem[0]);
}
this dictionary jsonDic will look like below.
Hope this is helpful for you.
Related
I am working with Contacts via REST API and I am trying to add an input field in my application for specifying the Source of the Contact. The problem is that the Source field is a combo box, which means that its values can be modified by Automation Steps (SM205000). For example, below is the list of the default values for the Source:
which corresponds to the CRMSourcesAttribute of that field
// Token: 0x020003D3 RID: 979
public class CRMSourcesAttribute : PXStringListAttribute
{
// Token: 0x06004052 RID: 16466 RVA: 0x000FD4A4 File Offset: 0x000FB6A4
public CRMSourcesAttribute() : base(new string[]
{
"W",
"H",
"R",
"L",
"O"
}, new string[]
{
"Web",
"Phone Inquiry",
"Referral",
"Purchased List",
"Other"
})
{
}
// Token: 0x04002158 RID: 8536
public const string _WEB = "W";
// Token: 0x04002159 RID: 8537
public const string _PHONE_INQ = "H";
// Token: 0x0400215A RID: 8538
public const string _REFERRAL = "R";
// Token: 0x0400215B RID: 8539
public const string _PURCHASED_LIST = "L";
// Token: 0x0400215C RID: 8540
public const string _OTHER = "O";
}
Should I go through the Automation Steps tables to get the final values of the combo-box or there is a way to get it by REST API specifying, for example, the DAC.FIELD?
For tasks like these, I'd suggest to use reflection. Below goes example of reading Attributes with sample of usage:
protected IEnumerable records()
{
//var row = new ClassFilter { ClassName = "PX.Objects.CR.CRMSourcesAttribute" };
var row = Filter.Current;
if (row != null && !string.IsNullOrWhiteSpace(row.ClassName))
{
var type = Type.GetType(row.ClassName) ??
Type.GetType(row.ClassName + ", PX.Objects");
if (type != null)
switch (type.BaseType.Name)
{
case "PXIntListAttribute":
{
int[] values;
string[] labels;
GetRecords(type, out values, out labels);
for (int i = 0; i < values.Length; i++)
yield return new KeyValueRecord { Key = values[i].ToString(), UiValue = labels[i] };
break;
}
case "PXStringListAttribute":
{
string[] values, labels;
GetRecords(type, out values, out labels);
for (int i = 0; i < values.Length; i++)
yield return new KeyValueRecord { Key = values[i], UiValue = labels[i] };
break;
}
}
}
}
private void GetRecords<T>(Type type, out T[] values, out string[] labels)
{
var obj = Activator.CreateInstance(type);
var flags = BindingFlags.NonPublic | BindingFlags.Instance;
values = type.GetField("_AllowedValues", flags).GetValue(obj) as T[];
labels = type.GetField("_AllowedLabels", flags).GetValue(obj) as string[];
}
and picture:
After that you can just add graph and DAC to endpoint and expose it.
Full source code with comments is available here.
I am new to Revit API and am working in C#. I want to get the schedule element parameters value using C#. I used the below code to get the view schedule.
var viewSchedule = new FilteredElementCollector(document)
.OfClass(typeof(ViewSchedule))
.FirstOrDefault(e => e.Name == "MyScheduleName") as ViewSchedule;
Schedule Element Data
From the above schedule, I used the below code to get the element data (please refer the above screenshot link) but it taking long time to reflect the output (10 to 15 seconds).
var rowCount = viewSchedule.GetTableData().GetSectionData(SectionType.Body).NumberOfRows;
var colCount = viewSchedule.GetTableData().GetSectionData(SectionType.Body).NumberOfColumns;
for (int i = 0; i < rowCount; i++)
{
for (int j = 0; j < colCount; j++)
{
data += viewSchedule.GetCellText(SectionType.Body, i, j);
}
}
Please let me know is there any alternate approach to get the schedule data using C#.
Thanks in advance.
Maybe you can also use ViewSchedule.Export as demonstrated by The Building Coder discussing The Schedule API and Access to Schedule Data.
Yes, you can easily access Schedule data without exporting.
Firstly, get all the schedules and read the data cell by cell. Secondly, create dictionary and store data in form of key, value pairs. Now you can use the schedule data as you want. I have tried this in Revit 2019.
Here is the implementation.
public void getScheduleData(Document doc)
{
FilteredElementCollector collector = new FilteredElementCollector(doc);
IList<Element> collection = collector.OfClass(typeof(ViewSchedule)).ToElements();
String prompt = "ScheduleData :";
prompt += Environment.NewLine;
foreach (Element e in collection)
{
ViewSchedule viewSchedule = e as ViewSchedule;
TableData table = viewSchedule.GetTableData();
TableSectionData section = table.GetSectionData(SectionType.Body);
int nRows = section.NumberOfRows;
int nColumns = section.NumberOfColumns;
if (nRows > 1)
{
//valueData.Add(viewSchedule.Name);
List<List<string>> scheduleData = new List<List<string>>();
for (int i = 0; i < nRows; i++)
{
List<string> rowData = new List<string>();
for (int j = 0; j < nColumns; j++)
{
rowData.Add(viewSchedule.GetCellText(SectionType.Body, i, j));
}
scheduleData.Add(rowData);
}
List<string> columnData = scheduleData[0];
scheduleData.RemoveAt(0);
DataMapping(columnData, scheduleData);
}
}
}
public static void DataMapping(List<string> keyData, List<List<string>>valueData)
{
List<Dictionary<string, string>> items= new List<Dictionary<string, string>>();
string prompt = "Key/Value";
prompt += Environment.NewLine;
foreach (List<string> list in valueData)
{
for (int key=0, value =0 ; key< keyData.Count && value< list.Count; key++,value++)
{
Dictionary<string, string> newItem = new Dictionary<string, string>();
string k = keyData[key];
string v = list[value];
newItem.Add(k, v);
items.Add(newItem);
}
}
foreach (Dictionary<string, string> item in items)
{
foreach (KeyValuePair<string, string> kvp in item)
{
prompt += "Key: " + kvp.Key + ",Value: " + kvp.Value;
prompt += Environment.NewLine;
}
}
Autodesk.Revit.UI.TaskDialog.Show("Revit", prompt);
}
I new with Xamarin , I am trying to convert my list of generic type to single string. I can comfortably performs this task in Android using below code.
Gson gson = new Gson();
Type collectionType = new TypeToken<ArrayList<Response_bean>>() {}.getType();
JsonElement element = gson.toJsonTree(response_data, collectionType);
JsonArray jsonArray = element.getAsJsonArray();
String strjsonarray = jsonArray.toString();
But I cant found its replacement in Xamarin.
Please help Thanks in advance.
I think you can use json.net
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Sizes = new string[] { "Small" };
string json = JsonConvert.SerializeObject(product);
// {
// "Name": "Apple",
// "Expiry": "2008-12-28T00:00:00",
// "Sizes": [
// "Small"
// ]
// }
As Alessandro Caliaro said, json.net can help you.
List<Product> list = new List<Product>();
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Sizes = new string[] { "Small" };
Product product2 = new Product();
product2.Name = "Banana";
product2.Expiry = new DateTime(2010, 12, 28);
product2.Sizes = new string[] { "Big" };
Product product3 = new Product();
product3.Name = "Pear";
product3.Expiry = new DateTime(2012, 12, 28);
product3.Sizes = new string[] { "Huge" };
list.Add(product);
list.Add(product2);
list.Add(product3);
string json = JsonConvert.SerializeObject(list);
Output
[
{"Name":"Apple","Expiry":"2008-12-28T00:00:00","Sizes":["Small"]},
{"Name":"Banana","Expiry":"2010-12-28T00:00:00","Sizes":["Big"]},
{"Name":"Pear","Expiry":"2012-12-28T00:00:00","Sizes":["Huge"]}
]
Please find the below code for for filtering bills, which returns only 10 sorted records even I passed the resultperpage>10.
public IEnumerable<Intuit.Ipp.Data.Qbo.Bill> FilterBills(DataServices dataServices, int startPage, int resultsPerPage, DateTime After, DateTime Before)
{
Intuit.Ipp.Security.OAuthRequestValidator oAuthRequestValidator = ((Intuit.Ipp.Security.OAuthRequestValidator)dataServices.ServiceContext.RequestValidator);
OAuthConsumerContext consumerContext = new OAuthConsumerContext
{
ConsumerKey = oAuthRequestValidator.ConsumerKey,
SignatureMethod = SignatureMethod.HmacSha1,
ConsumerSecret = oAuthRequestValidator.ConsumerSecret
};
OAuthSession oSession = new OAuthSession(consumerContext, "https://oauth.intuit.com/oauth/v1/get_request_token",
"https://workplace.intuit.com/Connect/Begin",
"https://oauth.intuit.com/oauth/v1/get_access_token");
oSession.AccessToken = new TokenBase
{
Token = oAuthRequestValidator.AccessToken,
ConsumerKey = oAuthRequestValidator.ConsumerKey,
TokenSecret = oAuthRequestValidator.AccessTokenSecret
};
var body = "PageNum={0}&ResultsPerPage={1}&Filter=LastUpdatedTime :AFTER: {2} :AND: LastUpdatedTime :BEFORE: {3} & Sort=LastUpdatedTime HighToLow";
body = String.Format(body, startPage, resultsPerPage, After.ToString("yyyy-mm-ddTHH:MM:ssz"), Before.ToString("yyyy-mm-ddTHH:MM:ssz"));
IConsumerRequest conReq = oSession.Request();
conReq = conReq.Post().WithRawContentType("application/x-www-form-urlencoded").WithRawContent(System.Text.Encoding.ASCII.GetBytes(body)); ;
conReq = conReq.ForUrl(dataServices.ServiceContext.BaseUrl + "bills/v2/" + dataServices.ServiceContext.RealmId);
conReq = conReq.SignWithToken();
Intuit.Ipp.Data.Qbo.SearchResults searchResults = (Intuit.Ipp.Data.Qbo.SearchResults)dataServices.ServiceContext.Serializer.Deserialize<Intuit.Ipp.Data.Qbo.SearchResults>(conReq.ReadBody());
IEnumerable<Intuit.Ipp.Data.Qbo.Bill> SearchResult = ((Intuit.Ipp.Data.Qbo.Bills)(searchResults.CdmCollections)).Bill;
return SearchResult;
}
After sending the request i m getting the respose as 10 sorted bill record without getting any error. I am using IPPDotNetDevKit 2.1.12.0 version.
Please Look into this filtering problem.
The OAuth parameters are being passed in the body of the request in your example above and overwriting your request body, so it is defaulting to PageNum=1&ResultsPerPage=20. Also, the date is formatted incorrectly. Here is a code sample that will work.
public IEnumerable<Intuit.Ipp.Data.Qbo.Bill> FilterBills(DataServices dataServices, int startPage, int resultsPerPage, DateTime After, DateTime Before)
{
StringBuilder requestXML = new StringBuilder();
StringBuilder responseXML = new StringBuilder();
var requestBody =
"PageNum={0}&ResultsPerPage={1}&Filter=LastUpdatedTime :AFTER: {2} :AND: LastUpdatedTime :BEFORE: {3}&Sort=LastUpdatedTime HighToLow";
requestBody = String.Format(requestBody, startPage, resultsPerPage, After.ToString("yyyy-MM-ddThh:mm:sszzz"),
Before.ToString("yyyy-MM-ddThh:mm:sszzz"));
HttpWebRequest httpWebRequest =
WebRequest.Create(dataServices.ServiceContext.BaseUrl + "bills/v2/" +
dataServices.ServiceContext.RealmId) as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Headers.Add("Authorization", GetDevDefinedOAuthHeader(httpWebRequest, requestBody));
requestXML.Append(requestBody);
UTF8Encoding encoding = new UTF8Encoding();
byte[] content = encoding.GetBytes(requestXML.ToString());
using (var stream = httpWebRequest.GetRequestStream())
{
stream.Write(content, 0, content.Length);
}
HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
using (Stream data = httpWebResponse.GetResponseStream())
{
Intuit.Ipp.Data.Qbo.SearchResults searchResults =
(Intuit.Ipp.Data.Qbo.SearchResults)
dataServices.ServiceContext.Serializer.Deserialize<Intuit.Ipp.Data.Qbo.SearchResults>(
new StreamReader(data).ReadToEnd());
return ((Intuit.Ipp.Data.Qbo.Bills) searchResults.CdmCollections).Bill.ToList();
}
}
private string GetDevDefinedOAuthHeader(HttpWebRequest webRequest, string requestBody)
{
OAuthConsumerContext consumerContext = new OAuthConsumerContext
{
ConsumerKey = consumerKey,
ConsumerSecret = consumerSecret,
SignatureMethod = SignatureMethod.HmacSha1,
UseHeaderForOAuthParameters = true
};
consumerContext.UseHeaderForOAuthParameters = true;
OAuthSession oSession = new OAuthSession(consumerContext, "https://www.example.com",
"https://www.example.com",
"https://www.example.com");
oSession.AccessToken = new TokenBase
{
Token = accessToken,
ConsumerKey = consumerKey,
TokenSecret = accessTokenSecret
};
IConsumerRequest consumerRequest = oSession.Request();
consumerRequest = ConsumerRequestExtensions.ForMethod(consumerRequest, webRequest.Method);
consumerRequest = ConsumerRequestExtensions.ForUri(consumerRequest, webRequest.RequestUri);
if (webRequest.Headers.Count > 0)
{
ConsumerRequestExtensions.AlterContext(consumerRequest, context => context.Headers = webRequest.Headers);
if (webRequest.Headers[HttpRequestHeader.ContentType] == "application/x-www-form-urlencoded")
{
Dictionary<string, string> formParameters = new Dictionary<string, string>();
foreach (string formParameter in requestBody.Split('&'))
{
formParameters.Add(formParameter.Split('=')[0], formParameter.Split('=')[1]);
}
consumerRequest = consumerRequest.WithFormParameters(formParameters);
}
}
consumerRequest = consumerRequest.SignWithToken();
return consumerRequest.Context.GenerateOAuthParametersForHeader();
}
I have a dictionary object as under
Dictionary<string, List<string>> dictStr = new Dictionary<string, List<string>>();
dictStr.Add("Culture", new List<string>() { "en-US", "fr-FR" });
dictStr.Add("Affiliate", new List<string>() { "0", "1" });
dictStr.Add("EmailAddress", new List<string>() { "sreetest#test.com", "somemail#test.com" });
And I have an entity as under
public class NewContextElements
{
public string Value { get; set; }
}
What I need to do is that for every value in a particular index of the dictionary value collection, I have to make a comma separated string and place it into List collection.
e.g. the NewContextElements collection will have (obviously at run time)
var res = new List<NewContextElements>();
res.Add(new NewContextElements { Value = "en-US" + "," + "0" + "," + "sreetest#test.com" });
res.Add(new NewContextElements { Value = "fr-FR" + "," + "1" + "," + "somemail#test.com" });
I was trying as
var len = dictStr.Values.Count;
for (int i = 0; i < len; i++)
{
var x =dictStr.Values[i];
}
no it is of-course not correct.
Help needed
Try this:
Enumerable.Range(0, len).Select( i =>
new NewContextElements {
Value = string.Join(",", dictStr.Values.Select(list => list[i]))
}
);
len is the number of items inside the individual lists (in your example, it's two).
This isn't a slick as #dasblinkenlight's solution, but it should work:
Dictionary<string, List<string>> dictStr = new Dictionary<string, List<string>>( );
dictStr.Add( "Culture", new List<string>( ) {"en-US", "fr-FR"} );
dictStr.Add( "Affiliate", new List<string>( ) {"0", "1"} );
dictStr.Add( "EmailAddress", new List<string>( ) {"sreetest#test.com", "somemail#test.com"} );
int maxValues = dictStr.Values.Select(l => l.Count).Max();
List<NewContextElements> resultValues = new List<NewContextElements>(dictStr.Keys.Count);
for (int i = 0; i < maxValues; i++) {
StringBuilder sb = new StringBuilder();
string spacer = string.Empty;
dictStr.Keys.ForEach( k => {
sb.AppendFormat( "{0}{1}", spacer, dictStr[k][i] );
spacer = ", ";
} );
resultValues.Add( new NewContextElements( ){ Value = sb.ToString() });
}
do you mean transform your data like
1 2
3 4
5 6
to
1 3 5
2 4 6
try this block of code? it can be optimized in a few ways.
var res = new List<NewContextElements>();
int i = dictStr.values.count()
for (int i=0; i < len; i++) {
NewContextElements newContextElements = new NewContextElements();
foreach (List<string> list in dictStr) {
if (newContextElements.value() == null ) {
newContextElements.value = list[i];
} else {
newContextElements.value += ", " + list[i] );
}
}
res.add(newContextElements);
}
let me know if there are problems in the code, most like there is when you write it without a real ide.