DateTime problems when moving to hosted environment - asp.net

I'm have the following code
Function SaveSession(ByVal model As ViewModelTrainingSession) As JsonResult
...
...
ses.Date = New DateTime(model.Date.Year, model.Date.Month, model.Date.Day, 0, 0, 0, 0, DateTimeKind.Local)
db.TrainingSessions.Add(ses)
db.SaveChanges()
When I run this code local (using debug) with let's say, 2014, 12, 24... The date that is saved in my database is 2014-12-24 00:00:00.000, which is what I want.
Now when I publish my code the server (shared hosting) the same code will end-up putting 2014-12-23 00:00:00.000 in the database.
I was using Azure database before and everything was working well. Now, I use the database on the new server I'm hosted on. The code did not change. But I get that date conversion now which baffles me. It is only when running from the published code that I get that date difference. When I run in debug mode local (but connecting to the de remotely) I have no problem
Any ideas?
Update
Here's what I do on the client side
bSoft.AjaxSaveSession = function (model) {
/* Convert it to JSON and send it to controller */
var json = ko.toJSON(model);
var targetURL = DataSrvOptimaxUrl + '/' + 'SaveSession';
bSoft.globals.vm.showLoadingWheel(true);
$.ajax({
url: targetURL,
type: "POST",
contentType: 'application/json; charset=utf-8',
Model contain various fields but two of them are named Date and DateStart, they are populated with javascript Date (I'm using XDate)
The model is sent to the server using the Ajax Call that you see.
On the other side (the server side), I have a ViewModel (ViewModelTrainingSession) defined with VB.NET. Again, that model contain a bunch of properties, two of them are Date and DateStart...
There is some magic performed by ASP.NET, the field are converted from JSON to VB based on the field names.
Function SaveSession(ByVal model As ViewModelTrainingSession) As JsonResult
If ModelState.IsValid Then
Try
'....
'Make sure date is save using time of 00.00.00:000
ses.StartTime = New DateTime(model.Date.Year, model.Date.Month, model.Date.Day, 0, 0, 0, 0, DateTimeKind.Local)
ses.Date = New DateTime(model.Date.Year, model.Date.Month, model.Date.Day, 0, 0, 0, 0, DateTimeKind.Local)
'...
db.TrainingSessions.Add(ses)
db.SaveChanges()
I think the dates get messed up in that conversion from JSON to VB. It is not the db which is the problem.
I think I'm going to try sending the date component instead of a date, I'll have a field called year, on called month, on called day, and put the component together on the server... This should prevent conversion and time zone issues.

You should switch from DateTimeKind.Local to DateTimeKind.Utc to avoid surprises like this one.
The hour difference stems from your server being in a different time zone than your emulator.
In general you should convert local times to Utc times before storing, and then convert the stored Utc times to local time immediately before displaying them. And get accustomed to seeing Utc times in your database's raw data. :-)

Related

Submitting time data to wikibase with `wbcreateclaim` results in "invald-snak" error

I am currently trying to populate a wikidata instance via POST requests. For this purpose I use the requests library in Python together with the MediaWiki API.
So far I managed to create claims with different datatypes (like String, Quantity, Wikidata items, Media ...). The general scheme I use is this (with different value strings for each datatype):
import requests
session = requests.Session()
# authenticate and obtain a csrf_token
parameters = {
'action': 'wbcreateclaim',
'format': 'json',
'entity': 'Q1234',
'snaktype': 'value',
'property': 'P12',
'value': '{"time": "+2022-02-19T00:00:00Z", "timezone": 0, "precision": 11, "calendarmodel": "http://www.wikidata.org/entity/Q1985727"}',
'token': csrf_token,
'bot': 1,
}
r = session.post(api_url, data=parameters)
print(r.json())
Every attempt to insert data of type time leads to an invalid-snak error (info: "invalid snak data.").
The following changes did not solve the problem:
submitting the value string as dictionary value (without the single quotes),
putting the numeric values into (double) quotes,
using a local item for the calendarmodel ("http://localhost:8181/entity/Q73"),
adding before and after keys in the dictionary,
omitting timezone, precision, calendarmodel and combinations thereof,
formatting the time string as 2022-02-19,
submitting the request with administrator rights (though the error message does not
suggest a problem with insufficient user rights).
Do you know, what I'm doing wrong here? What must the value field look like?
I am aware of the fact that special libraries or interfaces for exist for these tasks. But I do want to use the Wikidata API directly with the requests library in Python.
Thank you very much for your help!
Installed software versions:
MediaWiki: 1.36.3
PHP: 7.4.27
MariaDB 10.3.32-MariaDB-1:10.3.32+maria~focal
ICU 67.1
It works if the value string is generated from the dictionary via json.dumps().

Date becomes one (1) day behind after submitting model from Angular 6 to Web API

I am developing a web application using Angular 6 and PrimeNG controls for Frontend development and ASP.Net Web API and SQL Server for Backend development.
In one of my forms, there are two PrimeNG Calender controls to save From date and End date into the database. After the form is submitted all the form fields are collected to populate an object/model and passed this model to the Web API. The object/model is populated in Angular 6 using Typescript code. Below is my frontend model in Typescript code:
export class MyPackage {
public PackageId: number;
public PackageUid: number;
public PackageName: string;
public PackageDesc: string;
public ValidFrom: Date;
public ValidTill: Date;
public CreatedOn: Date;
}
Here is my object initialization process with Angular 6 and typescript:
let pakg = new MyPackage();
pakg.PackageName = this.packageAddForm.controls["packageName"].value;
pakg.PackageDesc = this.packageAddForm.controls["packageDesc"].value;
pakg.ValidFrom = this.packageAddForm.controls["dateFrom"].value;
pakg.ValidTill = this.packageAddForm.controls["dateEnd"].value;
Now the problem is when the model is passed to the Web API, From Date and End Date values become 1 day less which I don't know why. I have debugged my Angular 6 code and see that it passes the exact dates which I selected but when this model arrives in the Web API the dates become 1 day behind.
Can anyone describe, why this problem occurs and how to solve this problem?
To resolve this issue you need to convert date into "MM/DD/YYYY" format,
Follow the below steps in your .ts file in Angular Application,
1) Import DatePipe like
import { DatePipe } from '#angular/common';
2) Add the below in constructor
private datePipe: DatePipe
3) Convert your date using transform,
this.StartDate = this.datePipe.transform(this.todayDate, 'MM/dd/yyyy');
Note: The date variable should be any type.
angular client changes payload date format on HTTP Request. I solved my problem adding this to my module providers :
{ provide: MAT_DATE_LOCALE, useValue: 'en-GB' }, /* optional */
{ provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } },
and import them like this :
import {MAT_MOMENT_DATE_ADAPTER_OPTIONS} from '#angular/material-moment-adapter';
import { MAT_DATE_LOCALE } from "#angular/material/core";
and finally add this part to your modules and auto import
import: [MatDatepickerModule,MatMomentDateModule]
and your problem is solved too , hopefully :)
A likely culprit is the time zone offset between the client and the server.
When JavaScript dates are sent via the Angular HTTP Client, the data is converted to a JSON string using the JSON.stingify() method. This converts all dates into strings using ISO 8601 format, like this:
YYYY-MM-DDTHH:mm:ss.sssZ
One confusing aspect of this format is the purpose of the letter Z at the end, which stands for Zulu, or Zero UTC timezone offset.
When the date is converted to this string, the numerical time value is actually modified to reflect no timezone offset, instead of the timezone offset of the client. This is to normalize actual time in case the server is in a different timezone.
The important thing is to make sure the Web API is set up to interpret this string value representation of the time based on the zero UTC offset.
My time zone is GMT +6:00 (Bangladesh Time).
In same situation my problem solved by using moment format like this.
moment().format('YYYY-MM-DDThh:mm:ssZ');
Using Inside Angular:
import * as moment from 'moment';
currentDate : any = moment().format('YYYY-MM-DDThh:mm:ssZ');
ngOnInit() {
console.log(this.currentDate);
}
Output:
2022-03-22T12:31:47+06:00
To install moment.js via npm, use:
npm install moment --save
I had a string in format 'DD/MM/YYY', and I had to convert it to Date type before sending it to WebApi server.
So I converted it to UTC date using moment.js library.
Angular send with Date type request field.
WebApi (c#) got DateTyme type request field.
Day-reduced problem is solved :)
Here is my code for the string "26/01/2005":
moment.utc("26/01/2005", "DD/MM/YYYY").toDate()
To install moment.js via npm, use:
npm install moment --save
mor details about moment.js you can find in https://momentjs.com/
I know I am too late, but still it might be helpful for others, If you don't want to change the type of date variable to string, simply you can use below code. I had the same issue, i used below code and its working perfectly fine...
this.pakg.ValidFrom = new Date(Date.UTC(this.pakg.ValidFrom.getFullYear(), this.pakg.ValidFrom.getMonth(), this.pakg.ValidFrom.getDate()));
this.pakg.ValidTill = new Date(Date.UTC(this.pakg.ValidTill.getFullYear(), this.pakg.ValidTill.getMonth(), this.pakg.ValidTill.getDate()));
here you have to apply above code before hitting API's...

