Single Line string is failing during deserialization using Jsonsoft - c#

I have the following line of code
public T PostData<T>(string url, object content)
{
var result = default(T);
var response = string.Empty;
// other lines of code setting up client in between .. ignoring them for readability
response = client.UploadString(new Uri(url, UriKind.Relative), contentString);
result = JsonConvert.DeserializeObject<T>(response, settings);
}
result line is where the code is failing.
The above post content is called from
public string GetCustomer(CustomerReq request)
{
var url = string.Format(_apiUrl + "/GetCustomer");
var result = _webApiRouter.Route<string>(url, Enums.HttpMethodType.Post, request);
return result;
}
The above code is where we pass the type as string.
It works fine for all objects until I get a as string and respone is one word ex: "test"
Int , byte , double seem to work fine .
So now I want it as below. What is the best way to handle this code in a if condition
if (response = string i.e one word )
result =(T)Convert.ChangeType(response, typeof(T));

DeserializeObject() can handle plain strings as long as they are quoted:
var test = JsonConvert.DeserializeObject<string>("\"test\"");
Working example: https://dotnetfiddle.net/35qWGB
In case you cannot change the endpoint you can simply create a second overload of PostData() that doesn't do any deserialization:
public string PostData(string url, object content)
{
// other lines of code setting up client in between .. ignoring them for readability
return client.UploadString(new Uri(url, UriKind.Relative), contentString);
}
You could also do something weird like:
public T PostData<T>(string url, object content)
{
// other lines of code setting up client in between .. ignoring them for readability
var response = client.UploadString(new Uri(url, UriKind.Relative), contentString);
return typeof(T) == typeof(string)
? (T)(object)response
: JsonConvert.DeserializeObject<T>(response, settings);
}

Related

Bad Request when trying to submit long string to Asp.Net Web Api 2 controller method

I want to check if a long string exists in a column in my database. The string contains spaces, special characters and carriage return / line feeds.
My controller looks like this
[ResponseType(typeof(ReportsDTO.ReportDTO))]
[Route("api/Reports/GetReportIfExists/Value={text}")]
public IHttpActionResult GetReportIfExists(string text)
{
Report report = db.Reports.Where(x => x.reporttext == text).First();
if (report == null)
{
return NotFound();
}
ReportsDTO.ReportDTO reportDTO = TranslateDTO.ConvertReportToDTO(report);
return Ok(reportDTO);
}
And I called it like this
static async Task<string> GetReportAsync(string reporttext)
{
string responseString = string.Empty;
var builder = new UriBuilder("http://localhost/myAPI/api/Reports/GetReportIfExists/Value=" + WebUtility.HtmlEncode(reporttext));
builder.Port = -1;
string url = builder.ToString();
var response = client.GetAsync(url).Result;
if (response.IsSuccessStatusCode)
{
responseString = response.Content.ReadAsStringAsync().Result;
}
return responseString;
}
But the response comes back with 'Bad Request'.
The request works fine for simple strings what do not contain spaces or any other special characters.
How can I pass a complex long string to my controller?
First of all your route seems wrong and it should rather be
[Route("api/Reports/GetReportIfExists/{text}")]
Second be aware that every browser poses restriction on length of URI and thus if your string input is very long I would suggest pass it as body of request rather
Should be used WebUtility.UrlEncode instead of WebUtility.HtmlEncode.
Change the route to this (removed /Value={text} )
[ResponseType(typeof(ReportsDTO.ReportDTO))]
[Route("api/Reports/GetReportIfExists")]
public IHttpActionResult GetReportIfExists(string text)
{
}
and change called method to
var builder = new UriBuilder("http://localhost/myAPI/api/Reports/GetReportIfExists?text=" + WebUtility.HtmlEncode(reporttext));
Because URL has limit length you may need update in web.config
<requestLimits maxQueryString="32768"/>

F# cannot post to web api?

