JsonConvert.SerializeObject failes when having a single quote - c#

I have an object say:
public class Comment {
public string Id { get; set; }
public string Author { get; set; }
public string Body { get; set; }
}
And whenever I have a single quote in the body (the others vars will never have them)
the following line crashes:
return JObject.Parse("{ 'Result' : 'Sucessfull!', 'Comment' : '" + JsonConvert.SerializeObject(comment) + "' }");
And I'm sure it's on the body, because this only happens when I do something like this:
comment.Body = "testing th's ";
and the other values, are dynamicly set, and work for bodies without the single quotes.
any clue why this is happening?
Note: I need to upgrade the comment.Body to support new lines later on if that is relevant

Why do you add the comment object to your JSON as plain text? What you try to parse is this string:
{ 'Result' : 'Sucessfull!', 'Comment' : '{"Id":null,"Author":null,"Body":"testin
g th's"}' }
Obviously, it is not a valid JSON string. All you have to do is to rewrite your code a little bit:
return JObject.Parse("{ 'Result' : 'Sucessfull!', 'Comment' : " + JsonConvert.SerializeObject(comment) + " }");

Try this
Comment comment = new Comment()
{
Body = "testing th's ",
Author = "Author",
Id = "007"
};
var result = new
{
Result = "Sucessfull!",
Comment = comment
};
return JsonConvert.SerializeObject(result);

Related

ElasticSearch NEST searchresponse.hits data not populated

