JsonSerializer fails to de-serialize DateTimes in Azure Function - json

I have an Azure Function that receives some JSON from a queue, fx.
{"FromDate":"2020-05-26T07:15:00.3714532+00:00","ToDate":"2020-06-25T07:15:00.3714532+00:00"}
Using System.Text.Json.JsonSerializer I am trying to de-serialize this JSON into an object of the following type:
public class DateRange
{
public DateTime? FromDate { get; set; }
public DateTime? ToDate { get; set; }
}
The de-serialization:
var dateRange = JsonSerializer.Deserialize<DateRange>(json);
This does not work in Azure - FromDate and ToDate are always parsed to the default date 1/1/0001 12:00:00 AM. The strange thing is that the JSON is created from another Azure Function with JsonSerializer.Serialize(dateRange).
But if I run the Azure Function locally it does work.
It seems from the documentation, that the date/time format
"yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF('+'/'-')HH':'mm"
sent in the JSON is supported (which makes sense because it is created by JsonSerializer.Serialize()).
Why does it fail to de-serialize my JSON? And why does it work locally but not on Azure?

Are you using a queue which is bonded as an input to your function (and triggers it)? Could you show how you write the serialized string to queue and then how you read it from the queue before deserialization?
Are you sure that the string which is taken from the message looks exactly like in your example?
I am asking because the messages in queues bound to functions are expected to be base64 encoded which causes a lot of issues if you forget about this. And since it works locally, I would blame the transport mechanism (queue) for changing the behavior.

Related

Json convert TimeSpan Error .Net Core 2.2

i work with .net core 2.2, i tried to deserialize datas from WebApi but TimeSpan Type is not converted.
My InnerException is :{"Could not cast or convert from System.String to System.TimeSpan."}
My ErrorMessage is :{"
Error converting value "PT20H20M" to type 'System.TimeSpan'. Path 'value[0].StartTime', line 1, position 179."}
the problem is on a member of my class:
public TimeSpan StartTime { get; set; }
Can someone get the same error or can someone give me some ideas to how manage the problem.
Thanks !
Well, I guess the error is that the default converter does not know the format that you are trying to send in. You have to use a format that it understands or use a custom converter or use a string and convert it yourself afterwards.
If you run TimeSpan.Parse("PT20H20M") you will get an error that says it's not a valid format.
It seems that this call can get you a TimeSpan:
System.Xml.XmlConvert.ToTimeSpan("P2DT01H")
You can use a custom converter as described here or here (First one is for .net core 3).

Expression serialization/deserialization in C#

I try to realize database access decorator based on Expression types. So, I've already tried many different json serializing libraries, started from Newtonsoft Json till DataContractJsonSerializator and etc.
1) Most of serializators crash on Expression type serialization (including System.Text.Json.Serialization).
2) Newtonsoft.JsonSerializer successfully serialize Expression<Func<User, bool>> test = e => e.Id == sameUser.Id, where User is the class like:
public class User
{
public Guid Id { get; set; }
public string Fullname { get; set; }
}
and sameUser is an object of User class.
But Newtonsoft.JsonSerializer produces string of ~169-200 millions symbols. I don't know does Newtonsoft.JsonSerializer correctly deserialize this json of the other side becauseof the size. Ofcourse, I've tried to use different serializing options.
3) ServiceStack.Text.JsonSerializer successfully serialize Expression<Func<User, bool>> test = e => e.Id == sameUser.Id with normal json size (approx 2-3 thousands symbols), but on the deserialization Expression.Body always null after deserialization (and this really strange - serialized json has it well-serialized).
4) Serialize.Linq successfully passed the test.
I want to understand, what the reason of this strange behavior of main serializers like Newtonsoft, ServiceStack, Microsoft, etc?
P.S. I'ven't tested protobuf-net and MessagePack yet, I'll do this soon,but think they have the same troubles with Expression class object serialization/deserialization.
Expression has cyclical dependencies an non serializable references that is not suitable for serialization. If you want to serialize the debug string representation of an Expression do that in your code and serialize the string, don’t expect serialization libraries to attempt to serialize a non-serializable class that’s impossible to deserialize.
If you want to serialize code, send raw source code and use Roslyn or Code DOM to execute the source code received, you’ll need to validate any untrusted user code for potential security vulnerabilities or unwanted behavior before evaluating it.

