Posting date (dd/mm/yyyy) and float (comma) values to aspnet WebApi - json

The Problem
When I post jSon data to webapi, using pt-br formats (dd/mm/yyyy for date and comma decimal separator for float), the values are deserialized as en-us formats resulting in error.
i.e.
» date: posting 23/01/2013 becames 01/01/0001
» float: posting 1,4 becames 0.0
The Help Request
Can anybody help me to define "the ultimate" solution to post data to web api using other cultures than en-US.
I've read a few discussions but none of them presents the complete solution, or even a working solution.
Considering the following
Model:
public class Person
{
public Datetime BirthDate { get; set; }
public double Weight { get; set; }
}
ApiController Method
public HttpResponseMessage Create(Person person)
{
// ...
}
AjaxCall
$.ajax({
type: 'POST',
url: sl.baseUri + "/create",
data: "Weight=87%2C7&BirthDate=17%2F07%2F1981",
success: null,
dataType: "json",
})
** I already added the following globalization settings to the web.config
<globalization requestEncoding="utf-8" responseEncoding="utf-8" culture="pt-BR" uiCulture="pt-BR"/>

You could try posting it as a JSON object rather than a plain string:
{"BirthDate": "17/07/1981", "Weight": "87,7"}
However, you would need to tell Json.Net what date format to expect:
http://james.newtonking.com/archive/2009/02/20/good-date-times-with-json-net.aspx

To solve this issue, I created a custom binding for dates.
ko.bindingHandlers.date = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
ko.utils.registerEventHandler(element, 'change', function () {
var value = valueAccessor();
if (element.value !== null && element.value !== undefined && element.value.length > 0) {
value(element.value);
}
else {
value('');
}
});
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
var output = '';
if (valueUnwrapped !== null && valueUnwrapped !== undefined && valueUnwrapped.length > 0) {
output = moment(valueUnwrapped).format('YYYY-MM-DD');
}
if ($(element).is('input') === true) {
$(element).val(output);
} else {
$(element).text(output);
}
}
};
This binding keeps the date in the following format: 2014-11-05T00:00:00-02:00
It is recommended that you use a input type=date in your html.
Also, you'll need to include the moment.js library to your project.

Related

Not getting the LINQ join query result in Ajax success method from Json Result using MVC however the result is shown correctly

