Sending out incorrect Date after app restart - c#

All DateTimes are stored like this in the database:
myDate.ToUniversalTime()
I can see the dates are stored correctly in the database i.e. in UTC format.
When I, from an Android application created in Xamarin, create an object using parameters the newly created object is returned to the application and the UTC time is sent back correctly in that object.
However, when I close the app the same object does now have another timestamp i.e. not the UTC time stamp.
App -> CreatePayment(int amount) -> ASP.NET MVC does it's magic and returns the newly created object for the app to save locally.
In an example object the returned date was 21/10/2016 21:53:01.
Now I restart the app and the returned date value is 22/10/2016 4:53:01.
How could this happen?
Do I need to set some setting so that ASP.NET MVC knows that the dates loaded from the database are in UTC format?
Can Application_BeginRequest cause these problems with my settings?
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies["Language"];
if (cookie != null && cookie.Value != null)
{
var abbrivation = cookie.Value;
Thread.CurrentThread.CurrentCulture = new CultureInfo(abbrivation);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(abbrivation);
}
else
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("es");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("es");
}
}

You can try to add <globalization> parameters in the web.config as shown below:
<system.web>
<globalization culture="es-MX" uiCulture="es" />
</system.web>
On the other hand, if the problem cannot be solved by applying this settings, you might have a look at MVC - UTC date to LocalTime.

Related

Get local datetime instead of server DateTime in server side code C#

I am using ASP MVC 4.5. I have view to input payment details. I use C# to get current time when user input payment. But after hosting it on server, i found a hot error. It gets another dateTime (may be my server's time) instead of my user's local time!
I want to get user's current time using C#. Should i use C# or javascript?
I think it is easy to get user's time using javascript. But i want to use C# for this. Can you help me?
My web API:
// POST api/PaymentApi
public HttpResponseMessage PostPayment(Payment payment)
{
if (ModelState.IsValid)
{
var mem= db.Members.Where(m => m.MemberID.Equals(payment.MemberID)).FirstOrDefault();
if (mem ==null)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
payment.Date = DateTime.Now;
db.Payments.Add(payment);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, payment);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = payment.PaymentID }));
return response;
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
I used payment.Date = DateTime.Now.ToLocalTime(); also but not worked!
Many of here answered to use javascript date. That's why i used it. But javascript sends a datetime and my WebApi makes it slightly different.
Javascript: Date:Tue Dec 27 2016 11:04:12 GMT+0600 (Local Standard Time)
C#: Date:{27/12/2016 05:04:12}
It's impossible to get client DateTime at server-side if client is not sending it by itself.
You'll need to get the local date time in javascript and pass it to the server. I recommend you to use ISO8601 format.
DateTime works with local host's clock, e.g. the server. Most payments systems save the dates as relative to UTC, to avoid client/server time differences.
payment.Date = DateTime.UtcNow;
There isn't any way to know the user Local time from the server. What you need to do is send the local time from the client to the server inside the request in UTC format.
Javascript(requires Jquery):
var UTC = new Date().getTime();

.NET MVC UK date format won't validate despite culture en-GB

I have a series of web forms in MVC. After some updates to the website recently the DateTime field validation is assuming dates are in US format and therefore days greater than 12 are failing validation, despite the fact that I've specifed the edit date format, the validation code and the culture as en-GB. Tried various browsers, all with language set as English (United Kingdom) and validation fails in Firefox, Chrome and Edge, and only works in IE. Tried various other suggestions found here including ModelBinding but nothing seems to work.
In the class:
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
In web.config:
<globalization culture="en-GB" uiCulture="en-GB" requestEncoding="utf-8" responseEncoding="utf-8" enableClientBasedCulture="false" />
In global.asax:
CultureInfo newCulture = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();
newCulture.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy";
newCulture.DateTimeFormat.DateSeparator = "/";
Thread.CurrentThread.CurrentCulture = newCulture;
Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo("en-GB");
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
In jquery.validate.js:
date: function (value, element) {
$.culture = Globalize.culture("en-GB");
var date = Globalize.parseDate(value, "dd/MM/yyyy", "en-GB");
return this.optional(element) ||
!/Invalid|NaN/.test(new Date(date).toString());
}
Any other suggestions?
I got this to work correctly with MVC 5. There were two changes needed:
To add a model binder, as the default binder does not take into account the CurrentUICulture. I did this with client validation removed just to test it. The reason why it doesn't by default is you might use dates in URL's, although I think if I did I would want to format the URL along yyyy-mm-dd lines.
To alter the client validation to take into account UK dates. I am not sure your jquery.validate.js code would work. I also had a bit of trouble with this as well, so in the end I installed nuget package jQuery.Validation.AdditionalMethods and made code that used that.
My own blog post at http://www.ablogaboutcoding.com/2017/08/12/mvc-uk-date-issues/ explains further.

How to test localized web application?

