How to handle multiple items in a POST request - asp.net-web-api

I have a request where there is multple object in the json file . I need to add them via PostMan
This is my Dto
public class CustomerDto
{
[Required(ErrorMessage = "The Id is required")]
public int Id { get; set; }
[Required(ErrorMessage = "The FirstName is required")]
public string FirstName { get; set; }
}
This is my ServiceClass, this is where i add it to a class level customerlist object for now.
public static class CustomerService
{
public static List<CustomerDto> customerList = new List<CustomerDto>() {
new CustomerDto { FirstName = "Joe", Id = 1},
new CustomerDto { FirstName = "Rose", Id = 2},
new CustomerDto { FirstName = "Sid", Id = 3 },
};
}
This is my Api Post Request
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public ActionResult<VillaDTO> addCustomer([FromBody]CustomerDTO customerDTO)
{
if (customerDTO== null)
{
return BadRequest(villaDTO);
}
CustomerService.customerList.Add(customerDTO);
return Ok(customerDTO);
}
I try to debug but before it hits the method call it throws the exceptions. I just want to know how my object is populated first.
Thanks for having a look
After updating a bad Json using Json Validator . I now get this error message.
DTO seems to be the issue .
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-58f71fb73f3af573db60c11551cb2093-792cd201f9e3f0d3-00",
"errors": {
"$": [
"The JSON value could not be converted to CustomerManagementAPI.Model.Dto.CustomerDto. Path: $ | LineNumber: 0 | BytePositionInLine: 1."
],
"customerDTO": [
"The customerDTO field is required."
]
}
}

If you're trying to post a collection
[
{
"firstName": "John",
"id": 6
},
{
"firstName": "Anna",
"id": 7
}
]
Have your action accept a collection as well
public IActionResult addCustomer([FromBody] List<CustomerDto> customers) { }

Related

Spring GraphQL mutation NullPointerException

I'm learning GraphQL in spring boot and I have created a mutation that saves used details in database. When I try to call the mutation from GraphiQL UI using following mutation query, it throws NullPointerException because the object I passed in mutation is not mapped with UserDto and I don't know why.
I have following code:
Controller
#Controller
public class UserController {
private UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
#QueryMapping(name = "userById")
public UserDto findUserById(#Argument Long id) {
return userService.findById(id);
}
#QueryMapping
public String removeUserById(#Argument Long id) {
return userService.removeById(id);
}
#MutationMapping(name = "save")
public UserDto save(#Argument UserDto user) {
return userService.save(user);
}
#QueryMapping(name = "users")
public List<UserDto> findAll() {
return userService.findAll();
}
}
GraphQL Schema
schema {
query: Query
mutation: Mutation
}
type Query{
users:[User]
userById(id:ID):User
}
type Mutation{
save(userInput:UserInput):User
}
#input types
input UserInput{
firstName:String!
lastName:String!
emailAddress:String!
ipAddress:String!
address:AddressInput!
}
input AddressInput{
addressLine1:String!
addressLine2:String!
addressLine3:String!
addressLine4:String!
addressLine5:String!
addressPostCode:Int!
}
#object types
type User{
firstName:String!
lastName:String!
emailAddress:String!
ipAddress:String!
address:Address!
}
type Address{
addressLine1:String!
addressLine2:String!
addressLine3:String!
addressLine4:String!
addressLine5:String!
addressPostCode:Int!
}
Mutation Query
mutation Save($userDto: UserInput!) {
save(userInput: $userDto) {
firstName
lastName
emailAddress
ipAddress
address {
addressLine1
addressLine2
addressLine3
addressLine4
addressLine5
addressPostCode
}
}
}
Variables
{
"userDto": {
"ipAddress": "192.168.0.124",
"firstName": "John",
"lastName": "Mark",
"emailAddress": "john#gmail.com",
"address": {
"addressLine1": "251 WC",
"addressLine2": "UC MAIN",
"addressLine3": "PB121",
"addressLine4": "New York",
"addressLine5": "USA",
"addressPostCode": 457821
}
}
}
Results
{
"errors": [
{
"message": "INTERNAL_ERROR for b6287602-fc10-6ecf-2091-b57ceaeb9f0a",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"save"
],
"extensions": {
"classification": "INTERNAL_ERROR"
}
}
],
"data": {
"save": null
}
}
When I run the GraphQL query, it throws NullPointerException in console.
Console Error
java.lang.NullPointerException: Cannot invoke "com.graphql.sample.dto.UserDto.getEmailAddress()" because "userDto" is null
I'm answering my question because I have already solved it. I had made a small mistake in controller near #Argument UserDto user as below:
#MutationMapping(name = "save")
public UserDto save(#Argument(name = "userInput") UserDto user) {
return userService.save(user);
}
The name in #Argument should match the name of parameter in Mutation type as below:
type Mutation{
save(userInput:UserInput):User
}
type User{
firstName:String!
lastName:String!
emailAddress:String!
ipAddress:String!
address:Address!
}
Reason 1:
Your save mutation result is returned to this entity. But it can be possible that a property that you are receiving might be null that's why this error is thrown, as you are using ! with each property. You can remove ! if a value can/is null
Reason 2:
I couldn't see your resolver so it might be possible that the result is not an object or the property names that you are receiving don't match with the property names inside type User. It should be same or use resolver to provide their values