I am trying to pass LINQ join query result(joining three tables ) from the controller to Ajax success function from Json Result but I am not getting any value means success function did not run and it executes error function . the query generated the correct result and also when I placed the breakpoint on return Json(query) or return new JsonResult{ Data = query, JsonRequestBehavior = JsonRequestBehavior.AllowGet };, the query variable contains the data . the problem is that the generated query result is not passed from the controller to the ajax function. I have tried other possible solutions but did not get any success.
Note : I have created model class to store the join query result.
any guidance regarding this will highly be appreciated
Thanks in advance.
here my controller code
[HttpPost]
public JsonResult getscore(int val)
{
Debug.WriteLine("checking {0}", val);
var g = val;
List<Participant_info> p_details = context.Participant_info.ToList();
List<Participant_enrolled> e_details = context.Participant_enrolled.ToList();
List<Contest_marking> mark = context.Contest_marking.ToList();
var query = (from p in p_details
join e in e_details on p.stud_id equals e.stud_id
join m in mark on e.E_id equals m.E_id
select new ScoreViewModel
{
partVm = p,
enrollVm = e,
markVm = m
}).ToList();
foreach (var u in query)
{
Debug.WriteLine("name {0} mark{1} Contest_id {2} ", u.partVm.stud_name, u.markVm.C1st_marks, u.enrollVm.Contest_id);
}
return Json(query, JsonRequestBehavior.AllowGet);
//return new JsonResult { Data = query, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
Model class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace CEN_CONTEST_MGT_SYSTEM.Models
{
public class ScoreViewModel
{
public Participant_info partVm { get; set; }
public Participant_enrolled enrollVm { get; set; }
public Contest_marking markVm { get; set; }
}
}
View code
#model IEnumerable<CEN_CONTEST_MGT_SYSTEM.Models.ScoreViewModel>
#{
ViewBag.Title = "score";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>score</h2>
#Html.DropDownList("Trial", "--- Tous ---")
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
<script type="text/javascript">
$("#Trial").change(function () {
val = $("#Trial").val();
alert("fff" + val);
//var data = JSON.stringify({
// 'val': val
//});
$.ajax({
type: "POST",
url: "/judge_dashboard/getscore",
data: JSON.stringify({'val': val}),
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
processData: false,
cache: false,
success: function (data) {
alert("hello");
},
error: function () {
alert("error");
}
})
})
</script>
try to change the action
public ActionResult<List<ScoreViewModel>> getscore(int val)
{
... your code
return Ok(query);
}
When using this:
select new ScoreViewModel
{
partVm = p,
enrollVm = e,
markVm = m
}
Likely what's happening is the serialization process is also processing all of your child objects, and may be running into a problem with that. Is there any error that you are receiving? I have a feeling the serialization process might be complicating it.
To test that, try returning all the properties you need directly such as:
return Json(new {
x = vm.partVm.X,
y = vm.enrollVm.Y
}, JsonRequestBehavior.AllowGet);

Preferred way to serialize/deserialize js-joda LocalDate?

We are using js-joda LocalDate to represent various dates in our model and are storing those dates in sessionStorage. Is there a generalized preferred way of storing those dates so that they can serialize/deserialize without adding special code to each object that contains them?
We have been using the standard JSON.stringify / JSON.parse to do this, but since LocalDate converts to an ISO string when stringified, we lose its LocalDate type when we parse it back.
As demonstrated here
Here's the summary:
const myObj = { a: "thing", d: LocalDate.parse('2019-01-20') };
const stringified = JSON.stringify(myObj);
const parsed = JSON.parse(stringified);
// this fails because d is no longer a LocalDate
console.log(parsed.d.year());
Our workaround now is that we have custom deserializers for any class that contains a LocalDate, but it seems a little kludgy.
Seeking a cleaner solution for this. Perhaps we could make a generalized serializer for LocalDate that outputs the same thing as the %o modifier in console.log?
mydate -> serialize -> "LocalDate { _year: 2019, _month: 1, _day: 20}"
Before we do that, I'm looking to see if this has already been done cleanly or if I'm just missing something obvious.
Answering my own question.
I'm surprised it hasn't come up, but the solution is right there in the definitions of JSON.stringify and JSON.parse.
This post pointed me to the solution when I needed to do the same thing with a Map.
JSON.parse(text[, reviver])
JSON.stringify(value[, replacer[, space]])
I needed to add replacers and revivers to do the custom serialization:
function myReviver(key: string, value: any) {
if (value === undefined) return undefined;
if (value === null) return null;
if (typeof value === 'object') {
switch (value.dataType) {
case 'LocalDate':
return LocalDate.parse(value.value);
case 'LocalTime':
return LocalTime.parse(value.value);
case 'LocalDateTime':
return LocalDateTime.parse(value.value);
case 'Period':
return Period.parse(value.value);
}
}
return value;
}
function myReplacer(key, value) {
const originalObject = this[key];
if (originalObject instanceof LocalDate) {
return {
dataType: 'LocalDate',
value: originalObject.toJSON()
};
} else if (originalObject instanceof LocalTime) {
return {
dataType: 'LocalTime',
value: originalObject.toJSON()
};
} else if (originalObject instanceof LocalDateTime) {
return {
dataType: 'LocalDateTime',
value: originalObject.toJSON()
};
} else if (originalObject instanceof Period) {
return {
dataType: 'Period',
value: originalObject.toJSON()
};
} else {
return value;
}
}
Whenever I call stringify or parse, I add the above functions as their replacer/revivers.
JSON.stringify(mystuff, myReplacer);
JSON.parse(mystuff, myReviver);

Angular automatically resolve strings as dates

I have a bunch of entities I've declared:
export class Meeting implements IHasId {
id = 0;
locationId = 0;
meetTime = new Date();
isFinalized = false;
imageId: number = null;
description = '';
name = '';
}
I have a generic crud service which handles resolving these to its original type
export class ApiResourceBaseService<T extends IHasId> {
get(id: number): Observable<T> {
return this.http.get<T>(`${this.apiUrl}/${this.route}/${id}`);
}
}
Typescript Generics are only superficial, so when I call get<T> typescript assumes my json is correct. However, My date objects are not resolved properly, they are resolved as string.
I have several entities, It would be annoying to create custom constructors/adapters to parse the dates.
does anyone have a better idea for automatically resolve dates?
I've created an interceptor to transform the data, In the future I'll probably just have auto generate my models and api resources from the api documentation and avoid this but for now I'm just using this hack:
export class ModelBinderInterceptor implements HttpInterceptor {
// regex of ISO 8601 Date.
DATE_TIME_TIMEZONE_REGEXP =
/^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/;
constructor() {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(tap((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
event = event.clone({body: this.modifyBody(event.body)});
}
return event;
}));
}
private modifyBody(body: any) {
return this.deserializeDates(body);
}
private deserializeDates(obj) {
if ((!(obj instanceof Object)) || (isString(obj))) {
return obj;
}
for (const key of Object.keys(obj)) {
const value = obj[key];
let date;
if (isString(value) && (this.DATE_TIME_TIMEZONE_REGEXP.test(value))) {
date = new Date(value);
// the parsing above may fail, in which case we use isNaN to check if the date is valid
if (isNaN(date.getTime())) {
return;
}
obj[key] = date;
}
this.deserializeDates(value);
}
return obj;
}
}