I have the following code to post to a web api.
[<CLIMutable>]
type MyModel = { FileName:string; Period:DateTime; DownloadedTime:DateTimeOffset; Url:string; }
let PostDownload (filepath, date, url) =
async {
try
use client = new HttpClient()
let content = { FileName = filepath; Period = date; DownloadedTime = DateTimeOffset.Now; Url = url }
let! response = Async.AwaitTask(client.PostAsJsonAsync("http://localhost:5000/api/DownloadedFiles", content))
with
| ex -> logger.Error(ex, "Exception: " + ex.Message)
} |> Async.Start
The service has the following code and the debugger shows all the fields of downloadedFile are the default values (nulls or the minimum values for value types).
[HttpPost]
public void Post([FromBody]DownloadedFile downloadedFile)
{
try
{
_context.DownloadedFile.Add(downloadedFile);
_context.SaveChanges();
}
catch (Exception ex) { ...... }
}
The fiddler shows the F# code (or PostAsJsonAsync cannot handle F# mutable record type?) added # at the end of field name?
{"FileName#":"test","Period#":"2100-01-01T00:00:00","DownloadedTime#":"2016-08-18T15:50:37.5004391-04:00","Url#":"test"}
I don't know from where you get HttpClient.PostAsJsonAsync, because it's not on the version of HttpClient I'm currently looking at. Nevertheless, I typically use this extension, which works for me:
type HttpClient with
member this.PostAsJsonAsync (requestUri : string, value : obj) =
let json = string value
let content = new StringContent (json)
content.Headers.ContentType <-
Headers.MediaTypeHeaderValue "application/json"
this.PostAsync (requestUri, content)
I just ran into this issue and lost some hours solving it.
It seems the serializer that is used in HttpClient.PostAsJsonAsync does not handle fsharp types well. The # symbol issue is also not easily googleable.
Using the following code however seems to work:
task {
let content = JObject.FromObject({ Id = "foo" }).ToString()
let! response = client.PostAsync("url", new StringContent(content, Encoding.UTF8, "application/json"))
return "Hello world"
}

Web API json responds faulty json [duplicate]

