Required property not found in json - json

I'm trying to make a field mandatory before submitting to the server. For this I used the [Required] data annotation for the model validation. It work as expected for the string data types but not for a double.
For some reason it's not working for the double type property.
Here is the code that I have for the model:
public class ProductMetadata
{
[Required]
public string Barcode { get; set; }
[StringLength(50)]
[Required(AllowEmptyStrings = false, ErrorMessage="Please insert the product name!")]
public string Name { get; set; }
[Range(0, 5000)]
public double ShippingCostPerUnit { get; set; }
[Range(0, 10000)]
public int QuantityForFreeShipping { get; set; }
public Nullable<int> CategoryId { get; set; }
public bool IsDeleted { get; set; }
[Range(0, 1000000)]
[Required(ErrorMessage="Please provide a unit price for the product!")]
public double UnitPrice { get; set; }
}
The response body is a JSON response and for none of the required fields completed has the following content:
{
"Message":"The request is invalid.",
"ModelState":
{"product":["Required property 'UnitPrice' not found in JSON. Path '', line 1, position 33."],
"product.Barcode":["The Barcode field is required."],
"product.Name":["Please insert the product name!"]
}
}
I don't understand why is working fine for the Name and Barcode and not for UnitPrice.
Edit 1:
If I remove the [Required] attribute and I put the input for the UnitPrice -1 I receive the appropriate validation message, so why is not working for the Required attribute?
Edit 2: The request payload(also updated the ProductMetadata class):
{IsDelete: false, CategoryId: 1}
CategoryId: 1
IsDelete: false
Any help is appreciated! Thanks!

The fastest decision is to make Unit Price nullable
[Range(0, 1000000)]
[Required(ErrorMessage="Please provide a unit price for the product!")]
public double? UnitPrice { get; set; }
The problem is the field Unit Price is missing in json and JSON Formatter tries to deserialize double and receives exception before Required is executed.

Related

Model State Always true even when the required field is not sent

I am simply calling an API and passing an object as a parameter and everything works fine. But then i wanted to validate the model before going any further so i simply wrote [Required] above the fields i always wanted filled.
MODEL
public class Consent
{
public Consent()
{
}
public int Id { get; set; }
[Required]
public int FacilityId { get; set; }
public string Heading { get; set; }
public string Description { get; set; }
}
and validate the model state in controller like this
public ActionResult<int> AddConsent(Consent consent)
{
if(!ModelState.IsValid){
throw new CustomException("000-0000-000", "Validation failed");
}
//Further Code
}
By this i expected model state to be false when i don't send the facilityId when i call the api
JSON
{
"heading": "HeadingFromPostman5",
"description": "DiscriptiomFromPostman5"
}
but its still true . I know .Net core is allocating 0 to int value when null but how can i validate it then? Whats the work around for this?
Simply replace this line:
[Required]
public int FacilityId { get; set; }
With this:
[Required]
public int? FacilityId { get; set; }
The Required attribute works well for nullable reference objects. For primitives, when an instance is created, the default value (in this case 0 for int) is assigned for FacilityId, and hence the Required won't work. If you make the FacilityId as nullable int then the Required attribute will work fine.
[Required]
public int? FacilityId { get; set; }

how to pass json data to controller in aspnetcore 2

I have a json data.
Aim: I want to pass json data from view to aspnetcore controller, something like
public IActionResult(PRICES[] things)
{
}
but no success!..
model is:
public class PRICES :IEntity
{
public int ID { get; set; }
public decimal? PRICE { get; set; }
public decimal? PRICE2 { get; set; }
public decimal? PRICE3 { get; set; }
public decimal? PRICE4 { get; set; }
}
JSON data is:
"{"things":[{"ID":1,"PRICE":1.23,"PRICE2":2.34,"PRICE3":3.45,"PRICE4":5.67},{"ID":2,"PRICE":4.53,"PRICE2":6.34,"PRICE3":6.45,"PRICE4":7.67},{"ID":3,"PRICE":100,"PRICE2":0,"PRICE3":0,"PRICE4":0},{"ID":4,"PRICE":200,"PRICE2":3434,"PRICE3":0,"PRICE4":0},{"ID":5,"PRICE":11,"PRICE2":0,"PRICE3":2,"PRICE4":33},{"ID":6,"PRICE":3,"PRICE2":0,"PRICE3":0,"PRICE4":0},{"ID":7,"PRICE":4,"PRICE2":33,"PRICE3":0,"PRICE4":0},{"ID":8,"PRICE":1,"PRICE2":0,"PRICE3":0,"PRICE4":0},{"ID":9,"PRICE":100,"PRICE2":118,"PRICE3":3,"PRICE4":4}]}"
enter image description here
it took 4-5 hours, no success. any response will be preciated.
Your action method accepts an array.PRICES[] things.But you are sending a Json Object.
Remove things part and send only [{},{}]. ie send a json array.
or else refactor the action method to accept an object like
public class Things
{
public IList<PRICES> Things { get; set; }
}
}

Deserialize json invalid Property names