I have an index in ElasticSearch. I have setup an ASP.NET core lambda serverless app. I inject IElasticClient into my controller.
I want my controller to be signed as public IEnumerable<StreamSummary> Get() and the ElasticSearch query I would have thought to be as as simple as return searchResponse.Hits.Select(h => h.Source).ToList(); but this is not the case as can be seen below.
I query my Index with something basic like this
var searchResponse = elasticClient.Search<StreamSummary>(s => s
.Index("myindex")
.Query(q => q.MatchAll()
)
);
When I log how many "hits" I get, it is the correct amount (searchResponse.Hits.Count).
When I set my controller return IEnumerable<StreamSummary> and use searchResponse.Hits.Select(h => h.Source).ToList() the list is the correct number but every entry has no values. DateTime fields are all Datetime.Min strings are empty, nullables are null. It's basically an empty/freshly instantiated class and not populated/serialised as I would have expected it to be.
When I iterate the hits and display/log Index,Type and Id, this all works and displays exactly as I expect. The Issue I am having is with _source (Source Property NEST).
foreach (var searchResponseHit in searchResponse.Hits)
{
hits.Add(searchResponseHit.Index);
hits.Add(searchResponseHit.Type);
hits.Add(searchResponseHit.Id); searchResponseHit.Source
searchResponseHit.Source // here is the problem, no populated StreamSummary data}
Where hits is List<string> hits = new List<string>();
So I dig a bit further and in my Startup.cs I DisableDirectStreaming() on ConnectionSettings() so I can get at the request/response buffered byte streams.
I then do the following:
var requestJson = System.Text.Encoding.UTF8.GetString(searchResponse.ApiCall.RequestBodyInBytes);
var responseJson = System.Text.Encoding.UTF8.GetString(searchResponse.ApiCall.ResponseBodyInBytes);
return searchResponse.ApiCall.HttpMethod.ToString() + searchResponse.ApiCall.Uri + "\n" + requestJson + "\r\n" + responseJson;
This is an inccomplete/part response but as you can see it contains a lot of escape characters etc. (Could this be part of the problem, a serialisation issue??)
\"hits\" : {\n \"total\" : {\n \"value\" : 9,\n \"relation\" : \"eq\"\n },\n \"max_score\" : 1.0,\n \"hits\" : [\n {\n \"_index\" : \"accounts\",\n \"_type\" : \"_doc\",\n \"_id\" : \"U3P 1 8fb4b770-4e29-4f0d-aec8-1bcd4199005f\",\n \"_score\" : 1.0,\n \"_source\" : {\n \"ProcessingResponse\" : \"Success\",\n \"ProviderId\" : 6,\n
Connection/Client:
var uri = new Uri(Configuration["ElasticSearch:Url"]);
var httpConnection = new AwsHttpConnection(new BasicAWSCredentials(Configuration["AWS:AwsAccessKeyId"], Configuration["AWS:AwsSecretAccessKey"]),
RegionEndpoint.GetBySystemName(Configuration["ElasticSearch:Region"]));
var pool = new SingleNodeConnectionPool(uri);
var config = new ConnectionSettings(pool, httpConnection).DefaultIndex(Startup.ElasticSearchIndex)
.DisableDirectStreaming().PrettyJson();
var elasticClient = new ElasticClient(config);
services.AddSingleton<IElasticClient>(elasticClient);
POCO is:
public class StreamSummary : ResponseSummary
{
public string Type { get; set; }
public int? ProviderId { get; set; }
public string ProviderAccount { get; set; }
public int? ProcessingTime { get; set; }
public DateTime ProcessedTimeUtc { get; set; }
}
where Response Summary Contains a couple of nullable decimals(but also has an IList<AnotherClass>)
Help Appreciated.
If I'm not mistaken, this is what you're after:
searchResponse.Documents

Return Multiple Values C# [duplicate]

This question already has answers here:
Return multiple values to a method caller
(28 answers)
Closed 7 years ago.
I have written a separate class that holds the permissions of my website. I make calls to this class in every class I have. I am having trouble bringing back the values from my permissions class. I will show you what I have below:
Permissions Class
public class Permissions
{
public static string selectedNumber = "";
public static string selectedName= "";
public static string selectedLocation= "";
public Info SetInfo(string selectedValue)
{
string selectInfo = "SELECT [Num] AS 'Number', [Name] AS 'Name', CONVERT(nvarchar(50),RTRIM(b.Num])) + ' - ' + CONVERT(nvarchar(50),b.Name) AS 'Location' "
+ "FROM [TBL_Info] a "
+ "left join [TBL_Where] b on (a.[ID] = b.[ID]) "
+ "WHERE a.ID = #ID";
sqlCmd = new SqlCommand(selectInfo, sqlConn);
sqlConn.Open();
sqlCmd.Parameters.AddWithValue("#ID", selectedValue);
SqlDataReader rdrInfo = sqlCmd.ExecuteReader();
if (rdrInfo.HasRows)
{
rdrInfo.Read();
selectedNumber = rdrInfo .GetSqlString(rdrInfo .GetOrdinal("Number")).ToString();
selectedName= rdrInfo .GetSqlString(rdrInfo .GetOrdinal("Name")).ToString();
selectedLocation = rdrInfo .GetSqlString(rdrInfo .GetOrdinal("Location")).ToString();
}
sqlCmd.Connection.Close();
return new Info()
{
number= selectedNumber,
name= selectedName,
location= selectedLocation
};
}
public class Info
{
public String number{ get; set; }
public String name{ get; set; }
public String location{ get; set; }
}
}
And I am currently trying to call it in another class like this:
Classes.Permissions permission = new Classes.Permissions();
permission.SetInfo(selectedUserValue);
The end product is that I set textboxes in the class I am trying to make the call from with the 3 return values from permission.SetInfo()
Currently I am not able to get anything returned.... I know I am doing something wrong, clearly. So can someone please give me some advice on how to achieve this?
Other than some stylistic things I have issue with, your code looks like it should work (as long as you have data in your database). To return multiple values from a method, create a new object (ie Info) that defines the things to be returned.
So, you should be able to write something like:
Textbox txtBox;
var info = new Classes.Permissions().SetInfo(SelectedUserValue);
txtBox.Text =
info.number ?? "<null>" + " " +
info.name ?? "<null> + " " +
info.location ?? "<null>'
Note that I used the null coalescing operator (??) as SetInfo could return an instance of Info, where all members are null if no rows are returned from your database query.
By the way, the other way to return multiple values from a method is to use out parameters:
Textbox txtBox;
string number;
string name;
string location;
new Classes.Permissions().SetInfo(SelectedUserValue, out number, out name, out location);
And then your SetInfo would look like:
public void SetInfo(string SeelctedUserValue,
out string number, out string name, out string location)
{
//assign values to number,name and location
}
To return multiple instances of the same object, than your method should return
an IEnumerable (ie a List or Array),
a Tuple<>,
a container object.
For example, if you know you are going to return exactly three, you might want to have your method return Tuple<Info,Info,Info>:
public Tuple<Info, Info, Info> SetInfo(string SeelctedUserValue)
{
//query db
return new Tuple<Info, Info, Info>(
new Info{ number = "number", name = "name", location="location},
new Info{ number = "number", name = "name", location="location},
new Info{ number = "number", name = "name", location="location});
}

RestSharp (C#) - Deserialize JSON Objects to NULL

I'm trying to understand REST by utilizing RestSharp in my application.
Here is a bit of JSON that my client is returning:
{
"result" : {
"object_type" : "session",
"user_id" : "FEE3CBD4-5D35-11E3-A42A-606A40E381E5",
"object_name" : "Session",
"id" : "2F2968B6-5D37-11E3-89F4-5D6A40E381E5"
}
}
Here is my class object:
public class TGCResult : IDeserializer
{
public string object_type {get; set;}
public string user_id { get; set; }
public string object_name { get; set; }
public string id { get; set; }
public TGCResult()
{
}
public override string ToString()
{
return "object_type = " + object_type + "\nuser_id = " + user_id + "\nobject_name = " + object_name + "\nid = " + id;
}
}
And here is the code in which I am retrieving the JSON and attempting to deserialize:
var client = new RestClient("https://www.xxxxxxxxx.com");
var request = new RestRequest("/api/session", Method.POST);
request.AddParameter("username", "JSventoraGD");
request.AddParameter("password", "xxxxxxxxxxxxxxxx");
request.AddParameter("api_key_id", "xxxxxxxxxxxxxxxxxxx");
request.RequestFormat = DataFormat.Json;
var asyncHandle = client.ExecuteAsync<TGCResult>(request, response =>
{
TxtTest.Text = response.Data.ToString();
});
asyncHandle.Abort();
When doing this, I can see the data is returned to my application correctly, but the Data in my response always has NULL values. Any ideas on why this might be happening? Am I supposed to manually deserialize the JSON given the content? The samples I've seen online have a very similar setup to mine, I'm lost... any help is greatly appreciated!
var asyncHandle=client.ExecuteAsync(request,response=>{
String res=response.Content;
T obj = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(res);
});
Try adding
request.RootElement = "result";
I have just spent a couple of hours trying to get a simple GET request to parse anything but null, setting RootElement helped me. Bit surprised i needed it since you set your type class several other places in the code.
Try using it like this
var asyncHandle = client.ExecuteAsync(request, response =>
{
var json = response.Content;
// deserialize to TGCResult
});
This works fine for me
It seems you need to have another class as your Data type.
public class TGCResultContainer
{
public TGCResult result { get; set; }
}
Also, your TGCResult class does not need to implement IDeserializer.

Reading POST Request XML - Boolean value always read as false

I'm working on a WCF RESTful web service hosted in IIS. I'm currently working on a fairly simple post request, sending the following XML to the endpoint:
<StockListRequestData xmlns="http://myWebService.com/endpoint">
<UserID>2750</UserID>
<StockDatabase>stockLeekRoadVenue</StockDatabase>
<InStockOnly>true</InStockOnly>
</StockListRequestData>
This XML matches a DataContract on my web service:
[DataContract(Namespace = "http://myWebService.com/endpoint")]
public class StockListRequestData
{
[DataMember]
public string UserID { get; set; }
[DataMember]
public string StockDatabase { get; set; }
[DataMember]
public bool InStockOnly { get; set; }
}
The problem is the <InStockOnly>true</InStockOnly> element, when I set this to true or false it will always be interpreted as false...
Here is the code that handles the request:
public StockListResponseData GetListOfProducts(StockListRequestData requestData)
{
var stockList = new StockList(requestData.InStockOnly, requestData.StockDatabase);
StockListResponseData response;
if (stockList.Any())
{
var stockArray = new Stock[stockList.Count];
var i = 0;
foreach (var s in stockList)
{
stockArray[i] = s;
i++;
}
response = new StockListResponseData
{
StockList = stockArray,
WasSuccessful = true,
};
return response;
}
response = new StockListResponseData
{
WasSuccessful = false
};
return response;
}
The StockList class:
[DataContract]
public class StockList : List<Stock>
{
public StockList(bool inStockOnly, string stockDb)
{
if (inStockOnly)
{
// Get only products that are in stock
var conn = AndyServerDatabase.ConnectToStockMovementByDb(stockDb);
conn.Open();
// Compile SQL query
var q = new SqlCommand(null, conn) { CommandText = "SELECT StockID, Name, PerBox FROM Stock WHERE InStock = 1;" };
// Execute query
var rdr = q.ExecuteReader();
// Check that the output isn't null
if (rdr.HasRows)
{
while(rdr.Read())
{
var id = Convert.ToInt32(rdr[0]);
var name = rdr[1].ToString();
var perBox = Convert.ToInt32(rdr[2]);
Add(new Stock(id, name, perBox));
}
conn.Close();
}
// Output is null
conn.Close();
}
else
{
// Get all products
// Get only products that are in stock
var conn = AndyServerDatabase.ConnectToStockMovementByDb(stockDb);
conn.Open();
// Compile SQL query
var q = new SqlCommand(null, conn) { CommandText = "SELECT StockID, Name, PerBox FROM Stock;" };
q.Prepare();
// Execute query
var rdr = q.ExecuteReader();
// Check that the output isn't null
if (rdr.HasRows)
{
while (rdr.Read())
{
var id = Convert.ToInt32(rdr[0]);
var name = rdr[1].ToString();
var perBox = Convert.ToInt32(rdr[2]);
Add(new Stock(id, name, perBox));
}
conn.Close();
}
// Output is null
conn.Close();
}
// Add();
}
}
Resultant XML:
<StockListResponseData xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<StockList xmlns:a="http://schemas.datacontract.org/2004/07/SMS">
<a:Stock>
<a:Id>1</a:Id>
<a:Name>Smirnoff Vodka (70cl)</a:Name>
<a:PerBox>6</a:PerBox>
<a:Quantity>0</a:Quantity>
<a:Remains>0</a:Remains>
</a:Stock>
<a:Stock>
<a:Id>2</a:Id>
<a:Name>Jagermeister (70cl)</a:Name>
<a:PerBox>6</a:PerBox>
<a:Quantity>0</a:Quantity>
<a:Remains>0</a:Remains>
</a:Stock>
</StockList>
<WasSuccessful>true</WasSuccessful>
I hope this is enough to go on, I've been stumped for ages and just can't figure out why it's behaving in such a way.. if you need additional code I haven't included please feel free to ask.
Many thanks,
Andy
Edit:
To add some context to show what is happening:
For example, I know that:
<a:Stock>
<a:Id>2</a:Id>
<a:Name>Jagermeister (70cl)</a:Name>
<a:PerBox>6</a:PerBox>
<a:Quantity>0</a:Quantity>
<a:Remains>0</a:Remains>
</a:Stock>
Has its InStock row set to 0, which means that this should not be displayed in the resultant XML if I pass in true.
I have changed the StockList constructors if(inStockOnly) to if(!inStockOnly) - I then pass in <InStockOnly>true</InStockOnly> - when it gets to the StockList constructor it is then inverted and the correct data is displayed - so it must be reading it as false by the time it gets to this if statement.
If I pass in <InStockOnly>false</InStockOnly> it still displays the "correct" results, therefore it is reading it as false until it gets to the inversion!
Likewise if I leave it as if(inStockOnly) and pass in <InStockOnly>false</InStockOnly> it displays the data for false!
I have also added requestData.InStockOnly to the StockListResponseData DataContract and there it displays it outputs the value of requestData.InStockOnly as false.
Your discovery has led me to the explanation, and someone with a problem similar to yours:
WCF DataContract DataMember order?
http://msdn.microsoft.com/en-us/library/ms729813.aspx
Next in order are the current type’s data members that do not have the Order property of the DataMemberAttribute attribute set, in alphabetical order.
When the order of data members is not explicitly specified, their serialization order is alphabetical. That explains why InStockOnly worked when it was moved to the top, because it's first alphabetically. On the other hand, why StockDatabase worked is a bit of a mystery, because that's after UserId alphabetically (does AndyServerDatabase.ConnectToStockMovementByDb() use a default value if StockDb is null?).
For the sake of argument, if for whatever reason you wanted to keep the order you have there, you could do this:
[DataContract(Namespace = "http://myWebService.com/endpoint")]
public class StockListRequestData
{
[DataMember(Order = 0)]
public string UserID { get; set; }
[DataMember(Order = 1)]
public string StockDatabase { get; set; }
[DataMember(Order = 2)]
public bool InStockOnly { get; set; }
}
In fact, it's probably a good practice to explicitly indicate the order, so adding new properties later doesn't break anything.
I tried the suggestion above and it still didn't work! Kept searching and found another solution, actually setting the 'Specified' property to true:
PackageImagesPayload payload = new PackageImagesPayload();
payload.UsesSplitBy = usesSplitBy;
payload.UsesSplitBySpecified = true;

Replacing/changing a blank or null string value in C#

I've got something like this in my property/accessor method of a constructor for my program.
using System;
namespace BusinessTrips
{
public class Expense
{
private string paymentMethod;
public Expense()
{
}
public Expense(string pmtMthd)
{
paymentMethod = pmtMthd;
}
//This is where things get problematic
public string PaymentMethod
{
get
{
return paymentMethod;
}
set
{
if (string.IsNullOrWhiteSpace(" "))
paymentMethod = "~~unspecified~~";
else paymentMethod = value;
}
}
}
}
When a new attribute is entered, for PaymentMethod, which is null or a space, this clearly does not work. Any ideas?
do you perhaps just need to replace string.IsNullOrWhiteSpace(" ") with string.IsNullOrWhiteSpace(value) ?
From your posted code, you need to call:
this.PaymentMethod = pmtMthd;
instead of
paymentMethod = pmtMthd;
The capital p will use your property instead of the string directly. This is why it's a good idea to use this. when accessing class variables. In this case, it's the capital not the this. that makes the difference, but I'd get into the habit of using this.
Jean-Barnard Pellerin's answer is correct.
But here is the full code, which I tested in LinqPad to show that it works.
public class Foo {
private string _paymentMethod = "~~unspecified~~";
public string PaymentMethod
{
get
{
return _paymentMethod;
}
set
{
if (string.IsNullOrWhiteSpace(value))
_paymentMethod = "~~unspecified~~";
else _paymentMethod = value;
}
}
}
With a main of:
void Main()
{
var f = new Foo();
f.PaymentMethod = "";
Console.WriteLine(f.PaymentMethod);
f.PaymentMethod = " ";
Console.WriteLine(f.PaymentMethod);
f.PaymentMethod = "FooBar";
Console.WriteLine(f.PaymentMethod);
}
Output from console:
~~unspecified~~
~~unspecified~~
FooBar

Categories