I work out of New Zealand developing a web application for some Romanian clients. The application should default to ro-RO when viewed by a client using a Romanian machine and en-GB for pretty much everyone else at this stage. Problem is ALL machines I have used to test this are defaulting to en-US. That is, machines on Windows Azure European data centers, local machines here in NZ and various machine in Romania which I access via RDP.
So i use this code in a controller to set language based on user defaults:
public static void OnBeginExecuteCore(Controller controller)
{
if (controller.RouteData.Values[Constants.ROUTE_PARAMNAME_LANG] != null &&
!string.IsNullOrWhiteSpace(controller.RouteData.Values[Constants.ROUTE_PARAMNAME_LANG].ToString()))
{
// set the culture from the route data (url)
var lang = controller.RouteData.Values[Constants.ROUTE_PARAMNAME_LANG].ToString();
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(lang);
}
else
{
// load the culture info from the cookie
var cookie = controller.HttpContext.Request.Cookies[Constants.COOKIE_NAME];
var langHeader = string.Empty;
if (cookie != null)
{
// set the culture by the cookie content
langHeader = cookie.Value;
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(langHeader);
}
else
{
// set the culture by the location if not specified
langHeader = controller.HttpContext.Request.UserLanguages[0];
if (langHeader.ToLower() == "en-us") langHeader = "en-GB";
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(langHeader);
}
// set the lang value into route data
controller.RouteData.Values[Constants.ROUTE_PARAMNAME_LANG] = langHeader;
}
// save the location into cookie
HttpCookie cultCookie;
cultCookie = new HttpCookie(Constants.COOKIE_NAME, Thread.CurrentThread.CurrentUICulture.Name)
{
Expires = DateTime.Now.AddYears(1)
};
controller.HttpContext.Response.SetCookie(cultCookie);
}
where
langHeader = controller.HttpContext.Request.UserLanguages[0];
is always en-US. There are in fact 3 entries in this collection however:
but ro is clearly not weighted correctly. This is the same across all machines in all locales.
Globalization in web config is set to auto:
<globalization requestEncoding="utf-8"
culture="auto"
uiCulture="auto"
And regional windows settings are as follows:
Browser:
How can I make this work?
ANSWER
As per Martins answer in comments. Problem was that I had this in apparently all settings the world over.
when what I really wanted was this in Chrome... will get to the other browsers soon.
Ensure that your browser of choice (Internet Explorer, Chrome, Firefox, Safari etc.) has been set up to specify ro as the first language in the User Languages sent over HTTP to the server.
Updating the Windows and/or browser's UI language won't necessarily cause a non-English language ISO code to be sent to the server, which means that you'd just get English returned.
In Firefox, for example, this setting can be found under Options->Content->Languages->Choose.

Servicestack POSTing DateTime issue

Weirdly, this works locally but when it's deployed to an Azure website it doesn't
The POST variables that fail on Azure are:
name=Test&venue=1&fromDate=26%2F06%2F14&toDate=01%2F07%2F14&eventType=1
If I POST the following it works:
name=Test&venue=1&eventType=1
So it must be something to do with the date format.
The data type on the request is a DateTime, if I set this to string it works - I can then call request.ConvertTo<Model> and everything is passed over as expected. I just don't want to set the fromDate and toDate to be strings on the request.
Does anyone know why this would fail?
That looks like a globalization issue. The Azure servers will be using en-US culture that expects the dates in mm/dd/yy format for parsing.
But you are using UK date format dd/mm/yy, so the culture is en-GB. Your development machine will be set to use the en-GB locale already, hence no problems when testing locally.
You can specify the culture in your web.config:
<configuration>
<system.web>
<globalization uiCulture="en-GB" culture="en-GB" />
</system.web>
</configuration>
Or you can do so at runtime in global.asax:
public void PreRequestHandlerExecute(object sender, EventArgs e)
{
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
}
Or you could modify how ServiceStack.Text deserializes DateTime, but I wouldn't recommend that approach. In the AppHost Configure method:
JsConfig<DateTime>.DeSerializeFn = date => DateTime.ParseExact(date, "dd/MM/yy", CultureInfo.InvariantCulture);
Hope that helps.

Does Decrypting a cookie convert it to local time?

I have my own asp.net cookie created like this:
var authTicket = new FormsAuthenticationTicket(
version,
userName,
DateTime.UtcNow,
DateTime.UtcNow.AddMinutes(30),
createPersistentCookie,
userData,
"/");
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
As you can see everything is in UTC time.
When I decrypt it:
var cookie = HttpContext.Current.Request.Cookies.Get(FormsAuthentication.FormsCookieName);
if (cookie != null)
{
var ticket = FormsAuthentication.Decrypt(cookie.Value);
return ticket.Expiration.Ticks;
}
else
{
return 0;
}
It returns local time. So, does it get converted automatically or is it something else? If so how can I get it back to UTC time?
From MSDN:
FormsAuthenticationTicket.Expiration Property
Gets the local date and time at which the forms-authentication ticket expires.
You can use the DateTime.ToUniversalTime method to convert a DateTime to UTC:
return ticket.Expiration.ToUniversalTime().Ticks;
As you've seen, once the FormsAuthenticationTicket has been serialized to a cookie and deserialized, the Expiration and Issue times will always be local.
The Remarks section in MSDN says "If the FormsAuthenticationTicket was created using a constructor that takes an expiration parameter, the Expiration property returns the value supplied to the expiration parameter.". Hence if you pass UTC, you will get back UTC until the ticket has been serialized/deserialized, after which it will be converted to local.
If you supply issueDate and expiration to the constructor, they should normally be in local time. However no attempt is made to convert them to local time - probably the reason for this is for backwards compatibility with .NET 1.x.
With .NET 1.x the DateTime struct did not have a "Kind" property, so there was no way to tell it the caller supplied UTC or local time - it was just assumed to be local.
Therefore I suggest you change your code to pass local time to the FormsAuthenticationTicket constructor, though it does expose you to this bug recorded on Microsoft Connect.

Categories