I am trying to fix an ASP.NET WebAPI method where a Json response is required. However it's returning a string instead.
Initially it was returing XML format, but I've added this line to the mvc code in App_Start\WebApiConfig.cs in order to return Json by default.
config.Formatters.Remove(config.Formatters.XmlFormatter);
We've updated the c# method as follows to use NewtonSoft:
public string Get()
{
string userid = UrlUtil.getParam(this, "userid", "");
string pwd = UrlUtil.getParam(this, "pwd", "");
string resp = DynAggrClientAPI.openSession(userid, pwd);
JsonSerializer ser = new JsonSerializer();
string jsonresp = JsonConvert.SerializeObject(resp);
return resp;
}
The resp var is coming back as a string type:
"{status:\"SUCCESS\",data:[\"4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d\"]}"
and jsonresp var looks like this :
"\"{status:\\\"SUCCESS\\\",data:[\\\"4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d\\\"]}\""
and in Chrome's F12 dev tools, the data object is :
""{status:\"SUCCESS\",data:[\"4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d\"]}""
and in Console tools, the result of angular.fromJson(data) :
"{status:"SUCCESS",data:["4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d"]}"
I would appreciate some advice on how to properly return the Json object, and NOT in any string type.
UPDATE
By intercepting the resp var, and using Mr. Chu's suggestion below, I can successfully achieve a nice clean Json object on the client.
The key is that resp needs to contains double quotes around both key:value pairs:
public HttpResponseMessage Get()
{
string userid = UrlUtil.getParam(this, "userid", "");
string pwd = UrlUtil.getParam(this, "pwd", "");
string resp = DynAggrClientAPI.openSession(userid, pwd);
resp = "{\"status\":\"SUCCESS\",\"data\":[\"194f66366a6dee8738428bf1d730691a9babb77920ec9dfa06cf\"]}"; // TEST !!!!!
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(resp, System.Text.Encoding.UTF8, "application/json");
return response;
}
in Chrome console, the response is :
Object {status: "SUCCESS", data: Array[1]}
data: Array[1]
status: "SUCCESS"
__proto__: Object
resp is already a JSON string, but it is not valid JSON (the keys are not wrapped in quotes ("). If it is returned to angular, the JavaScript JSON.parse() method is unable to deserialize it. However, you can use JSON.NET in deserialize it to a JObject and serialize it again into valid JSON and create your own HttpResponseMessage...
public HttpResponseMessage Get()
{
string userid = UrlUtil.getParam(this, "userid", "");
string pwd = UrlUtil.getParam(this, "pwd", "" );
string resp = DynAggrClientAPI.openSession(userid, pwd);
var jObject = JObject.Parse(resp);
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(jObject.ToString(), Encoding.UTF8, "application/json");
return response;
}
Or you can just return the JObject and have Web API serialize it for you...
public JObject Get()
{
string userid = UrlUtil.getParam(this, "userid", "");
string pwd = UrlUtil.getParam(this, "pwd", "" );
string resp = DynAggrClientAPI.openSession(userid, pwd);
var jObject = JObject.Parse(resp);
return jObject;
}
In either case, the Web API call should return this JSON, which is now valid...
{
"status": "SUCCESS",
"data": [
"4eb97d2c6729df98206cf214874ac1757649839fe4e24c51d21d"
]
}
In the angular code, you'd have to dig out the session id which is stored in an array called data...
userService.openUserSession(rzEnvJson).then(function (response) {
var sessionResponse = response.data; // or simply response, depending if this is a promise returned from $http
$rootScope.rgSessionVars.sessionID = sessionResponse.data[0];
});
The key to what is going on here is in the comment made by Mike Cheel; serialization is happening twice, once in the OP's code and once by Asp.Net WebAPI. That is why a string is returned instead of a Json object.
I was encountering the exact same thing. Here is a hello world example showing the problem. I first did something like this:
[Route("getall")]
public string GetAllItems()
{
var result = new
{
x = "hello",
y = "world"
};
return JsonConvert.SerializeObject(result);
}
I then tried to so something like this, thinking that I needed to return IHttpActionResult to resolve this:
[Route("getall")]
public IHttpActionResult GetAllItems()
{
var result = new
{
x = "hello",
y = "world"
};
return Ok(JsonConvert.SerializeObject(result));
}
Both these controller actions gave me a string rather than the Json object that I was wanting; so I go this:
"{\"x\":\"hello\",\"y\":\"world\"}"
Finally I saw the comment by Mike and realized that I needed to return the .Net object directly and just let WebAPI handle the serialization. So instead of returning this:
return Ok(JsonConvert.SerializeObject(result));
return this:
return Ok(result);
Then I got the result that I was expecting:
{"x":"hello","y":"world"}
I don't see what this has to do with AngularJS, but your problem is simple. Your data object is JSON encoded. So you could almost certainly access data.JsonRequestBehavior and it would be 1. But your Data field inside it is AGAIN JSON-encoded. You need to decode it before trying to use it - it's just a string when you get to this callback:
var myData = angular.fromJson(data.Data);
console.log(myData.data);
Note that your data.Data object is itself another wrapper - an array. You almost certainly want myData.data[0] to go into that sessionID field...
These other solutions weren't working for me, but I was able to get something like this to work:
[HttpGet]
public async Task Get(CancellationToken cancellationToken)
{
string userid = UrlUtil.getParam(this, "userid", "");
string pwd = UrlUtil.getParam(this, "pwd", "");
await using (Stream contentStream = await DynAggrClientAPI.openSessionStreamAsync(userid, pwd, cancellationToken))
{
Response.StatusCode = (int)HttpStatusCode.OK;
Response.ContentType = "application/json";
await contentStream.CopyToAsync(Response.Body, cancellationToken);
}
}
I had a similar problem (raw json in string, like resp) and this worked fine for me in .Net 6. I haven't checked previous versions.
[HttpGet]
public IActionResult Get()
{
string userid = UrlUtil.getParam(this, "userid", "");
string pwd = UrlUtil.getParam(this, "pwd", "" );
string resp = DynAggrClientAPI.openSession(userid, pwd);
return Content(resp, "application/json"):
}

Consuming json input from url ,deserialize into c# & retrieve values from web API

I have been stuck in trying figure out the syntax for a particular scenario.
Scenario: When I give a JSON string as argument in the URL, I want the url to consume an API and retrieve the details from that API, as per the given input.
My project needs deserialization into c# so, I used JSON.NET for the same.
Say: input is - Profile-id : 123456789
The output should consume details pertaining to that Pid and display.
The i/p given in url:
https://www.docscores.com/widget/api/org-profile/demo-health/npi/123456789
The expected o/p:
json string
What i have been doing is :
string url = "https://www.docscores.com/widget/api/org-profile/demo-health/npi/?profile-id=ShowProfile";
string data = GET(url);
dynamic jsonDe = JsonConvert.DeserializeObject(data);
var phyRatings = Convert.ToString(jsonDe.profile.averageRating);
Console.WriteLine(phyRatings);
public string ShowProfile(string pid)
{
}
public static string GET(string url)
{
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
string data = reader.ReadToEnd();
reader.Close();
stream.Close();
return data;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return null;
}
So, when I pass profile-id as 123456789 in the url, I want the syntax to extract other info with this Profile-id
I AM totally confused with the syntax in C#. How can I pass the argument and write inside the ShowProfile function? I searched everywhere but not able to find the correct syntax.
Can someone please tell me if this is the right way to do it?
EDIT: Sounds like you have two questions here. First is how to pass your Profile-Id in the URL, and the second is how to deserialize the JSON result into a C# object. But let me know if I'm misunderstanding.
For passing 123456789 as your profile ID, you just need to concatenate it into the URL string. So you might have
public string ShowProfile(string pid)
{
ProfileInfo info = GET(pid);
// Do what you want with the info here.
}
public static ProfileInfo GET(int profileId)
{
try
// Note this ends in "=" now.
string basePath = "/widget/api/org-profile/demo-health/npi/?profile-id=";
string path = basePath + profileId.ToString();
//...
ProfileInfo would be your custom class to match the JSON structure.
Then to deserialize the result, in your GET() method, you might instead try calling the service using HttpClient from the Microsoft.AspNet.WebApi.Client NuGet package, and then read that directly into a C# object whose structure maps to the JSON response you get (see example below). Your GET() method could then return that object, and then it'd be trivial for the ShowProfile() method to read the properties you want from that C# object.
public static ProfileInfo GET(int profileId)
{
try
{
// Note this ends in "=" now.
string basePath = "/widget/api/org-profile/demo-health/npi/?profile-id=";
string path = basePath + profileId.ToString();
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://www.docscores.com");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
ProfileInfo info = await response.Content.ReadAsAsync<ProfileInfo>();
return info;
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return null;
}
More code and info at MSDN: Calling a Web API From a .NET Client in ASP.NET Web API 2 (C#)

How to compare parsed json value in C#

I am a beginner in c# , I am creating a app in which login page requests PHP file in url and it sends Json data as response I was able to decode the Json data,But the decoded data was not able to use in string comparison as below
Program
private async void Button_Click(object sender, RoutedEventArgs e)
{
var username = usernames .Text;
var password = passwords .Password;
var postMessage = new StringContent(string.Format("username={0}&password={1}", username, password), Encoding.UTF8 , "application/x-www-form-urlencoded");
var response = await (new HttpClient()).PostAsync("http://xxxxx.xx.xxx/xlogin.php", postMessage);
var responseBody = await response.Content.ReadAsStringAsync();
var jsonString = responseBody ;
//remove "{" and "}" from sting
var result = jsonString.Replace("{", "").Replace("}", "");
//separate property name from it's value
var pair = result.Split(':');
//property will contain property name : "result"
var property = pair[0];
//value will contain property value : "Invalid"
var value = pair[1];
// String van=value .ToString() ;
MessageBox.Show(value);
if(value=="Valid")
{
Messagebox.show("success");
}
else
{
Messagebox.show("Error");
}
}
Response from URL
Json response from url is {"result":"Invalid"} while validation fails and for validation success {"result":"Valid"}
Problem
Every time I get "Valid" From url it is not accepting in if condition,more precisely string is not getting compared...any solutions?
I suspect the immediate problem is that your pair[1] value still starts and ends with a double quote - so if you print it out you'll see
"Value"
rather than
Value
You could just trim them from the start manually, but I would strongly advise you to use a JSON library instead. There's no good reason to do all of this manually, and trying to do so is very likely to lead to brittle code.
As an example, using Json.NET it's as simple as:
string json = "{\"result\":\"Valid\"}";
JObject parsed = JObject.Parse(json);
string result = (string) parsed["result"];
Console.WriteLine(result); // Prints Valid

Categories

Resources