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);
}
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"/>
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"):
}
I am trying to do a post with HttpClient to a standard REST API. The post method I am targeting requires two key/value pairs, name and size. When I perform the post using the code below, the API returns the error "Required keys missing: size." However, I've clearly added it to the FormUrlEncodedContent.
I'm wondering if there is an encoding issue, or if I am using one of wrong types of HttpContent.
public async Task<OHDrive> Create(OHDrive drive)
{
string json = "";
var values = new Dictionary<string, string>();
//name and size are required
if (string.IsNullOrEmpty(drive.Name) || drive.Size == 0)
throw new Exception("Name and Size are required for drive creation");
values["name"] = drive.Name;
values["size"] = drive.Size.ToString();
if (drive.UserID != null)
values["user"] = drive.UserID;
if (drive.Encryption != null)
values["encryption:cipher"] = drive.Encryption;
var content = new FormUrlEncodedContent(values);
using (HttpClient client = OHUtilities.CreateClient(userID, secretKey))
{
var url = urlBase + "create";
var response = await client.PostAsync(url, content);
json = await response.Content.ReadAsStringAsync();
}
return JsonConvert.DeserializeObject<OHDrive>(json);
}
Update:
I tried switching the order of the key/value pairs, like this:
values["size"] = drive.Size.ToString();
values["name"] = drive.Name;
I then got the opposite error message: "Required keys missing: name." It's like the API is not seeing the second param for some reason. I checked the request in Fiddler and everything appears to be correct.
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#)