Entity not passed on UpdateAsync - json

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.

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; }

Required property not found in 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.

Dream Factory .NET SDK Post records Unique Integrity Error

In teh .NET SDK your create record method passes a 0 for id on all records as this is unknown until teh response comes back with the id's populated etc
It Seems that the JSON DefaultValueHandling = DefaultValueHandling.Ignore is not working on the freshly minted int '0' id's
An therefore the body has the id:0 and trys inserts the records with id:0 on all and trips a Unique constraint on the inner exception in fiddler
I had a similar problem with DreamFactory
I added a conditional Property Serialization attribute to the Poco/DTO for the staff record as an example
internal class StaffRecord
{
public bool ShouldSerializeUid()
{
return Uid != 0;
}
public int Uid { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public bool Active { get; set; }
public override string ToString()
{
return string.Format("{0}: name = {1} {2}, age = {3}, active = {4}", Uid, FirstName, LastName, Age, Active);
}
}
This now works as expected on both serialization/deserialization
Here is the docs in the JSON.NET docs
Conditional Property Serialization
Cheers :D

JSON deserialization throws circular reference ONLY in live build

I have a strange issue that I can't wrap my head around. I am trying to create an "export to csv" function for my MVC4 application where the relevant JSON is passed via an ajax call to my ActionResult. The ActionResult deserializes the stringify'd JSON (with JSON.Net), writes it to a file in csv format, then returns the server path to the new file. My success callback then receives the path and calls the url to download.
This works fine locally, but on my live test server I get the following exception:
A circular reference was detected while serializing an object of type 'System.Reflection.RuntimeModule'.
The JSON (and subsequently the objects they are deserialized to) are slightly complex. They come from a grouped subset of a SlickGrid DataView. I was getting circular reference exceptions when I included the aggregate information for column totals (this is only relevant to those that are versed in SlickGrid, I do not believe the data being passed to the server is an issue), but I've removed them before passing the JSON to the server. Here is my JSON to C# class structure:
[Serializable]
public class Row
{
public int id { get; set; }
public DateTime DateCreated { get; set; }
public int RefNo { get; set; }
public string ClientName { get; set; }
public string Plate { get; set; }
public string Address1 { get; set; }
public int? ProductID { get; set; }
public string Product { get; set; }
public string S1 { get; set; }
public string S2 { get; set; }
}
[Serializable]
public class RootReportObject
{
public bool __group { get; set; }
public int level { get; set; }
public int count { get; set; }
public string value { get; set; }
public string title { get; set; }
public int collapsed { get; set; }
public List<Row> rows { get; set; }
public object groups { get; set; }
public string groupingKey { get; set; }
}
The only thing that I'm thinking is that, because of the way the data is structured, the List<> of rows in the root object may be throwing the circular references during deserializtion because a group does not necessarily have unique row references.
My question is why does it work fine locally?? I have no idea what I'm missing.
That's great that the [ScriptIgnore] attribute is helping. Also, something to be completely sure of is that all of your URL paths, including in your AJAX code, resolve correctly to the application root. When some of these are wrong, this is a notorious source of problems during the move from development to production.
It doesn't sound like it is necessarily the primary issue but I don't have any understanding of your app's design. It's definitely worth looking over.

EF - Saving a new entity with linked existing entities creating duplicates

public class Car {
public string SomeProperty { get; set; }
public Manufacturer Manufacturer { get; set; }
public IList<Color> Colors { get; set; }
}
public class Manufacturer {
public int Id { get; set; }
public string Name { get; set; }
}
public class Color {
public int Id { get; set; }
public string Name { get; set; }
}
I already have tables full of Colors and Manufacturers. When I create a new car I want to be able to assign it a Color and Manufacturer bound from .net MVC.
When I save my new car with
context.Cars.Add(car);
A new Car is created (great) but a new Color and Manufacturer are also created even though these objects already had an Id and Name set that matched the content in the database.
The two solutions I see are to either write a custom save method for car, and tell the context that the Manufacturer and Color are Unchanged.
context.Cars.Add(car);
context.Entry(car.Manufacturer).State = EntityState.Unchanged;
foreach (Color color in car.Colors)
context.Entry(car.Color).State = EntityState.Unchanged;
Alternatively, to load the Manufacturer and Color from EF and then link them to the Car, instead of using the MVC bound objects.
car.Manufacturer = carRepository.GetManufacturer(car.Manufacturer.Id);
car.Colors = carRepository.GetColorsById(car.Colors);
I am not thrilled by either solution as this example is very trivial, but my real cases are far more complicated. I don't really want to have to fiddle around with EF in detail for each object I save. I have lots of complex object graphs to save and this seems very error prone.
Is there a way of making EF behave more like NHibernate, whereby you can give it something with an ID already assigned and it will assume without your intervention that it already exists?
Edit - question clarified to show collection of existing entities as well as many-to-one relationships.
Unfortunately, EF does not have anything like session.Load in NHibernate that allows you to get a proxy from an id.
The usual way to deal with this in EF is create a separate FK field containing the scalar value that corresponds to the reference. For example:
public virtual Manufacturer Manufacturer { get; set; }
public int ManufacturerId { get; set; }
Then you only have to set ManufacturerId and it will be saved correctly.
(So much for "POCO" and "code first". Pffffff)
You can define scalar properties in your entities and bind the values to them instead. Eg add
ManufacturerId and ColorId
public class Car {
public string SomeProperty { get; set; }
public int? ManufacturerId { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
public int? ColorId { get; set; }
public virtual Color Color { get; set; }
}
Then set those scalar properties when you assign (eg through a DropDownList)
This way you can avoid loading many related entities to populate the entity.