Deserialize JSON using Newtonsoft in C# - serialization

I am having a heck of a time converting JSON. Tried a dozen stackoverflow solutions, but still stuck. I am connecting to an API and getting JSON data in the format below. The goal is to get a list of Firstname, Lastname and street addresses of the homeowners parsed from the JSON collection. I built a simple utility to try and sort this out. I paste JSON in the top textbox and results appear in the bottom textbox.
JSON data:
[
{
"HomeOwnerFirstName": "Elizabeth",
"HomeOwnerLastName": "Jones",
"PropertyAddress": "123 AnyStreet",
},
{
"HomeOwnerFirstName": "Bob",
"HomeOwnerLastName": "Smith",
"PropertyAddress": "345 AnyStreet",
}
]
public class Homeowners
{
public string HomeOwnerFirstName { get; set; }
public string HomeOwnerLastName { get; set; }
public string PropertyAddress { get; set; }
}
private void cmdDeserial_Click(object sender, EventArgs e) //deserialize by using JSON in Top textbox
{
desiraliseJSON(txtInput.Text);
}
private void desiraliseJSON(string strJSON)
{
try
{
var jsondata = JsonConvert.DeserializeObject<List<Homeowners>>(strJSON);
txtBox2.Text = jsondata.ToString(); //Show the deserialized text in the bottom textbox.
}
catch (Exception ex)
{
txtBox2.Text = ("Error: " + ex.Message.ToString());
}
}

Ok, I finally found the problem and fixed it. I was trying to deserialize based on internal JSON values instead of a class (group) of them
So changing the try/catch to:
try
{
var homeowner = JsonConvert.DeserializeObject<Homeowners[]>(strJSON);
foreach var (account in homeowner)
{
txtBox2.Text = (account.HomeOwnerLastName + ", " + account.PropertyAddress + " Balance: " + account.Balance);
}
}
allowed it to iterate through the lines and produce the right results.

Related

The repeated fields in a protobuf message is empty in a POST api in ASP.NET Core

As the title said, when I try to post a message (which is generated by protobuf message) from a react application to ASP.NET Core, the backend cannot receive the repeated fields (empty).
The following is the payload of a post action from the browser:
{ "strs": [ "test1", "test2" ] }
enter image description here
But in the POST API of ASP.NET Core, the body is just empty:
enter image description here
The protobuf message is very simple:
message TestArray {
repeated string strs = 1;
}
Any advice will be appreciated. Thank you in advance.
Part of the generated TestArray class in C#:
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
// ...
public sealed partial class TestArray : pb::IMessage<TestArray>
// ...
private readonly pbc::RepeatedField<string> strs_ = new pbc::RepeatedField<string>();
// ...
public pbc::RepeatedField<string> Strs {
get { return strs_; }
}
I followed this document and created the model as below:
public class TestArray
{
public RepeatedField<string> Strs { get; set; }
}
Tested with postman:
It seems binded successfully,so I asked you for the details of TestArray class to check what's wrong
I think you could create a DTO and add the necessary data to the instance of TestArray class
public sealed partial class TestArray
{
private readonly RepeatedField<string> strs_ = new RepeatedField<string>();
public RepeatedField<string> Strs
{
get { return strs_; }
}
}
public class SomeDto
{
public string[] Strs { get; set; }
}
In controller:
[HttpPost]
public IActionResult Post(SomeDto dto)
{
var testarr = new TestArray();
testarr.Strs.Add(dto.Strs);
return Ok();
}
Result:

How to find from mongo collection using comma separated string in C#