JSON Response IBM BPM

In our environment we have to prepare the response call with a JSON format (tw.local.jsonResponse). I'm new to JSON, not sure how to parse the date with the following JSON format in IBM BPM. It could be a great help if anyone guide/suggest (by using the following data).
Success Response
Code: 200
Content:
{
“status” : “success”
“data” : {
“change_number” : [string],
“instance” : [string],
“customer” : [string],
“tasks” : [
{ “task_number” : [string],
“description” : [string],
“schedule_start” : [datetime],
“schedule_end” : [datetime]
},
{ /* another task */ }
]
}
}
I have experienced similar problem with json and dates in IBM BPM.
In your solution, you can get the external JavaScript file json.js.
You can use the following function to return your JSON string:
BPMJSON.convertTWToJSON(tw.local.MyObject, false)
The first thing you need to do is make BO with require Datatype with the same name of BO.
Then use the following code to convert twObject to JSON:-
function createJson(twObject){
var jsonString="";
if(typeof twObject =='object' && twObject!=null){
if(twObject.listLength>0){
jsonString+="[";
for (var j=0; j<twObject.listLength; j++){
if(typeof twObject[j]!='string')
jsonString+="{";
for (var property in twObject[j].propertyNames){
var name = twObject[j].propertyNames[property];
if(typeof twObject[j][name]=='object'){
if(Object.prototype.toString.call(twObject[j][name]).indexOf("TWDate")!="-1"){
jsonString+="\""+name+"\":\""+twObject[j][name].format("yyyy-MM-dd'T'HH:mm:ss'Z'")+"\",";
}else{
jsonString+="\""+name+"\":"+createJson(twObject[j][name]);
}
}
else{
jsonString+="\""+name+"\":\""+twObject[j][name]+"\",";
}
if(twObject[j].listLength>0)
{
for (var k=0;k<twObject[j].listLength;k++){
jsonString+="\""+ twObject[j][k]+"\",";
}
}
}
if(typeof twObject[j] == 'string'){
jsonString+="\""+twObject[j]+"\"";
}
if(typeof twObject[j]!='string')
jsonString+="}";
if(j!=twObject.listLength-1){
jsonString+=",";
}
} jsonString+="],";
}else{
try{
if(twObject.propertyNames.length>0){
jsonString+="{";
for(var property in twObject.propertyNames){
var name = twObject.propertyNames[property];
if(typeof twObject[name]=='object'){
if(Object.prototype.toString.call(twObject[name]).indexOf("TWDate")!="-1"){
jsonString+="\""+name+"\":\""+twObject[name].format("yyyy-MM-dd'T'HH:mm:ss'Z'")+"\",";
}else{
jsonString+="\""+name+"\":"+createJson(twObject[name]);
}
}else{
jsonString+="\""+name+"\":\""+twObject[name]+"\",";
}
}
jsonString+="},"; }
else{
return "{},";
}}catch(e){
return "{},";
}
}
}
else if(typeof twObject =='object' && twObject==null){
return "{},";
}
return jsonString;
}
Source Code:http://www.ibpmcoding.com.
This is what worked in BPM 8.6 for a Rest Token:
tw.local.authToken = JSON.parse(tw.system.invokeREST(request).content).access_token;
Explained part by part:
tw.system.invokeREST(request)
Invoke the REST client to make a call.
tw.system.invokeREST(request).content
Contains the response as a jsonstring.
JSON.parse(tw.system.invokeREST(request).content).access_token
Parses it back to a json object and extract the attribute access_token as a string.
Humm.. I see why you have issue. Let me make it clear.
JSON Dates are not dates – they are Strings!!
So there is no fix format of date within JSON but we are lucky in case of IBM BPM.
String representation of date are in format of UTC time (indicated by the Z) in case of IBM BPM, for example
"2020-09-24T18:04:41.306Z"
You can convert this date string to JS Date on any browser using any date function for example
new Date("2020-09-24T18:04:41.306Z")
On server side JS you can use the same trick, converting sting date to JS date.

