I have this json string that looks like:
string jsonString = "[ {"id": "1"}, {"id": "2", "category": "toys"} ]";
The quotations are already escaped in the string. And I want to find a nice way to create a link out of json that looks similar to this by converting this to GET parameters. I have only really seen solutions that work well for flat structures.
Edit: I also need tp be able to convert back into the json string.
Initial Answer
You could do something like this to turn it into a link:
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text;
public class Program
{
public static void Main()
{
dynamic obj = JArray.Parse(jsonString);
var builder = new StringBuilder();
builder.Append("?id0=" + obj[0].id);
builder.Append("&id1=" + obj[1].id);
builder.Append("&category1=" +obj[1].category);
Console.WriteLine("http://www.something.com" + builder.ToString());
}
public static string jsonString = #"[ {""id"": ""1""}, {""id"": ""2"", ""category"": ""toys""} ]";
}
Output:
http://www.something.com?id0=1&id1=2&category1=toys
More Generic Follow Up Answer
Based on your comment, here is something more generic:
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
JArray array = JArray.Parse(jsonString);
var builder = new StringBuilder();
for (var i = 0; i < array.Count; ++i)
{
JToken obj = array[i];
foreach (JProperty prop in obj)
{
var prefix = i == 0 ? "?" : "&";
builder.AppendFormat("{0}{1}{2}={3}", prefix, prop.Name, i, prop.Value);
}
}
Console.WriteLine("http://www.something.com" + builder.ToString());
}
public static string jsonString = #"[ {""id"": ""1""}, {""id"": ""2"", ""category"": ""toys""} ]";
}
Output:
http://www.something.com?id0=1&id1=2&category1=toys
Okay to answer my own question, this isn't a good way to solve the problem. The json string can be very large and may be truncated or denied if over 2048 characters on the server.
The best approach is to create a jsonHashTable.json that will store the hash of what you are trying to send as the key, and the thing you are sending as a value. Then email the hash/key. Have the controller receiving the hash use the table to look up what data was needed.
Related
I have a requirement to store json in a single line(without any formatting) inside a blob storage file. I am using azure function with Newtonsoft.JSon properties for some manipulation purpose and then writing to a blob . But when I try to using JToken.Parse I am getting exception or internal server error.Below is the code I am using:
#r "Newtonsoft.Json"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public static async Task<IActionResult> Run(HttpRequest req,TextWriter outputBlob,ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
log.LogInformation($"Response is {requestBody}");
dynamic jObject = JsonConvert.DeserializeObject(requestBody);
JToken jCategory = jObject;
var clus = jCategory["clusters"];
foreach(JObject item in clus)
{
var custom_tag=item["custom_tags"];
var app_logical_name = item.SelectToken("custom_tags.app_name");
item.SelectToken("init_scripts_safe_mode").Parent.AddAfterSelf(new JProperty("app_logical_name",app_logical_name));
}
var clus2 = JsonConvert.SerializeObject(jCategory,Formatting.None);
//var clus_new=JArray.Parse(clus).toString(Newtonsoft.Json.Formatting.None);
outputBlob.Write(clus2);
// outputBlob.Write(clus_new);
return new OkObjectResult(requestBody);
}
I have tried both ways but both are giving runtime errors. I just need to put the json in a single line(without any formatting) and write to blob.Can you please help me in this ?
This is the structure on my side:
{
"clusters":[
{
"custom_tags":{
"app_name": "appname1"
},
"init_scripts_safe_mode":{
"xxx": "yyy"
}
},
{
"custom_tags":{
"app_name": "appname2"
},
"init_scripts_safe_mode":{
"xxx2": "yyy2"
}
}
],
"test":"333"
}
And this is my code:
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace FunctionApp3
{
public static class Function1
{
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
log.LogInformation($"Response is {requestBody}");
dynamic jObject = JsonConvert.DeserializeObject(requestBody);
JToken jCategory = jObject;
var clus = jCategory["clusters"];s2 = JsonConvert.SerializeObject(jCategory, Formatting.None);
foreach (JObject item in clus)
{
var custom_tag = item["custom_tags"];
var app_logical_name = item.SelectToken("custom_tags.app_name");
var xxx = item.SelectToken("init_scripts_safe_mode");
xxx.Parent.AddAfterSelf(new JProperty("app_logical_name", app_logical_name));
log.LogInformation(JsonConvert.SerializeObject(custom_tag, Formatting.None));
log.LogInformation(JsonConvert.SerializeObject(app_logical_name, Formatting.None));
}
return new OkObjectResult(clus);
}
}
}
It seems no problem:
If you get the server side error, please check the details log to get where is the error comes from.
The 500 error is not helpful to solve this problem, you need to check the specific error of the azure function. You can use application insights to get the details error. The function must configure the corresponding application insights before you can view the log on the portal.
So you need to configure an application insights to your function app like this:
Then your function app will restart.
Of course, you can also go to kudu to view:
First, go to advanced tools, then click 'GO',
Then After you go to kudu, click Debug Console -> CMD -> LogFiles -> Application -> Functions -> yourtriggername. You will find log file there.
If you are based on linux OS, after go to kudu, just click 'log stream'(this is not supportted to consumption plan for linux.).
I'm creating a query to include Cosmos entities from the last 30 days:
var filter = TableQuery.GenerateFilterConditionForDate(
"Timestamp",
QueryComparisons.GreaterThanOrEqual,
DateTimeOffset.Now.Date.AddDays(-30));
Next I create a query using this filter:
var query = new TableQuery<ResponseEntity>().Where(filter);
Next I execute the query:
var result = await table.ExecuteQuerySegmentedAsync(query, null);
However, for some reason, the result always contains zero (0) hits.
If I execute the query without any filter...
var query = new TableQuery<ResponseEntity>();
...I do get all entities.
Looking at the generated filter string, it looks OK to me (and identical to the one in the Azure portal when using the query builder for Cosmos):
Timestamp ge datetime'2018-09-15T22:00:00.0000000Z'
Is there any limitation on querying based on Timestamp?
Edit: Tried switching to the new Microsoft.Azure.Cosmos.Table NuGet package (currently in preview, version 0.9.1), but I'm still not getting any results when filtering by Timestamp.
Please refer to my working code.
code:
using Microsoft.Azure.CosmosDB.Table;
using Microsoft.Azure.Storage;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JayGongCosmosTable
{
class Program
{
static void Main(string[] args)
{
TableQuerySegment <ResponseEntity> resultE= QueryTableAsync("test").Result;
foreach(ResponseEntity re in resultE)
{
Console.WriteLine("Timestamp: "+re.Timestamp);
Console.WriteLine("------------------------------------------");
}
Console.WriteLine("execute done");
Console.ReadLine();
}
public static async Task<TableQuerySegment<ResponseEntity>> QueryTableAsync(string tableName)
{
CloudStorageAccount storageAccount = CreateStorageAccountFromConnectionString("***");
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
CloudTable table = tableClient.GetTableReference(tableName);
var filter = TableQuery.GenerateFilterConditionForDate(
"Timestamp",
QueryComparisons.GreaterThanOrEqual,
//QueryComparisons.LessThanOrEqual,
DateTimeOffset.Now.AddDays(-10).Date);
Console.WriteLine(filter);
var query = new TableQuery<ResponseEntity>().Where(filter);
var result = await table.ExecuteQuerySegmentedAsync(query, null);
return result;
}
}
class ResponseEntity : TableEntity
{
public string Name { get; set; }
public DateTimeOffset logtime { get; set; }
}
}
My data list as below without filter:
If I used Timestamp as filter, it works:
Another thing I'd like to mention is, please avoid timestamp interval query if possible. Such a query will result in a whole table scan in server side. If timestamp interval query is needed usually in your scenario, please consider choosing timestamp as your partition key or row key to optimize the query performance.
Just for summary, finally , the solution is uninstalling WindowsAzure.Storage and switch using statements to use types from Microsoft.Azure.CosmosDB.Table instead.
I am trying to make a web API Post method call as follows but it not working as expected,xmlcontent seems OK but somehow the formatting seems messed up when the request is being sent and the response throws an error ,I double checked the XML from python and it works,is there a better way to create and send the XML?what am I doing wrong?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
namespace WebApiXML
{
public class Program
{
static void Main(string[] args)
{
testWCF2(); //Or whatever
Console.ReadLine();
}
public static async Task testWCF2()
{
string xmlcontent = #"<SoftwareProductBuild>
<BuildSource>DATASOURCE</BuildSource>
<BuiltBy>username1</BuiltBy>
<CreatedBy>username1</CreatedBy>
<Name>username1_1959965_1969310_524f7fef-5b37-11e7-b4ee-f0921c133f10_UL.AB.1.2_test2</Name>
<Status>Approved</Status>
<BuiltOn>2017-06-27T06:20:30.275690</BuiltOn>
<Tag>username1_1959965_1969310_524f7fef-5b37-11e7-b4ee-f0921c133f10_test2</Tag>
<Keywords>
<KeywordInfo>
<Name>subystem</Name>
</KeywordInfo>
</Keywords>
<SoftwareImageBuilds>
<SoftwareImageBuild>
<Type>LA</Type>
<Name>username1_1959965_1969310_524f7fef-5b37-11e7-b4ee-f0921c133f10_UL.AB.1.2_test2</Name>
<Location>\\location1\data1\PRECOMMIT_OS_DEF</Location>
<Variant>PRECOMMIT_OS_DEF</Variant>
<LoadType>Direct</LoadType>
<Target>msm8998</Target>
<SoftwareImages>
<SoftwareImage>
<Name>UL.AB.1.2</Name>
</SoftwareImage>
</SoftwareImages>
</SoftwareImageBuild>
</SoftwareImageBuilds>
</SoftwareProductBuild>";
#region using
using (var client = new System.Net.Http.HttpClient())
{
var response = await client.PostAsXmlAsync("http://server:8100/api/SoftwareProductBuild", xmlcontent);
if (!response.IsSuccessStatusCode)
{
//throw new InvalidUriException("Some error with details.");
Console.WriteLine(response);
}
Console.WriteLine("Printing DEV Pool Response\n");
}
#endregion
//return null;
}
}
}
PostAsXmlAsync will try to serialize the object passed to it. So you have a string that contains XML and then try to post the string as XML(Double serialization).
Use StringContent, giving it the XML string value and set the content type to appropriate media type, then post it. i.e. client.PostAsync(url, content)
using (var client = new System.Net.Http.HttpClient()) {
var url = "http://server:8100/api/SoftwareProductBuild";
var content = new StringContent(xmlcontent, Encoding.UTF8, "application/xml");
var response = await client.PostAsync(url, content);
if (response.IsSuccessStatusCode) {
var responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine("Printing DEV Pool Response\n");
Console.WriteLine(responseBody);
} else {
Console.WriteLine(string.Format("Bad Response {0} \n", response.StatusCode.ToString()));
}
}
I've asp.net webservice with json returning data, when I call it, it return me data in json but embed it in xml.
What should I do on the server side to ensure that my webservice just returns json?
My .asmx service is as below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;
using System.Web.Script.Serialization;
using System.Text;
using System.Collections;
using System.IO;
using System.Xml;
[WebMethod(Description = "DemoMethod to get Total.")]
public string GetTotal(string a, string b, string c)
{
List<Hashtable> objMyclass = new List<Hashtable>();
JSonOutPutProperties jsonProperty = new JSonOutPutProperties();
//
int total = Convert.ToInt32(a) + Convert.ToInt32(b) + Convert.ToInt32(c);
jsonProperty.Properties.Add("Total", total);
objMyclass.Add(jsonProperty.Properties);
//
JsonOutput objjson = new JsonOutput();
objjson.objectcount = objMyclass.Count;
objjson.objectname = "Total";
objjson.objectvalues = objMyclass;
//
JavaScriptSerializer js = new JavaScriptSerializer();
string strJSON = js.Serialize(objjson);
return strJSON;
}
The problem may be solved if you add the following line to your method:
[WebMethod(Description = "DemoMethod to get Total.")]
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
public string GetTotal(string a, string b, string c)
{
...
And you probably have to make sure that you are using post instead of get.. Scott Guthrie has another good post on json
Please take a look at the following question how-to-let-an-asmx-file-output-json or the other links in that post. I had a similar problem once.
There is a auction website in, the requirement is that everytime user make a bidding on an auction. That action will be posted on their facebook wall if the user allow us to post on their behalf. Is this possible to do and what i have to know to be able to do this. I don't know much about facebook application development.
I don't have knowledge of facebook-c#-sdk (as you tagged) but for this need to follow these steps
Authenticate user using facebook OAuth 2.0 with user_status permission
and the you need to call status api with required param
after googling I found a small solution to update status using facebook-c#-sdk
FacebookClient fbClient = new FacebookClient(accessToken);
parameters = new Dictionary<string, object> {
{ "message", "this is my test message" }
};
fbClient.Post("me/feed", parameters);
The answer above is a possible solution, but a bit clunky.
Leveraging Open Graph Actions would be better.
Your starting point would bd to read:
https://developers.facebook.com/docs/opengraph/
It's not quite as easy as FB suggest of course and the documentation is sketchy, but for an automated, 'frictionless' action as per your requirement, this is the route to follow.
I created an video tutorial and sample source code for doing exactly this.
Video/Code:
http://www.markhagan.me/Samples/Grant-Access-And-Post-As-Facebook-User-ASPNet
If you don't feel like going to my website, here is the source code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Facebook;
namespace FBO
{
public partial class facebooksync : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
CheckAuthorization();
}
private void CheckAuthorization()
{
string app_id = "374961455917802";
string app_secret = "9153b340ee604f7917fd57c7ab08b3fa";
string scope = "publish_stream,manage_pages";
if (Request["code"] == null)
{
Response.Redirect(string.Format(
"https://graph.facebook.com/oauth/authorize?client_id={0}&redirect_uri={1}&scope={2}",
app_id, Request.Url.AbsoluteUri, scope));
}
else
{
Dictionary<string, string> tokens = new Dictionary<string, string>();
string url = string.Format("https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&scope={2}&code={3}&client_secret={4}",
app_id, Request.Url.AbsoluteUri, scope, Request["code"].ToString(), app_secret);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
string vals = reader.ReadToEnd();
foreach (string token in vals.Split('&'))
{
//meh.aspx?token1=steve&token2=jake&...
tokens.Add(token.Substring(0, token.IndexOf("=")),
token.Substring(token.IndexOf("=") + 1, token.Length - token.IndexOf("=") - 1));
}
}
string access_token = tokens["access_token"];
var client = new FacebookClient(access_token);
client.Post("/me/feed", new { message = "markhagan.me video tutorial" });
}
}
}
}