I want to fetch data from mongo using comma separated string in C#. Below is my code.
string numbers = "32,12,56,78";
List<CustomerNumbers> calling_number= new List<CDRs>();
IMongoCollection<CustomerNumbers> Collec;
calling_number= Collec.Find(x => x.customer == ID && x.numbers.Contains(numbers)).ToList();
I am new to mongo and and did't know the exact approach. while using above code I am getting records for single number. Please guide me to fix this.
TIA
Class structure
public class CustomerNumbers
{
public string numbers { get; set; }
public int customer { get; set; }
}
Ideally, you'd have modeled your numbers field in mongo as an array rather than a delimited string, this would allow you to add indexes and performance tune your queries.
However, we can make use of the aggregation pipeline for this. We'll need an extra class like the following that we'll use:
public class CustomerNumbersSplit
{
public string[] numbers { get; set; }
public int customer { get; set; }
}
We'll also need to do is split your comma-delimited string.
var numbers = "32,12,56,78";
var numbersSplit = numbers.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToArray();
Once we've done that we can then write a query as the following:
var result = await collection.Aggregate()
.Match(x => x.customer == ID)
.AppendStage<CustomerNumbersSplit>(#"{ $addFields: { numbers: { $split: [""$numbers"", "","" ] } } }")
.Match(x => x.numbers.Any(y => numbersSplit.Contains(y)))
.ToListAsync();
This makes use of a $split and $addFields, this is so we can use the database engine to split the number and query them in the database engine.
If you're interested in the query that it generated:
[
{ "$match" : { "customer" : 12324 } },
{ "$addFields" : { "numbers" : { "$split" : ["$numbers", ","] } } },
{ "$match" : { "numbers" : { "$elemMatch" : { "$in" : ["32", "12", "56", "78"] } } } }
]

add unique id property to Episerver Composer block

Need to add a unique ID property in a composer tab, what's the best way of doing this and here's my attempt:
[PageTypeProperty(
EditCaption = "UniqueID",
HelpText = "UniqueID",
Type = typeof(PropertyString),
//DisplayInEditMode=false,
Tab = typeof(ComposerTab))]
public virtual Guid UniqueID
{
get { return UniqueID; }
set { UniqueID = System.Guid.NewGuid(); }
}
Intended behaviour: each time a new textbox is added on the page, it should be assigned a unique ID.
Problem with this piece of code is I don't see a unique ID entered in the text box when in Composer - Edit Mode (when I check the properties of this content block)
Please comment on correct way to set this GUID property and where. Thanks!
Later edit:
http://tedgustaf.com/blog/2011/9/create-episerver-composer-function-with-page-type-builder/
This example describes my approach
Block.cs
namespace MyProject.ComposerFunctions
{
[PageType("70421202Efdghajkfgkjd43535",
Name = "Block",
Description = "Block",
Filename = "Block.ascx")]
public class Block : BaseComposerFunctionData
{
[PageTypeProperty(
EditCaption = "UniqueID",
HelpText = "UniqueID",
Type = typeof(PropertyString),
//DisplayInEditMode=false,
Tab = typeof(ComposerTab))]
public virtual Guid UniqueID
{
get { return UniqueID; }
set { UniqueID = System.Guid.NewGuid(); }
}
}
}
Block.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="Block.ascx.cs" Inherits="MyProject.ComposerControls.Block" %>
Block.ascx.cs
namespace MyProject.ComposerControls
{
public partial class Block : Dropit.Extension.Core.BaseContentFunction
{
protected override void OnLoad(EventArgs e)
{
if (!IsPostBack)
{
this.DataBind();
}
}
}
}
BaseContentFunction is derived from UserControl, IPageSource, IFunctionSource
BaseComposerFunctionData is derived from TypedPageData
I'm not quit sure if this will work, but could you try the following in your Block.cs?
[PageTypeProperty(
EditCaption = "UniqueID",
HelpText = "UniqueID",
Type = typeof(PropertyString),
//DisplayInEditMode=false,
Tab = typeof(ComposerTab))]
public virtual Guid UniqueID { get; set; }
public override void SetDefaultValues(ContentType contentType)
{
UniqueID = System.Guid.NewGuid();
}

Returning sub-properties from document in RavenDb via Index using Lucene

I'm using RavenDB 2.5 and what I want to do is query a Group (see below) providing a valid Lucene search term and get back a collection of Member instances (or even just Ids) that match. So, class definition:
public class Group {
public string Id { get; set; }
public IList<Member> Members { get; set; }
}
public class Member {
public string Name { get; set; }
public string Bio { get; set; }
}
And they are stored in the database as session.Store(groupInstance); as you'd expect. What I'd like to do is query and return the Member instances which match a given search term.
So, something like:
public class GroupMembers_BySearchTerm : AbstractIndexCreationTask {
public override IndexDefinition CreateIndexDefinition(){
return new IndexDefinition {
Map = "from g in docs.Groups select new { Content = new [] { g.Members.Select(m => m.Name), g.Members.Select(m => m.Bio) }, Id = g.Id }",
Indexes = { { "Id", FieldIndexing.Default }, { "Content", FieldIndexing.Analyzed } }
}
}
}
If I call this using something like:
session.Advanced.LuceneQuery<Group, GroupMembers_BySearchTerm>().Where("Id: myId AND Content: search terms").ToList();
I obviously get back a Group instance, but how can I get back the Members instead?
What about an index like this:
public class Members_BySearchTermAndGroup : AbstractIndexCreationTask {
public override IndexDefinition CreateIndexDefinition(){
return new IndexDefinition {
Map = "from g in docs.Groups
from member in g.Members
select new {
GroupdId = g.Id,
Name = member.Name,
Bio = member.Bio,
Content = new [] {member.Name, member.Bio },
}",
Indexes = {
{ "GroupId", FieldIndexing.Default },
{ "Content", FieldIndexing.Analyzed }
},
Stores = {
{ "Name", FieldStorage.Yes },
{ "Bio", FieldStorage.Yes }
}
}
}
}
If you take a closer look you'll see that we are creating a new lucene entry for each member inside of a group. Consequently, you'll be able to query on those elements and retrieve them.
Finally you can query your store like this (more info about searching):
session.Query<Member, Members_BySearchTermAndGroup>()
.Search(x => x.Content, "search terms")
.ProjectFromIndexFieldsInto<Member>()
.ToList();
I cannot check this right now but I guess that you need to project your results using the ProjectFromIndexFieldsInto(). Some more information about projections in this link.
or, following your example:
session.Advanced
.LuceneQuery<Member, Members_BySearchTermAndGroup>()
.Where("GroupId: myId AND Content: search terms")
.SelectFields<Member>()
.ToList();

NHibernate: HqlGenerator: Create calculated property by concatenating other properties

I am trying to add an HqlGenerator to allow NHibernate to query a calculated property on the following domain entity:
public class User
{
public string FirstName { get; set; }
public string LastName {get; set; }
public string FullName
{
get { return FirstName + " " + LastName; }
}
}
I have created an HQL generator like so:
public class UserFullName : BaseHqlGeneratorForProperty
{
public UserFullName()
{
var properties = new List<MemberInfo> { typeof(User).GetProperty("FullName") };
SupportedProperties = properties;
}
public override HqlTreeNode BuildHql(MemberInfo member, Expression expression, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
var user = visitor.Visit(expression).AsExpression();
return treeBuilder.Concat(
treeBuilder.Dot(user, treeBuilder.Ident("FirstName")),
treeBuilder.Constant(" "),
treeBuilder.Dot(user, treeBuilder.Ident("LastName"))
);
}
}
The generator is wired up correctly into the configuration as the debugger will break within the BuildHql method when I run the query:
session.Query<User>().FirstOrDefault(x => x.FullName == "Aaron Janes");
however, later on in the NHibernate internals an exception is thrown:
NHibernate.Hql.Ast.ANTLR.QuerySyntaxException : Exception of type 'Antlr.Runtime.NoViableAltException' was thrown. [.FirstOrDefault[User](NHibernate.Linq.NhQueryable`1[User], Quote((x, ) => (String.op_Equality(x.FullName, Aaron Janes))), )]
Can anyone spot what I am doing wrong?
In your BuildHQL() you include the subexpression 'user' multiple times. This is not possible. You need to use
var user1 = visitor.Visit(expression).AsExpression();
var user2 = visitor.Visit(expression).AsExpression();
and use each of those once in the Concat expression.