JSON Parameter is null on calling REST API - json

I'm trying to send a URL as content from my client to my web api.
I don't want to encode it, so I'm sending it in the body as JSON.
Sending the JSON as
"{"URL":"https://www.example.com/s/otherdetail"}"
If I use method signature
[HttpPost("UploadURL/{SpecID}/{DocType}")]
public ActionResult<string> UploadSpecsURL(int SpecID, string DocType, [FromBody] JsonElement body) {
string json = System.Text.Json.JsonSerializer.Serialize(body);
then I get content
body = ValueKind = Object : "{"URL":"https://www.example.com/s/otherdetail"}"
json = "{\"URL\":\"https://www.example.com/s/otherdetail\"}"
but if I try to define my own type to receive the content
public struct URLpacket {
public string URL;
}
[HttpPost("UploadURL/{SpecID}/{DocType}")]
public ActionResult<string> UploadSpecsURL(int SpecID, string DocType, [FromBody] URLpacket packet) {
I don't get an error, but the URL is null.

you have to add getters setters to your class
public struct URLpacket {
public string URL { get; set; }
}

Related

How to return JSON from serialized JSON in Spring Rest Controller

I have a String that represents JSON:
[{"type":"ERROR","message":"some error message"}]
This String is returned by ex.contentUTF8() in the following code:
#RestControllerAdvice
#RequiredArgsConstructor
public class ControllerExceptionHandler {
#ExceptionHandler(FeignException.class)
#ResponseBody
public String afterThrowing(FeignException ex, HttpServletResponse response) {
response.setStatus(ex.status());
return ex.contentUTF8();
}
}
An HTTP client though doesn't get a JSON response though. Instead, it gets HTML with body of the response being that String. How can I instead have JSON returned? Do I need to deserialize that String?
Update
The response to the client must be exactly the JSON object that represent (would be serialized into) the String returned by ex.contentUTF8():
[{"type":"ERROR","message":"some error message"}]
So, a wrapper object like ErrorDto (as provided in a few answers) will not work.
You should return an Object that fit with your JSON representation :
public class ErrorDto {
private String type;
private String message;
}
And :
#RestControllerAdvice
#RequiredArgsConstructor
public class ControllerExceptionHandler {
#ExceptionHandler(FeignException.class)
#ResponseBody
public ErrorDto afterThrowing(FeignException ex, HttpServletResponse response) {
return new ErrorDto("your type", "your message");
}
}
Building from the answer by #Fabien, you can use the ResponseEntity<Object> class to return an application/json content type response instead. Using ResponseEntity essentially gives control over every aspect of the response.
You can try something like this instead:
#ExceptionHandler(FeignException.class)
public ResponseEntity<Object> afterThrowing(FeignException ex) {
ErrorDto payload = new ErrorDto(ex.status(), ex.contenUTF8());
return ResponseEntity
.status(ex.status())
.contentType("application/json")
.body(payload);
}

Convert Json to Object in Angular 7

This is json string {"firstName":"John" ,"lastName":"Doe" }.
I would like to convert json string to object with custom name in angular.This is c# code.
public class Example
{
[JsonProperty("firstName")]
public string FName { get; set; }
[JsonProperty("lastName")]
public string LName { get; set; }
}
Just use JSON.parse
console.log(JSON.parse('{"firstName":"John" ,"lastName":"Doe" }'))
But you shouldn't have to. How are you getting the JSON string? If you made a call to your C# api with the HttpClient like
http.get<YourModel>('apiUrl');
The response from the api should already be parsed as long as the api responded with a content type of text/json.
If you have a front-end model, use the classToPlain method of the lib class-transformer https://github.com/typestack/class-transformer
Example
import { classToPlain } from "class-transformer";
...
var yourModel: YourModel = {"firstName":"John" ,"lastName":"Doe" };
this.http.post(`${url}/AnyMethod`, classToPlain(yourModel)).pipe();
...
class YourModel{
firstName: string;
lastName: string;
}

Can't parse JSON parameter

I am using WebAPI to get the POST message. The body of the POST message:
{"datetime":"2017-01-06T20:40:44.2401244Z","filename":"somefilename.csv","datasourcename":"MyDataSource","error":"The uploaded file has no tags."}
The header included with the POST:
Content-type: application/json
My action method that handle the message:
[HttpPost]
public void SaveMessage([FromBody] string msg)
{
MyModel w = JsonConvert.DeserializeObject<MyModel>(msg);
db.MyModels.Add(w);
db.SaveChanges();
}
My question is how do I encode the JSON so that I can parse it? I can't change the incoming message. What can I do in my method so that I can read it? Right now msg always give me null.
Given that you have no control over the data being sent, then as suggested in the comments, make sure you have a model that matches the desired object model of the JSON
public class MyModel {
public DateTime datetime { get; set; }
public string filename { get; set; }
public string datasourcename { get; set; }
public string error { get; set; }
}
And take advantage of the model binding capability of the Web API framework and let the action bind a strongly typed model from the body of the request.
[HttpPost]
public IHttpActionResult SaveMessage([FromBody] MyModel model) {
if(ModelState.IsValid) {
db.MyModels.Add(w);
if(db.SaveChanges() > 0)
return Ok();
}
return BadRequest();
}
If there are any issues with saving the message the action will return HTTP Status Code 400 Bad Request, otherwise it will return HTTP Status Code 200 OK.

How to use Json File to serve as a data source for webapi

I want to retrieve data from Json file with webapi using Json file as data source.
In the controller, I have added following code:
Public HttpResponseMessage Get()
{
var json = File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath(#"~/App_Data\Bim.Json"));
return new HttpResponseMessage()
{
Content = new StringContent(json, Encoding.UTF8, "application/json"),
StatusCode = HttpStatusCode.OK
};
}
and in model,
public class bimModel
{
public string name { get; set; }
public string material { get; set; }
public string tag { get; set; }
public string contentType { get; set; }
}
Actually, I want to use a json file which is located in app_data folder, how to read data from JSON file? I am very new to the webApi, so it will be of great help if the experts can post the entire working code or as many details as possible, please.
If I am correct, I believe you want to deserialize the json text file to model classes, then serialize them back to json for the client.
To do this, you can use https://www.nuget.org/packages/newtonsoft.json/ to help you out. Follow the instructions to get the package installed.
Once you do that, you can write a function such as
public bimModel Get()
{
var json = File.ReadAllText(System.Web.HttpContext.Current.Server.MapPath(#"~/App_Data\Bim.Json"));
var model = JsonConvert.DeserializeObject<bimModel>(json);
return model;
}
If your json file is an array of bimModels, then you can change the return type and type parameter of DeserializeObject to List<bimModel>.
To ensure your server is returning json to the client, make sure your WebApiConfig class is using the JsonMediaTypeFormatter
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
config.Formatters.JsonFormatter.SerializerSettings.Formatting = Formatting.Indented;
}
And of course, be sure to include using Newtonsoft.Json; and using Newtonsoft.Json.Serialization;

Custom serialization in Service Stack using DeSerializeFn

In servicestack, I am trying to process a webhook which sends the following JSON body to a service stack endpoint:
{
"action": "actionType1",
"api_version": "1.00",
"data": {
"id": "a8d316b8-10a7-4440-a836-9bd354f656db",
//VARIABLE other properties / structure
}
}
Which I am trying to map to the following request object:
[Route("/public/Webhookhandler", HttpVerbs.Post)]
public class MyCustomRequst
{
public string action { get; set; }
public string api_version { get; set; }
public string data { get; set; } //Will be the remaining JSON
}
However, when the service stack framework processes this - the value in "data" is the correct part of the JSON body, but with all of the quotes removed - so it is no longer valid.
I have tried to override the serialization for the whole request object using something like this:
JsConfig<MyCustomRequst>.DeSerializeFn = DeserializeMyRequestDto;
public MyCustomRequst DeserializeMyRequestDto(string rawBody)
{
var result = rawBody.FromJson<MyCustomRequst>();
return result
}
But even in this case, the value of the "rawBody" variable is still the correct JSON data but with all the quotes removed, e.g.
{
action:actionType1,
api_version:1.00,
data:{id:a8d316b8-10a7-4440-a836-9bd354f656db}
}
Am I doing something wrong here? I am unsure whether I am trying to make service stack do something it is not intended to do, or whether I am missing something that would make this work.
Any help would be appreciated :-)
Your DTO should closely match the shape of the JSON, if it's always a flat object you can use a string Dictionary, e.g:
[Route("/public/Webhookhandler", HttpVerbs.Post)]
public class MyCustomRequst
{
public string action { get; set; }
public string api_version { get; set; }
public Dictionary<string,string> data { get; set; }
}
If it's a more nested object structure you can use a JsonObject for a more flexible API to parse dynamically.