iisExpress local httpruntime.cache always null

strange problem here. On local development in asp.net webforms (4.5 / 4.7) I am finding httpruntime.Cache always null even when properly set. I attempted it on another iis express workstation and found the same behavior, even with a tester single page web page. That same page in production IIS 7.5 works and is storing and delivering from cache. The code specifically is below, but I have tried a tester storing a simple string in httpruntime.Cache.
var cache = System.Runtime.Caching.MemoryCache.Default;
var luCacheKey = "lu_" + dsName;
var ic = HttpRuntime.Cache.Get(luCacheKey) as ICollection;
if (ic == null) {
and from the tester
var item = HttpRuntime.Cache.Get("x");
if (item == null)
{
HttpContext.Current.Cache.Insert("x", "test" , null, DateTime.Now.AddHours(1), Cache.NoSlidingExpiration);
Response.Write("added to cache<br>");
}
else {
Response.Write("already in cache");
}
So, I am wondering if there is something perhaps in web.config that I could look at or is this expected IIS express behavior? Note, System.runtime.Caching does work properly.
var cache = System.Runtime.Caching.MemoryCache.Default;
var ic = cache[luCacheKey] as ICollection;
if (ic == null)
{
var filterCriteria = new BinaryOperator("LookupGroup", dsName, BinaryOperatorType.Equal);
var lookups = xpoSession.GetClassInfo(typeof(Lookups));
ic = xpoSession.GetObjects(lookups, filterCriteria, new SortingCollection(), 0, 0, false, false);
var cachePolicy = new System.Runtime.Caching.CacheItemPolicy() { AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(30) };
cache.Add(new System.Runtime.Caching.CacheItem(luCacheKey, ic), cachePolicy);
You incorrectly add your object to the cache.
Instead of DateTime.Now follow the docs and put DateTime.UtcNow. This resolves a common issue where your machine is in a "non-zero" time zone which prevents the inner logic of the cache to manage your expirations correctly.
From the docs
To avoid possible issues with local time such as changes from standard time to daylight saving time, use UtcNow rather than Now for this parameter value.
https://msdn.microsoft.com/en-us/library/4y13wyk9(v=vs.110).aspx
Adding more information as follow up on why the behavior may change between servers.
This change in behavior may be caused by having .NET 4.7 installed on the machine. The article linked below says that Microsoft will fix this in the next version of .NET and in the next hotfix.
Quoting parts of the Microsoft page:
Symptoms:
Assume that you have Microsoft .NET Framework 4.7 installed on a
computer. When you try to insert items into the Cache object by using
the Cache.Insert (string, object, CacheDependency, DateTime, TimeSpan)
Insert overload method, you may notice that the inserted Cache items
expire much earlier or later than the specified DateTime (expiration
time).
Cause:
The internal implementation of System.Web.Caching.Cache uses
Coordinated Universal Time (UTC) time-stamp for absolute expiration.
But this particular Cache.Insert (string, object, CacheDependecy,
DateTime, TimeSpan) Insert overload method does not make sure whether
the expiration time is converted to UTC. Therefore, expiration for
items that are inserted into the Cache object by using this overload
will occur earlier or later than expected, depending on the computer
time zone difference from Greenwich Mean Time (GMT).
Workaround:
The temporary workaround for this issue is to use either the Cache.Add method or a different Cache.Insert overload method.
Resolution:
This issue will be fixed in the next version of the .NET Framework, and will also be available in the next hotfix for the .NET Framework 4.7.
References:
https://support.microsoft.com/en-us/help/4035412/fix-expiration-time-issue-when-you-insert-items-by-using-the-cache-ins
http://vimvq1987.com/2017/08/episerver-caching-issue-net-4-7/

How to set local timezone in Sails.js or Express.js

When I create or update record on sails it write this at updateAt:
updatedAt: 2014-07-06T15:00:00.000Z
but I'm in GMT+2 hours (in this season) and update are performed at 16:00.
I have the same problem with all datetime fields declared in my models.
How can I set the right timezone on Sails (or eventually Express) ?
The way I handled the problem after hours of research :
Put
process.env.TZ = 'UTC'; //whatever timezone you want
in config/bootstrap.js
I solved the problem, you should setting the MySql options file to change timezone to UTC
in the config/connections.js
setting at this
devMysqlServer: {
adapter: 'sails-mysql',
host: '127.0.0.1',
user: 'root',
password: '***',
database: '**',
timezone: 'utc'
},
Trying to solve your problem by setting the timezone on your server is a bit short-sighted. What if you move? Or someone in a different country accesses your application? The important thing is that the timestamps in your database have a timezone encoded in them, so that you can translate to the correct time on the front end. That is, if you do:
new Date('2014-07-06T15:00:00.000Z')
in your browser console, you should see it display the correct date and time for wherever you are. Sails automatically encodes this timestamp for you with the default updatedAt and createdAt fields; just make sure you always use a timezone when saving any custom timestamps to the database, and you should be fine!
The best architecture planning here, IMO, is to continue using Sails.js isoDate formatting. When you're user's load your website/app the isoDate will be converted to their client/browser timezone which is usually set at the OS level.
Here's an example you can test this out with. Open a browser console and run new Date().toISOString() and look at the time it sets. It's going to be based of off the spec for isoDate 8601 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString).
Now, change your system time to a different time zone or simply change your hour on the time and save (you shouldn't have to reload if you're using chrome console). Run your command in the console again new Date().toISOString() and you'll get an adjusted time appropriate to the time you just changed.
If you'd like to continue on proving to yourself the time Sails.js is appropriate to use, use Moment.js on an isoDate that is stored in your database (created by waterline ORM) like so moment("2016-02-05T22:36:48.800Z").fromNow() and you'll notice the time is relative to your system time.
I've come to grips with not setting a timezone at the app level (I see why the sails authors did it that way), however I've been having a rough time performing a simple date match query. I'd assume that if you create a record using the default blueprint methods (this one containing an extra datetime field over the defaults), passing in a date, that you'd be able to pass in the same date in a get query and get the same record.
For example, let's say the datetime field is called "specialdate". If I create a new record through the api with "specialdate" equaling "06-09-2014" (ignoring time), I haven't been able to run a find query in which I can pass in "06-09-2014" and get that record back. Greater than queries work fine (if I do a find for a date greater than that). I'm sure it's a timezone offset thing, but haven't been able to come up with a solution.

ASP.NET session variable is wrong after multiple click event fast

I have an asp.net website to manage projects. I realized that when I click for the next project really fast and often it overrides all the next projects with the data of the first one. I call a method to save before to go for the next project. I use also a session variable for the id of the project.
EDIT:
It looks like the sever stacks the save method and the ids but keeps the values of the first project in the controls
Am I right?
this is the ajax that calls a server method to get the id and set it in an hidden field:
function NextClick() {
var tabvalue = $("#<%=TabsToFocus.ClientId%>").val();
$.ajax(
{
type: "POST",
url: "Projet.aspx/NextProj",
data: "{tab:'" + tabvalue + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(d) {
if (d.d != "False") {
$("#<%=hid_selProjetID.ClientID%>").val(d.d);
var btn = $("#<%=btnClickLstProjet.ClientID%>");
fillHidden();
btn.click();
}
}
});
}
And btn.click() calls this method on the server side to save
Private Sub Button1_ServerClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnClickLstProjet.ServerClick
If HttpContext.Current.Session.Item("isUser") IsNot Nothing AndAlso HttpContext.Current.Session.Item("isUser") = True Then
If HttpContext.Current.Session.Item("curProjetID") IsNot Nothing Then
btnSaveIndicateurs_Click()
btnSaveEnTete_Click()
btnSaveGen_Click()
btnSavePlanif_Click()
End If
End If
HttpContext.Current.Session.Item("curProjetID") = hid_selProjetID.Value
Response.Redirect("Projet.aspx")
End Sub
Thank you
The very first thing you should do is STOP using session.
Seriously, back away from the session object.
A proper use of session is long term, fairly unchanging data. Data that has to change on literally every post back etc belongs in the page itself.
Here is what's happening.
You click on a link to load up the project. The Session variable is being set with the current project id.
You then click on a link to get the next project,
Then quickly click on the link to get the one after that.
The server, meanwhile, is multithreaded. #3 basically interupted #2's execution.. and ran before #2. This means your session variable is jacked up.
Why would the 3rd request run before the 2nd? Well, you are executing a number of queries. It's likely that the queries for request 2 are taking slightly longer to exec than the ones for request 3.
Solution: Stop using Session.
Why: You cannot predict the order in which IIS is going to respond to requests. IIS is a parallel (not serial) engine and requests might very well happen out of the sequence you think they should.
Finally, the guy who said that session is locked by the first requestor wasn't entirely accurate. It is WRITE locked.. but that only occurs when the page starts writing to session. Reads are not locked.
So, when request 3 executes it is using the ID of request 1, or 2. Depending on which one is still active by the time it hits the write code.

Resources