I am using .NET Core 3.1 for an API that works like this:
[HttpPost]
public IActionResult Post([FromBody]ClassA classA)...
[HttpGet]
public IActionResult Get([FromQuery]ClassB classB)...
public ClassA {
[JsonProperty("date1")]
public DateTime date {get;set;}
}
public ClassB{
[JsonProperty("date2")]
public DateTime date {get;set;}
}
When I send a GET request I am able to get in the format I want (dd/MM/yyyy) because I have a custom ModelBinder that does the trick.
I thought it would work also for POST request but it does not. When I send a date in format (dd/MM/yyyy), it get as (MM/dd/yyyy) in controller.
I read somewhere that ModelBinder works only for x-www-form-urlencoded, but for my POST method I am sending a JSON.
I have tried changing DefaultThreadCurrentCulture and DefaultThreadCurrentUICulture but it did not work.
I have tried also using a custom JsonConverter but then I would have to add the JsonConverter to every date I have.
I am looking for a more sophisticated solution.
Try following :
public class ClassA
{
private DateTime _date
[JsonProperty("date1")]
public string date {
get{ return _date.ToString("MM/dd/yyyy");}
set{ _date = DateTime.ParseExact(value, "MM/dd/yyyy", System.Globalization.CultureInfo.InvariantCulture);}
}
}
Related
In my ASP.NET MVC 5 dwith EF 6 project, I have a database where datetime format is stored as string like "dd-MM-yyyy". User can change this format any time. User will use the given format in the date fields in the view. But when they will post that. Automatically it will bind as a DateTime for that property. I am statically handling it by the following code
[DataType(DataType.Time), DisplayFormat(DataFormatString = "{HH:mm}", ApplyFormatInEditMode = true)]
public DateTime? EndingTime { get; set; }
public string EndingTimeValue
{
get
{
return EndingTime.HasValue ? EndingTime.Value.ToString("HH:mm") : string.Empty;
}
set
{
EndingTime = DateTime.Parse(value);
}
}
but I know it's not a best way to do that. There may need a model binder or filter or any kind of custom attribute. I will be greatly helped if you give me a efficient solution with sample code. Thanks in advance.
NB: I am using razor view engine. and my solution consists of 7 projects. So there is no chance of using Session in model. Again I have a base repository class for using entity framework.
People usually store the datetime in the database as a datetime.
Then wherever you do a translation from datetime to string that datetime can be displayed in a format that depends on the culture of the viewer.
By doing this you can quickly make a page with datetime formats that will format the datetimes nicely wherever you are.
change the culture you pass to the toString and the format changes.
please see this MSDN page for more info about it.
edit: (see comments below)
anywhere on server:
string WhatYouWant = yourTime.ToCustomFormat()
and create an extension method for the datetime that gets the format out of the database and returns a string in the correct format.
public static class MyExtensions
{
public static string ToCustomFormat(this DateTime yourTime)
{
// Get the following var out of the database
String format = "MM/dd/yyyy hh:mm:sszzz";
// Converts the local DateTime to a string
// using the custom format string and display.
String result = yourTime.ToString(format);
return result;
}
}
This will allow you to call it anywhere anytime on your server. You can't access the method client side in javascript. I hope this helps.
(To be honest I'm a new developer too and still have a lot to learn ^^)
I have tried many options regarding this problem. Now what I am doing is created an action filter to catch all the DateTime and nullable DateTime Fields. Here I am providing the binder.
public class DateTimeBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
DateTime date;
var displayFormat = SmartSession.DateTimeFormat;
if (DateTime.TryParseExact(value.AttemptedValue, displayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
{
return date;
}
else
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName,"Invalid Format");
}
return base.BindModel(controllerContext, bindingContext);
}
}
in views the code I am formatting the date using same date format.
I have a intranet application using WebAPi and I'm having trouble binding the DateTime value to my model. I need the following format dd/MM/yyyy hh:mm:sss
XHR Post Data
Start=14/12/2015 02:44:09
End=14/12/2015 02:44:10
X-Requested-With=XMLHttpRequest
Config
<globalization uiCulture="en" culture="en-GB" />
Model Properties
[JsonConverter(typeof(CustomDateTimeConverter))]
public DateTime Start { get; set; }
[JsonConverter(typeof(CustomDateTimeConverter))]
public DateTime End { get; set; }
As you can see I've tried using a custom JSON converter on the properties.
public class CustomDateTimeConverter : IsoDateTimeConverter
{
public CustomDateTimeConverter()
{
base.DateTimeFormat = "dd/MM/yyyy hh:mm:ss";
}
}
The issue seems to be with the day or month being the other way round i.e MM/dd/yyyyhh:mm:ss.
Any ideas how I can get this binding in properly? Do I need a custom binder or JSON serializer?
I'm looking for a way to pass javascript dates to .NET web api controllers without installing another library on the client...
I'm expecting the javascript dates to deserialize to .NET DateTime.
var date = new Date();
post({currentDate: date.toISOString()});
Arrives at server as a DateTime.Min (indicating it failed to deserialize).
Here's an example of what is being sent over the wire, but the ApiController is not able to create a DateTime with the correct date...
Request:
{"Date":"2014-04-16T17:03:03.383Z"}
C#:
[Serializable]
public class MyObj
{
public DateTime Date { get; set; }
}
public class MyController : ApiController
{
public HttpResponseMessage Post(MyObj dd)
{
// dd's Date property equals DateTime.Min rather than the correct date...
return null;
}
}
}
Remove the [Serializable] attribute.
I think you should push the ticks from the client side. Then the server side will get a date from the ticks.
Example:
Javascipt:
var date = new Date();
post({ticks: date.getTime()});
.NET:
DateTime date = new DateTime(ticks);
Given this VM
public class ApplicationDTO : BaseDTO
{
public DateTime Date { get; set; }
public int JobId {get;set;}
public int Status {get;set;}
[Required]
public string Message { get; set; }
public string ExpertCode { get; set; }
}
I have a hidden field thusly
#Html.Hidden("Date", DateTime.Now)
Which fiddler shows me is sent to the server as I would expect (UK format, I'm in the UK!)
But on the controller the date shows as being the default min. date
Is it just the UK format? If so, what is my best way round it? Whilst currently I am setting it to the current date, potentially it could be set to any given date i.e.
#Html.HiddenFor(x => x.Date)
I am using AJAX to submit the form, if that makes a difference.
If it is a Get MVC uses culture invariant format (Basically US format) by default during model binding. So it doesn't accept UK date format. I believe the design reasons are that a querystring could be passed around so therefore it needs to be culture invariant (I wasn't 100% convinced by that logic).
This article covers a possible solution http://xhalent.wordpress.com/2011/05/14/localization-of-dates-in-asp-net-mvc/
We just make sure we never do a Get with a UK date format
This questions also covers the issue Globalization problem with DateTime and ASP.NET MVC 3 Model Binding
you should use Data Annotation for Formatting the date on your Model or View model
public class ApplicationDTO : BaseDTO
{
[DisplayFormat(DataFormatString="{0:dd/MM/yyyy}", ApplyFormatInEditMode=true)]
public DateTime Date { get; set; }
public int JobId {get;set;}
public int Status {get;set;}
[Required]
public string Message { get; set; }
public string ExpertCode { get; set; }
}
Apply the format according you.
As i have seen you are not providing any format to your property
I had a similar issue with dd.MM.yyyy format and had to set globalization element in web.config to appropriate culture and uiCulture attribute settings.
If you use #Html.Hidden (not the For helper) it won't be able to match the parameter in the request to the property in your model.
If you use #Html.HiddenFor(x=>x.Date, "28/2/2013") you will see the date populated appropriately.
Also you can verify the Request.Params collection. Put a break point in the Action. You'll see that one of the Params has your date.... JQuery does not affect this in any way.
I have this code:
#Html.TextBoxFor(m => Model.MyDateTime)
MyDateTime - is DateTime object.
It shows correct date and time inside textbox: 09/10/2010 05:19:56 PM
But when I try to click submit button it shows that it is incorrect value. I use jquery.validate.unobtrusive.js file for validation.
The gist of the solution I pointed to in my comment is that you can use a specialized model for the view which contains a string representation instead of the DateTime type, which allows you to easily validate the value with RegularExpressionAttribute. When you receive this model on the server (as posted from the client), simply convert it to a corresponding database model.
public class ViewModel
{
[Required]
[RegularExpression("\d{2}-\d{2}-\d{4}\s\d{2}:\d{2}:\d{2}")]
public string MyDateTime { get; set; }
public Model ToPoco()
{
return new Model {
MyDateTime = DateTime.Parse(this.MyDateTime, "MM-dd-yyyy H:mm:ss")
};
}
}
public class Model
{
DateTime MyDateTime { get; set; }
}
data annotation will work for you!
You could use dataannotaion for validate yor model field properly. Using such annatation you could manualy prvide format of date in your annotation passing string pattern to it. And in that case it will perefectly working with default mvc validation.