How to include time zone in Web API 2 JSON dates?

How do I configure the JSON dates produced by my Web API 2 Controller to include the time zone?
Data type used for dates in SQL Server are datetime and I don’t have the option of changing the Legacy database.
Breeze uses Json.NET to serialize/deserialize json. You can configure the serializer settings that Breeze uses by creating a custom class that inherits from Breeze.ContextProvider.BreezeConfig. Breeze will automatically discover this class and create an instance of it for all configuration tasks.
Something like this:
public class CustomBreezeConfig : Breeze.ContextProvider.BreezeConfig
{
protected override Newtonsoft.Json.JsonSerializerSettings CreateJsonSerializerSettings()
{
var ret = base.CreateJsonSerializerSettings();
ret.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
// ret.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Local;
return ret;
}
}
But before you go down this path please read this (the response specifically):
breezejs: date is not set to the right time
Try returning your DateTime formatted with .ToString() and use a custom date and time format like "K". See: http://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx#KSpecifier for more information.

Accept only number formats for a property from JSON

I am developing ASP.Net Web API application and we are exposing a REST API for different clients. I have a problem when taking users' JSON files and converting them to Data Model classes. My JSON looks like below.
{"engagementid":1,"clientname":"fsdfs","myno":"23,45","address1":"fsd","address2":"fsdfs","city":"fsdfs","zip":"fsdf","info":"fsdfs","country":"fsdfs","currency":"NOK"}
You can see that my "myno" is sent as a string. But in my Server Data Model "myno" is a double value. So what happen here is when I send the value for "myno" as "23,45", it gets assigned to MyNo property of my Model as 2345. This is wrong, because you can see that the number has been changed because of this wrong conversion. What I simply need is to restrict this conversion. I mean, I want to send an error to Client if he sends a string for "myno" property. Since it is a double value in my Server Data Model, I want to accept only numbers from the client for this property. Which means, I want it like this.
{"myno":2345} //correct
{"myno":"2345"} //wrong. I want to send a error to user by saying, "We only accept Numbers for this value"
How do I do this?
Update:
This problem gets solved if I am using int in my server-model. I mean, if a client send a string to a property which is represented as int in my model, then it gives an error to user by saying string to int conversion can not be done.
I don't whether it is correct or not. I am just telling my suggestion according to my experience. Why can't you create a custom validation attribute and check the datatype of data.
public class IsNumberAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext context)
{
if(value.GetType() != Int)
return new ValidationResult("Only Numbers Allowed");
return null;
}
}

WinRT serializing a DateTimeOffset

I'm working on a Windows 8 Metro application that references a c# WinRT project. Among other things, the c# project makes web requests to an Azure service to perform CRUD operations against a SQL Azure database.
When performing a POST operation on the service, I'm serializing an instance of a class and putting it in the body of the request.
public sealed class Foo
{
int FooId { get; set; }
DateTimeOffset FooDate { get; set; }
}
When this is serialized using the DataContractJSONSerializer, the result is something like this:
{"FooId":1,"FooDate":{"DateTime":"/Date(1342732970000)/","OffsetMinutes":-420}}
FYI that this is 7/19/2012 2:22:50PM -07:00.
OK great ... Only problem is that the Azure service is expecting just a DateTime, not a DateTimeOffset. I don't own the Azure service so I can't change its behavior.
So (ignoring that I'm losing the offset) what I need is this to serialize into:
{"FooId":1,"FooDate":"/Date(1342732970)/"}
My first approach was to add a new aliased DateTime property/datamember to the class with a getter that returns the DateTime portion of the DateTimeOffset. However, WinRT doesn't support the DateTime type.
There are a couple of hacky ways to get around this, but I wanted to see if there's an elegant way to do this before resorting to one of these:
Regex on the serialization result before the POST
String property on the class that returns a JSON formatted date
Thanks
I ended up implementing a property on the class with a getter that formats the date appropriately.
I decorated the Foo field with the IgnoreDataMember attribute so that it gets ignored during serialization. I then added a new field and gave it the alias of Foo for serialization.
Thanks