Format JSON string before displaying it in MVC? (with datatables)

Got a nice JSON problem over here;
I don't know how to go about formatting date, timespan, decimals etc before sending it to the view in MVC. I'm using the datatables jQuery plugin, and my 'DataHandler' method returns a JSON object as source for the datatable.
When I was processing the data and filtering client-side it was pretty straightforward, but now I'm processing the data on the server-side.
Controller:
public JsonResult DataHandler(DTParameters param)
{
try
{
var dtsource = new List<spRegistrations_Result>();
using (entities dc = new entities())
{
dtsource = dc.spRegistrations().ToList();
}
List<String> columnSearch = new List<string>();
foreach (var col in param.Columns)
{
columnSearch.Add(col.Search.Value);
}
List<spRegistrations_Result> data = new ResultSet().GetResult(param.Search.Value, param.SortOrder, param.Start, param.Length, dtsource, columnSearch);
int count = new ResultSet().Count(param.Search.Value, dtsource, columnSearch);
DTResult<spRegistrations_Result> result = new DTResult<spRegistrations_Result>
{
draw = param.Draw,
data = data,
recordsFiltered = count,
recordsTotal = count
};
return Json(result);
}
catch (Exception ex)
{
return Json(new { error = ex.Message });
}
}
Table initialization:
var table = $('#myTable').DataTable({
responsive: true,
"serverSide": true,
"ajax": {
"type": "POST",
"url": '/Table/DataHandler',
"contentType": 'application/json; charset=utf-8',
'data': function (data) { return data = JSON.stringify(data); }
},
"drawCallback": function(settings){
$('.card').hide();
},
"paging": true,
"deferRender": true,
"columns": [
{ "data": "RegId" },
{ "data": "PresenceDate" }, etc...
Model:
public int RegId { get; set; }
public System.TimeSpan StartTime { get; set; }
public System.TimeSpan EndTime { get; set; }
public System.DateTime PresenceDate { get; set; }
This is how it looks when the table is displayed
As you can see, the date is not very nicely formatted, and is the reason that I want to format the data before displaying it. Same goes for a couple of TimeSpan objects etc that I eventually want to show in the table.
I'm still pretty new to ajax, and don't know how to go about this the easiest way. Thanks for any input !
You could use the columns.render property to define the content of the table cell, using a custom js function to format the date. Something like:
...
"render": function ( data, type, full, meta ) {
var date = new Date(parseInt(data.substr(6), 0));
return ISODateString(date);
}
The function to format the date dd/mmm/yyyy:
function ISODateString(d) {
function pad(n) { return n < 10 ? '0' + n : n }
return pad(d.getDate()) + '/' + pad(d.getMonth() + 1) + '/' + d.getFullYear();
}