I have a method that originally returned an HttpResponseMessage and I'd like to convert this to return IHttpActionResult.
My problem is the current code is using JSON.Net to serialize a complex generic tree structure, which it does well using a custom JsonConverter I wrote (the code is working fine).
Here's what it returns:
string json = NodeToJson(personNode);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(json, Encoding.UTF8, "application/json");
return response;
The NodeToJson method is where the custom converter comes into play ...
private static string NodeToJson(Node<Person> personNode) {
var settings = new JsonSerializerSettings {
Converters = new List<JsonConverter> { new OrgChartConverter() },
Formatting = Formatting.Indented
};
return JsonConvert.SerializeObject(personNode, settings);
}
Note this returns a string, formatted as JSON.
If I switch this to IHttpActionResult, it seems to fail regardless of what I try. I can just leave it (it works) but I am supposed to be using best practices for this and IHttpActionResult seems to be what I should be using.
I have tried to return Json(json); but this results in invalid, unparsable JSON, presumably because it's trying to do a double conversion?
return Ok(json); results in the JSON string being wrapped in XML.
What is the right way to do this?
EDIT:
I have successfully converted every method in this project to use IHttpActionResult now except this particular method.
It's a serialization of a generic tree to JSON. Regardless of what approach I try, I get back invalid JSON. The HttpResponseMsessage approach works fine, but I can not get valid JSON back with IHttpActionResult.
You can create your own IHttpActionResult class instance to return the JSON and a method in your controller or base controller class to utilize it.
Create the IHttpActionResult instance that sets the content and status code:
public class JsonTextActionResult : IHttpActionResult
{
public HttpRequestMessage Request { get; }
public string JsonText { get; }
public JsonTextActionResult(HttpRequestMessage request, string jsonText)
{
Request = request;
JsonText = jsonText;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Execute());
}
public HttpResponseMessage Execute()
{
var response = this.Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(JsonText, Encoding.UTF8, "application/json");
return response;
}
}
Add a method to your controller to create the result. Here is a Web API example:
public class MyApiController : ApiController
{
protected internal virtual JsonTextActionResult JsonText(string jsonText)
{
return new JsonTextActionResult(Request, jsonText);
}
[HttpGet]
public IHttpActionResult GetJson()
{
string json = GetSomeJsonText();
return JsonText(json);
}
}
Another recommendation is as below;
var json = JToken.FromObject(yourObject);
return Ok(json);
I've got the same problem and this piece of code worked for me (Using Newtonsoft.Json nuget package to deserialize the json):
var unserializedContent = JsonConvert.DeserializeObject(json);
return Json(unserializedContent);
It seems we must have an object in order to Json() work as it should.
Some of the solutions here are converting string to JSON, that's not necessary.
You are just using computer resources for nothing.
// Instead of
// return Ok(jsonstring);
// do:
HttpResponseMessage response = this.Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(jsonstring, Encoding.UTF8, "application/json");
Request.RegisterForDispose(response); //To avoid the Pragma CA2000 warning
return ResponseMessage(response);
Another solution At client side
You can make a small change to be prepared to receive a string and convert it if necessary. The code bellow is Javascript
var data;
if (typeof weapiresponse == "string")
data = JSON.parse(weapiresponse);
else
data = weapiresponse;
If you have no intention of using XML as a return type, you can also remove the XmlFormatter in your WebApiConfig:
config.Formatters.Remove(config.Formatters.XmlFormatter);
The correct way is to return:
Ok(json);
It's converting the result to XML because that's the default accepted return type. Try adding:
Accept: application/json into your API request headers, I think that should resolve the issue.
I had the same problem with web-service returning JSON string in a XML-tag. I tried all the simple solutions Like :
return Json(text) , json deserialize and adding config.Formatter for json, but that did't help. I got double cotes around the json object or it was malformed.
Only the solution written by TGRA worked for me.
create your own IHttpActionResult class instance to return the JSON
For me, the only way to return an IHttpActionResult with the string content as Json in the following.
[HttpGet]
public IHttpActionResult ReturnStringAsJson()
{
return this.ResponseMessage(new HttpResponseMessage
{
Content = new StringContent("[json string]"),
Encoding.UTF8,
"application/json"),
});
}
Related
I'm using .net core web api. in my API controller class have PATCH method as follows,
[HttpPatch("updateMessageTemplate/{templateId}")]
public IActionResult UpdateMessageTemplate([FromHeader] int tenantId, int templateId,[FromBody] testClass msg)
{
try
{
//Some implementation is here
return Accepted();
}
catch
{
return StatusCode(500);
}
}
testClass as follows,
public class testClass
{
public string body { get; set; }
}
I called the API from postman and its returns 400 BadRequest.
I placed the breakpoint in Controller method, but its not hitting. after I removed the [FromBody] testClass msg from the method parameter breakpoin hit without return 400 . why its returns 400 when I use [FromBody] testClass msg ? And how can I call this controller method from the HTTP Client ?.
I tried this, its also returns 400 BadRequest
string serviceUrl = string.Format("{0}/notification/updateMessageTemplate/{1}", ConfigurationManager.AppSettings["LtApiUrl"], templateID);
string json = "[{\"body\":\"sample text\"}]";
HttpClient client = new HttpClient();
HttpMethod method = new HttpMethod("PATCH");
HttpRequestMessage message = new HttpRequestMessage(method, serviceUrl);
StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Add("tenantId", tenantId.ToString());
client.DefaultRequestHeaders.Add("Authorization", string.Format("bearer {0}", token));
message.Content = content;
var response = client.SendAsync(message).Result;
return response.StatusCode.ToString();
How can I solve this? please help me. I deleted the previous question and this is my real problem
Updated:
I changed the postman request as.
after that its works. but when I call it through http client code its provides 400 BadRequest. how to provide JSON body correct way through http client
For you use FromBody,you need to send request with json instead of form data.You could change your postman like below:
1.change the ContentType to application/json:
2.change the Body to raw and choose the style JSON:
UPDATE:
You need change your json like below:
string json = "{\"body\":\"sample text\"}";
Could you please try this.
[HttpPatch("updateMessageTemplate/{templateId}")]
public IActionResult UpdateMessageTemplate([FromHeader] int tenantId, int templateId,
[FromBody] JsonPatchDocument<testMsg> msg)
{
try
{
//Some implementation is here
return Accepted();
}
catch
{
return StatusCode(500);
}
}
My question is referring to this question.
The answer shows only solutions where you would have to change the type of the method to HttpResponseMessage or string.
This is my method:
public IHttpActionResult Get()
{
return Ok("I am send by HTTP resonse");
}
It returns:
"I am send by HTTP resonse"
I expect:
I am send by HTTP response
Is there a way to return a simple string without quotation mark where the return type of the method is IHttpActionResult?
You can use ApiController.ResponseMessage(HttpResponseMessage) Method
Creates a ResponseMessageResult with the specified response.
ResponseMessageResult is derived from IHttpActionResult
public IHttpActionResult Get() {
var message = "I am send by HTTP response";
var httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK) {
Content = new StringContent(message, System.Text.Encoding.UTF8, "text/plain")
};
return ResponseMessage(httpResponseMessage);
}
Change it to:
public IHttpActionResult Get()
{
return Content("I am send by HTTP resonse");
}
The IHttpActionResult is WebApi2 way, you can also use
public HttpResponseMessage Get()
{
return Request.CreateResponse(HttpStatusCode.OK, "I am send by HTTP response");
}
Also if you expect without double quotes please refer to the link you specified in your question.
I am trying to send sourceFile value to web api. But in API i am receiving is null
var formVars = new Dictionary<string, string>();
formVars.Add("sourceFile", "Helloo");
HttpContent content = new FormUrlEncodedContent(formVars);
var result = client.PostAsync("ImageApi/Compare", content).Result;
string resultContent = result.Content.ReadAsStringAsync().Result;
return Content(resultContent);
API code
[HttpPost()]
public ActionResult Compare(string sourceFile)
{
return Ok(sourceFile);
}
I am using DotNet core 2.0
you need to await the result, do not try to access .Result yourself. The call would not have completed at that point.
you need to use something like this:
HttpContent content = new FormUrlEncodedContent(formVars);
var result = await client.PostAsync("ImageApi/Compare", content);
result .EnsureSuccessStatusCode();
string responseBody = await result.Content.ReadAsStringAsync();
This is based on your code and hasn't been tested but should set you on the right path to get this working. Don't ever try to do async stuff by accessing .Result.
One more thing, you need to use a model as well.
create a model class, which has all the properties you add in your dictionary.
in your case it will be something like :
public class MyModel{
public string sourceFile { get ;set; }
}
your controller becomes:
[HttpPost()]
public ActionResult Compare([FromBody]MyModel model)
{
return Ok(model.sourceFile);
}
I have the following RESTful Action on an MVC-project:
[Route("save")]
[HttpPut]
public ActionResult UpdateAllSettings(Dictionary<string,object> values){}
Currently I am stuck sending values to that Action. I tried using the following JSON-Structure:
fancyData="'values':[{'key':'k1','value':'v1'}]";
$http({url:'myurl',data: fancyData}
but values is always null.
I also tried replacing Dictionary<string,object> by List<KeyValuePair<string,object>> with the same results
You have to tell the action to look for data in the request body:
public ActionResult UpdateAllSettings([FromBody]Dictionary<string,object> values){}
In this case it would be better that you decorate the values parameter with the FromBody attribute. This gives you the benefit that when creating the PUT request you can add the JSON-content as content to the request.
httpClient.PutAsync("URL", new StringContent("YOUR JSON HERE",
Encoding.UTF8,
"application/json"));
To have better reusability just derive from StringContent and create a JSONContent-class:
public sealed class JsonContent : StringContent
{
public JsonContent(object content)
: base(JsonConvert.SerializeObject(content))
{
}
public JsonContent(object content, Encoding encoding)
: base(JsonConvert.SerializeObject(content), encoding, "application/json")
{
}
}
Note I use Json.NET as JSON library
now you can modify it to:
httpClient.PutAsync("URL", new JsonContent(yourDictionaryHere,
Encoding.UTF8,
"application/json"));
I have this action:
public IHttpActionResult SearchFor(int aboItemType, DTO.FilterColumns filter)
{
//Do stuff...
return Ok<DataSet>(ds);
}
My client does:
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
var response = client.PostAsJsonAsync(myurl).Result;
if (response.IsSuccessStatusCode)
{
var results = HttpUtility.HtmlDecode(response.Content.ReadAsStringAsync().Result);
}
The above scenario works perfectly. However, if I comment the Accept line, the action returns the dataset in json format.
I would like to force this one particular action to always send the result in xml. Is this possible? Maybe with an attribute?
I used Сonfiguration.Formatters.XmlFormatter
public IHttpActionResult Get()
{
...
return Content(HttpStatusCode.OK, Model, Configuration.Formatters.XmlFormatter);
}
Also you can do this (in the case you have to pass some http header values):
public IHttpActionResult Get()
{
var result = Request.CreateResponse(HttpStatusCode.OK,
model,
Configuration.Formatters.XmlFormatter);
result.Headers.Add("Access-Control-Allow-Origin", "*");
return ResponseMessage(result);
}