Part of the json read from Mailchimp looks like this.
"interests": {
"5e0344ae18": true,
"545e5bdb01": true,
"33aa542ea0": true,
"f51a5f9716": true,
"31109a4d58": true,
"bf5f946fd4": true,
"563320981e": false
}
So the properties used for deserialize should be this I believe.
public Interests interests { get; set; }
public class Interests
{
public bool 5e0344ae18 { get; set; }
public bool 545e5bdb01 { get; set; }
public bool 33aa542ea0 { get; set; }
public bool f51a5f9716 { get; set; }
public bool 31109a4d58 { get; set; }
public bool bf5f946fd4 { get; set; }
public bool 563320981e { get; set; }
}
However the property names consisting of numbers and letters aren't valid with compile error for each like 'Invalid token '5e0344' in class, struct, or interface member declaration'.
How can the property name match the name in the json data?
While I don't believe you will be able to use property names beginning with numbers, you could possibly prefix these with a character or string and do some manual parsing.
Assuming you're working with C#, http://www.newtonsoft.com/json/help/html/t_newtonsoft_json_linq_jobject.htm may allow you to handle the JSON response and parse properties without using the automatic deserialize I'm guessing you're currently using.
Here's another post I found describing a similar problem and some potential solutions: Parse jsonObject when field names are unknowm
You can use Data Annotations to map your JSON properties to your Model properties
This works both ways (incoming/outgoing):
using Newtonsoft.Json; // or Json.Net (built-in)
[JsonProperty(PropertyName = "5e0344ae18")]
public bool YourPropertyName { get; set; }

Newtonsoft JSON deserialize and write data

I have the following class Visual Studio created from the JSON pasted below.
public class Rootobject
{
public Class1[] Property1 { get; set; }
}
public class Class1
{
public string id { get; set; }
public string comments { get; set; }
public DateTime createdDate { get; set; }
public DateTime modifiedDate { get; set; }
public string createdBy { get; set; }
public string modifiedBy { get; set; }
}
-----JSON-----
[{"id":"00a17000000LmTOAA0","comments":"This is a comment or note added from code","createdDate":"2015-03-13T15:52:02.000+0000","modifiedDate":"2015-03-13T15:52:02.000+0000","createdBy":"Contact","modifiedBy":"Contact"},{"id":"00a17000000LmTTAA0","comments":"This is a comment or note added from code","createdDate":"2015-03-13T15:53:19.000+0000","modifiedDate":"2015-03-13T15:53:19.000+0000","createdBy":"Contact","modifiedBy":"Contact"},{"id":"00a17000000LmTYAA0","comments":"This is a comment or note added from code","createdDate":"2015-03-13T15:54:29.000+0000","modifiedDate":"2015-03-13T15:54:29.000+0000","createdBy":"Contact","modifiedBy":"Contact"},{"id":"00a17000000LmU7AAK","comments":"New Note Entered by Requester: This is a comment or note added from code","createdDate":"2015-03-13T16:39:43.000+0000","modifiedDate":"2015-03-13T16:39:43.000+0000","createdBy":"Contact","modifiedBy":"Contact"},{"id":"00a17000000LmW3AAK","comments":"added this comment from SalesF app as an agent","createdDate":"2015-03-13T17:37:24.000+0000","modifiedDate":"2015-03-13T17:37:24.000+0000","createdBy":"Agent","modifiedBy":"Agent"}]
I'm trying to create an object and do a foreach and get the data... I keep getting error Cannot deserialize the JSON array (e.g. [1,2,3]) into type ' ' because type requires JSON object (e.g. {“name”:“value”}) to deserialize correctly.
I have tried this among other things:
var jsonResponseNotes = JsonConvert.DeserializeObject<Rootobject>(GetCommentsByID());
Any Ideas would be greatly appreciated!!!
you just need the root class:
public class RootObject
{
public string id { get; set; }
public string comments { get; set; }
public string createdDate { get; set; }
public string modifiedDate { get; set; }
public string createdBy { get; set; }
public string modifiedBy { get; set; }
}
and then deserialize it like this:
var result = JsonConvert.DeserializeObject<List<RootObject>>(json);
This is a list of your object. You will need to deserialize as such. Your code should be:
var jsonResponseNotes = JsonConvert.DeserializeObject<List<Class1>>(GetCommentsByID());
Edit
Just noticed your root object property is an array. Still, I believe arrays deserialize into list objects. I've adjusted my code.

Entity not passed on UpdateAsync

Currently I can insert and lookup entities perfectly fine, however when I do
await myTable.UpdateAsync(entity);
It correctly goes into the corresponding TableController but no entities are passed through, every field is null, or its MinValue.
I can put the same entity into an
await myTable.InsertAsync(entity);
and all variables correctly come through at the other end.
Just to add some more information, I am getting the entity originally by
Entity entity = await myTable.LookupAsync(id);
Then I update values on this entity and pass it to the UpdateAsync
The Entity definition on my mobile app is
public Guid Id { get; set; }
public String firstName { get; set; }
public String lastName { get; set; }
public DateTime added { get; set; }
[Microsoft.WindowsAzure.MobileServices.Version]
public string Version { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public DateTimeOffset? UpdatedAt { get; set; }
public bool Deleted { get; set; }
The entity definition is the same at the TableController, the only difference is that I don't specify the CreatedAt, UpdatedAt, Deleted and Version as they are part of EntityData that I am inheriting from.
At the TableController end here is some more information on the patch.
patch.GetUnchangedPropertyNames().ToList();
Count = 5
[0]: "added"
[1]: "firstName"
[2]: "lastName"
[3]: "Version"
[4]: "CreatedAt"
patch.GetChangedPropertyNames().ToList();
Count = 3
[0]: "Id"
[1]: "UpdatedAt"
[2]: "Deleted"
I also tried changing the Id to a string and removing the DateTime at both ends yet the firstName and lastName never come through.
Due to more debugging (as per my comments below) I correct my statement and say that it is at the TableController end. It is not accepting anything other than Booleans.
The dynamic view will show DateTime or Int32 but no String. For example I added an integer property to my entity and sent this through
{
"Deleted":"false",
"test":123,
"firstName":"test"
}
But here is what I get in the controller.
Just a note, I can change Deleted to true and it reflects correctly.