Fetching data from an API in ASP.NET Core MVC

I'm facing problem while fetching data from an API in ASP.NET Core MVC controller (imdb api).
The problem is I cannot deserialize the current JSON object into type
this is my code
List<Movie> movieList = new List<Movie>();
using (var httpClient = new HttpClient())
{
using (var response = await httpClient.GetAsync("https://imdb-api.com/en/API/Title/****/tt0110413"))
{
string apiResponse = await response.Content.ReadAsStringAsync();
var Movie = JsonConvert.DeserializeObject<Movie>(apiResponse);
//movieList = JsonConvert.DeserializeObject<List<Movie>>(apiResponse);
}
}
return View();
My api data looks like this
{
"items": [
{
"id": "tt0111161",
"rank": "1",
},...
]
}
I have an issue with deserialize - any help?
You need to make sure the structure of Movie is corresponding to your json data:
public class Movie {
public List<Item> items { get; set; }
}
public class Item {
public string id { get; set; }
public string rank { get; set; }
}
Use IMDbApiLib.
GitHub:
https://github.com/IMDb-API/IMDbApiLib
Nuget:
https://nuget.org/packages/IMDbApiLib
Movie's TitleData:
https://github.com/IMDb-API/IMDbApiLib/blob/master/IMDbApiLib/Models/TitleData.cs

Return error message when Post JSON is incorrect

