I have a post method that accepts object containing decimal property as below
[HttpPost]
public async Task<IActionResult> Create(CreateDto createDto)
{
...do stuff here
}
public class CreateDto
{
[Required]
public string Id{ get; set; }
[Required]
public decimal? Rate{ get; set; }
}
when a value containing leading 0 being passed in for Rate field, eg: 0015, it is always coming in as 10.
Would appreciate if somebody could explain this phenomena.
The issue lies within aspnet core mvc JSON parser which allows leading zeros before numbers that are all in the range [0-7], and treats them as octal, to match the sort of results one would get using eval in javascript.
This behaviour contradicts with guildlines stated in on http://json.org:
"A number is very much like a C or Java number, except that the octal
and hexadecimal formats are not used."
and the syntax graph does not allow a number to have a leading non-significant zero.
RFC 4627 Section 2.4. agrees:
"Octal and hex forms are not allowed. Leading zeros are not allowed."
So in short, the only way is to use JSON parser that implements the Json specs correctly.
Reference: Override Json deserializing a number with a leading zero as a decimal and not an octal value
Related
I have a problem controlling how the xml serializer formats a Guid.
is there anyway to force the property of the first example to exclude the dashes, using the XmlSerialzer?
example:
public class Example{
[XmlElement]
public Guid Value {get; set;}
}
when serializing the above class i would get: (36 characters)
<Example>
<Value>3164fc09-1dc5-4629-b04c-e9cdc5e85de4</Value>
</Example>
but i want the value not to include dashes (32 characters)
<Example>
<Value>06102471381242609d0176b269120082</Value>
</Example>
normally i would not care about the difference, but in this particular case i don't have a choice as i have to follow a standard provided by a third party that includes a set of xsd's.
I know i can do something like this to solve the problem, but it is messy and i would like to avoid it:
public class Example
{
[XmlIgnore]
public Guid Value { get; set; }
[XmlElement(nameof(Value))]
public string ValueString {
get => Value.ToString("N");
set
{
if (Guid.TryParse(value, out var uuid))
Value = uuid;
else
throw new InvalidOperationException();
}
}
}
Provided xsd
the xsd provided by this company define the custom type to be a string with a range of 1 to 35 characters, but their documentation states that the value should always be a uuid version 4 with no dashes and 32 characters long.
the documentation provided only have a danish version.
See page 5 sekt 01.07.2016 UUID i EpisodeOfCareIdentifier for the specific problem.
about the standard (optional reading):
This standard is part of a message service between counties, hospitals and other independent healthcare specialists, regarding patient treatments.
All in all there is quite a few software systems that have to implement this standard.
We are connecting to an external system that provides a WSDL that expects decimals to be provided to 2 decimal places - i.e.:
<collectionAmount>1000.00</collectionAmount>
However, when our client serializes the SOAP request the decimals appear with a single precision:
<collectionAmount>1000.0</collectionAmount>
We have attempted to use metadata extension:
[MetadataType(typeof(amountSetRequestMetadata))]
public partial class amountSetRequest
{
internal sealed class amountSetRequestMetadata
{
[XmlIgnore]
public decimal collectionAmount { get; set; }
[System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 14, ElementName = "collectionAmount")]
public string collectionAmountString => "yay!";
}
}
amountSetRequest is the generated partial class that the WSDL service auto-generator produces. The output XML is no different so this doesn't appear to have any effect on the request.
We would think that this is fairly common, but can't find out much how this is solved. We have seen solutions that extend the base XML serializer.
What is this cleanest way to have a SOAP request serialized in this way?
So we fixed it by slightly hacking the type-system.
It turns out that decimals converted from strings and back to decimals have different precisions. Hence we did:
public void RequestAmount(decimal amount) {
var request = new amountSetRequest()
request.collectionAmount = Convert.ToDecimal(amount.ToString("F2"));
// ...
}
In doing this when the XML serializer sees the decimal, it keeps the precision that the Convert.ToDecimal uses from ToString.
Use following :
public partial class amountSetRequest
{
private decimal _collectionAmount { get; set; }
public string collectionAmount {
get {return _collectionAmount.ToString("F2");}
set {_collectionAmount = decimal.Parse(value);}
}
}
I have an API hosted on IIS Server.
I am making a request to a URI with below params.
{"CurrentTime":"2013-09-23 13:05:52",
"Measurement":[{"Comment":"Test Comment","RecordIdentifier":"7F54BF3C-6022-423B-8B8F-0121BA2AF516"}],
"Source":"ABC","Destination":"XYZ",
"FinalIdentifier":"058B5913-FAB9-4641-B02E-2729A02B5059"}
For the above request i can successfully deserialize the request parameters. Notice the value of "FinalIdentifier" and "Comment" parameter.
But, when Request like :
{"CurrentTime":"2013-09-23 13:05:52",
"Measurement":[{"Comment":"Âëīö","RecordIdentifier":"01CEBEAE-B99D-47B1-9C2D-1CB80069917B"}],
"Source":"ABC","Destination":"XYZ",
"FinalIdentifier":"058B5913-FAB9-4641-B02E-2729A02B5059"}
I can also deserialize this request successfully but the value of "FinalIdentifier" parameter is getting Guid.Empty (00000000-0000-0000-0000-000000000000).
Here notice the Umlet characters in 2nd request for comment field, it is some German characters (junk characters).
So, does junk characters affect the GUID value ?
But, also notice the Value of "RecordIdentifier" value in both request. It is not problem with "RecordIdentifier".
So where is the thing going wrong ?
I have below Entity for Request and parsing.
public class Measurement
{
public string Comment { get; set; }
public Guid RecordIdentifier { get; set; }
}
public class MeasurentEntityMain
{
public List<Measurement> measurement { get; set; }
public Guid FinalIdentifier { get; set; }
public string Source { get; set; }
public string Destination { get; set; }
}
Above both request i have captured from fiddler. and at API side i have tested it with debugging.
So, why this Guid field set to empty field.
I am using JSON serialization and deserialization.
I found the solution of the above said problem.
Actually i was checking Guid value at Controller side. And was getting Empty value.
I have created a HTTPhandler at my API side. This handler handles every request at routing time and then request is forwarded to respective APIController.
I have noticed at Handler side that for the Request with some Umlaut Characters, Some part of Requested data get truncated.
In Real Guid Field is of 32 Alphanumeric value and 4 dashes. But I was getting around 29 characters in Guid Value as it was last parameter in Request data some part was truncated.
When googled more i found that Umlaut characters with Length function returns length = 2.
So, For 3 Umlaut characters, 3 characters in Request data was getting truncated as i was using UTF8ENCODING and then Converting it To Byte data with Length of original string.
For more detail of this issue visit :
iOS HttpRequest with umlaut has incorrect length
Thanks a lot SO.
I'm trying to deserialize the following:
{"ts":"2012-04-22 04:14:50,669", "msg":"Hello"}
into
public class LogEntry
{
public DateTime Ts { get; set; }
public string Msg { get; set; }
}
using
var logEntry = JsonConvert.DeserializeObject<LogEntry>(line);
But get a JsonSerializationException saying "{"Error converting value \"2012-04-22 04:14:28,478\" to type 'System.DateTime'. Line 1, position 31."}. I cannot change the log format.
I think I might need to parse the date string myself using a Converter. However, I cannot find any examples of JsonConverter that seem relevant. Specifically how to read the value from the reader in the ReadJson method.
Are there any simple examples that I should look at? Or am I going about this the wrong way?
The format on your DateTime string uses a comma for the decimal separator (,478). You may be able to initialise a JsonSerializerSettings object (documented here) with an appropriate Culture, and then deserialise using DeserializeObject<T>(value, settings) (documented here). This would deserialise using the culture you specify rather than the default InvariantCulture.
I suspect the issue is because the value you are getting is using a comma as the decimal separator which suggests it was created in a locale that uses commas (e.g. a lot of European languages other than English). You could try changing your locale to match so that the parsing would work?
Motive : I have a decimal property in a class which I wish to validate so that it adheres to regex "^\d{1,7}.\d{2,7}$"
So i have applied the Regex validator attribute to the property
[RegexValidator(#"^\d{1,7}\.\d{2,7}$"...)]
public Decimal MyDecimalProperty { get; set; }
Then, via propertyproxyvalidator on my asp.net page i have tied a textbox validation to this property type.
<cc1:PropertyProxyValidator ID="MyValidator" runat="server" ControlToValidate="MyTextBox"
PropertyName="MyDecimalProperty" SourceTypeName="Myclass, Mydll"></cc1:PropertyProxyValidator>
At runtime i get this error when validation gets performed:
"Value to validate is not of the
expected type: expected System.String
but got System.Decimal instead."
Any idea how to get around this issue, or an alternate to achieve my motive ?
Regular expressions are built to work on strings, not numeric types. Perhaps you need something like this instead:
public Decimal MyDecimalProperty { get; set; }
[RegexValidator(#"^\d{1,7}\.\d{2,7}$")]
public string MyDecimalPropertyString
{
get
{
return this.MyDecimalProperty.ToString();
}
}
Also, update the PropertyName attribute of the PropertyProxyValidator.