I need to validate a JSON before saving the information on the database. The object has the following pattern:
{
"id": "string",
"name": "string",
"description": "string",
"price": "int"
}
If the post was made with the correct JSON, I return the object saved (The ID can't be in the post, it will be generated by database).
But, if the post has a missing field or additional one I need to return an error message.
How is the best way to do this? I'm reading some articles and can't understand exactly.
I'm using spring-boot, JPA, connecting to an H2 database (MVC Pattern).
Here is my Controller and Service layer:
First, the delete method. That works as I want.
#DeleteMapping("/{id}")
#Transactional
public ResponseEntity<Product> deleteProduct(#PathVariable String id) {
ResponseEntity<Product> response = productService.deleteProduct(id);
return response;
}
public ResponseEntity<Product> deleteProduct(String id) {
Optional<Product> product = productRepository.findById(id);
if (product.isPresent()) {
productRepository.deleteById(id);
return ResponseEntity.ok().build();
} else
return ResponseEntity.notFound().build();
}
Here the Post Method. That I can't find a good way to return the response that I want:
#PostMapping
public ResponseEntity<Product> insertProduct(#RequestBody ProductForm form) {
Product product = productService.insertProduct(form);
if (product) {
return ResponseEntity.ok().body(product);
} else
return ResponseEntity.notFound().build();
}
public Product insertProduct(ProductForm form) {
Product product = form.insertConverter();
productRepository.save(product);
return product;
}
The second method in both snippets is located in a separated JavaClass.
This was what I want to return:
{
"code": integer,
"error": "string"
}

springboot mongodb crud update only changed fields

Hello i have springboot with mongodb (spring-boot-starter-data-mongodb)
My problem is if I send only one or only the fields I want to change so the other values are set to null. I found something on the internet like #DynamicUpdate but not working on mongodb can you help me with this problem. I'm a beginner, I don't know how to help and it's quite important for me, if you need more code or more information, I'll write in the comment. I hope I have described the problem sufficiently. :)
MY POJO:
#Data
#Getter
#Setter
#NoArgsConstructor
public class Person {
#Id
private String id;
private String firstName;
private String lastName;
private boolean enabled;
private String note;
Repo
#Repository
public interface PersonRepository extends MongoRepository <Person, String> {
}
i have this call
#PutMapping("/{id}")
#ResponseBody
public void UpdatePerson (#PathVariable String id , #RequestBody Person person) {
personRepository.save(person);
}
#GetMapping(path = "/{id}")
public Person getPersonByid(#PathVariable String id ){
return personRepository.findById(id).orElseThrow(PersonNotFound::new);
}
sample:
get call before update :
{
"id": "5fc940dc6d368377561dbb02",
"firstName": "Rambo",
"lastName": "Norris",
"enabled": true,
"note": "hello this is my first note from you",
}
put call :
{
"id": "5fc940dc6d368377561dbb02",
"firstName": "Chuck"
}
get call after update :
{
"id": "5fc940dc6d368377561dbb02",
"firstName": "Chuck",
"lastName": null,
"enabled": false,
"note": null,
}
what I would like
get call before update :
{
"id": "5fc940dc6d368377561dbb02",
"firstName": "Rambo",
"lastName": "Norris",
"enabled": true,
"note": "hello this is my first note from you",
}
put call :
{
"id": "5fc940dc6d368377561dbb02",
"firstName": "Chuck"
}
get call after update :
{
"id": "5fc940dc6d368377561dbb02",
"firstName": "Chuck",
"lastName": "Norris",
"enabled": true,
"note": "hello this is my first note from you",
}
You are inserting a new collection instead of updating. First, you need to get the old value from mongodb, then you need to update the collection, then save to DB.
Use the below code in #putmapping.
#PutMapping("/{id}")
#ResponseBody
public void UpdatePerson (#PathVariable String id , #RequestBody Person person) {
Person personFromDB = personRepository.findById(person.getId());
personFromDB.setFirstName(person.getFirstName());
personRepository.save(personFromDB);
}
Try updating like this
#PutMapping("/{id}")
public ResponseEntity<Person> UpdatePerson (#PathVariable String id , #RequestBody
Person person) {
Optional<Person> personData = personRepository.findById(id);
if (personData.isPresent()) {
Person _tutorial = personData.get();
if(!StringUtils.isEmpty(person.getFirstName())) {
_tutorial.setFirstName(person.getFirstName());
}
if(!StringUtils.isEmpty(person.getLastName())) {
_tutorial.setLastName(person.getLastName());
}
if(!StringUtils.isEmpty(person.getNote())) {
_tutorial.setNote(person.getNote());
}
if(!StringUtils.isEmpty(tutorial.isEnabled())) {
_tutorial.setEnabled(tutorial.isEnabled());
}
return new ResponseEntity<>(repo.save(_tutorial), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}

effective way to loopoever three array lists to compare values

I have two object of arraylist orderList, productList and one String arraylist customerIdList.I have ProductInfo POJO to be mapped with orderList and productList where cuustomerId should match.If I don't have order or productlist for given ProdId I should add standard Error and map to the ProductInfo Error.Here is what I am doing ...
public class ProductInfo {
private List<ProductDetails> products;
private List<Error> errors;
private String customerId;
}
public class ProductDetails {
private String customerId;
private Order order;
private Product product;
private List<Error> errors;
}
Sample result ...
{
"productInfo": {
"customer_id": "123",
"product_details": [
{
"customer_id": "123",
"order_details": null,
"product_details": {
"customer_id": "123"
"product_id" : "2343"
"product_name": "XYZ",
"product_type": "PQR"
...
},
"errors": [
"error_code":"6001",
"error_desc":"Failure in getting Order information from Order Service"
]
},
{
"order_details": {
"customer_id":"123"
"order_id": "3543454",
"order_date":"2016-10-12",
"order_status":"ordered"
},
"product_details": null,
"errors": [
"error_code":"6001",
"error_desc":"Failure in getting Product information from Product Service"
]
}
],
"system_errors":[]
}
}
Looping over ArrayList and Mapping
for(String customerId : customerIdList) {
for(Product product: productList) {
for(SOrder ordr: orderList) {
if(customerId.equals(product.getCustomerId()) && customerId.equals(Order.getCustomerId()) ) {
ModelMapper mapper = new ModelMapper();
Order order = mapper.map(ordr, Order.class));
productDetails.setOrder(order);
//mapping to ProductInfo
productDetailsList.add(productDetails);
}
}
}
}
I want to know if there is any better way of doing this and also I am using ModelMapper to map SOrder to Order POJO andother POJOs would like to know if there is any other efficient model mapper available.Thanks.
you can create maps from productList and orderList with customerId as key
Map<String, Product> productMap = productList.stream().collect(Collectors.toMap(p -> p.getCustomerId(), p -> p));
Map<String, Product> orderMap = orderList.stream().collect(Collectors.toMap(o -> o.getCustomerId(), o -> o));
then with just one loop you can check if there is product and order for that customer id
for(String customerId : customerIdList) {
if (productMap.containsKey(customerId) && orderMap.containsKey(customerId)) {
//do your mapping stuff here
}
}

Resources