I am still getting my hands around MVC.
I have seen several similar questions, some custom code and various methods but I have not found something that works for me.
I have a search model that fills an HTML table with results inside of a partial view. I have this in my search results model:
public DateTime? BeginDateTime { get; set; }
Which is set to DateTime.Now in the controller. The user can specify that date and time to run a task with the search results' data on the model's POST call.
What I would like to do is validate that the date/time the user defined is at least 1 minute in the future. If this can be done as a client-side validation it will be better, but I am open to options as long as it works.
View:
Begin update: #Html.TextBoxFor(o => o.BeginDateTime, new { id="txtBegin" })
Thanks.
Create a new Attribute:
public class FutureDateAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
return value != null && (DateTime)value > DateTime.Now;
}
}
Now in your model set this attribute:
[FutureDate(ErrorMessage="Date should be in the future.")]
public DateTime Deadline { get; set; }
This is another good way to check that the date selected is from the future.
public class FutureDate : ValidationAttribute
{
public override bool IsValid(object value)
{
DateTime dateTime;
var isValid = DateTime.TryParseExact(
//Getting the value from the user.
Convert.ToString(value),
//We want the user to enter date in this format.
"d mmm yyyy",
//It checks if the culture is us-en
CultureInfo.CurrentCulture,
//Mosh has no idea what this does.
DateTimeStyles.None,
//Output parameter.
out dateTime);
return (isValid && dateTime > DateTime.Now);
}
}
Related
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);}
}
}
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 want to enter date time as string inside textbox. Actually there are two input fields
From time
To time
Both should be in format like 00:00 so I can enter
From time 00:00
To time 23:59
how can validate user input in asp.net mvc viewmodel using annotations so I can restrict users input from 00:00 as min value and 23:59 as max value?
You could create a custom attribute that you can decorate your property with.
namespace JensB.Tools.CustomAttributes
{
public class IsDateOk: ValidationAttribute
{
public override bool IsValid(object value)
{
if (value == null) return false;
if (value.GetType() != typeof(DateTime)) throw new InvalidOperationException("can only be used on DateTime properties.");
bool isValid = // do validation here
return isValid;
}
}
}
You can then decorate your property like this:
[IsDateOk(ErrorMessage="Dates must be .....")]
public property DateTime MyTime {get; set ;}
The nice part about doing this is that you basically dont need to code anything on the front end and just need to display the #Html.ValidationMessageFor( x=> ....) to make this work
Using regular expression, you can validate your model, and client side validation also work with this
like
[RegularExpression(#"^(0[1-9]|1[0-2]):[0-5][0-9] (am|pm|AM|PM)$", ErrorMessage = "Error message")]
public string FromTime {get;set;}
I have been having headaches with this function so I need a little help.
Describing a little bit there is one class which has this attribute:
public class SessionDate
{
...
[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime? searchValue2 { get; set; }
...
}
and there is a interface that has this function
public interface ISessionDate
{
IEnumerable<SessionDate> Search (string searchName, Datetime? searchDate)
}
which is declared in another class
public class SessionDateHelper
{
IEnumerable<SessionDate> Search (string searchName, Datetime? searchDate)
{
...
}
}
The problem is that the searchvalue2 is invoked in the View (inside the MVC 4 logic), which is set to dd/M/yyyy date format, but when I invoke the search in the Controller, somehow it goes rearranged to M/dd/yyyy, making the input change completely. For example I introduce 09/03/2014 (March 9th, 2014), but when it reaches the service it gets 03/09/2014 (Sept 03rd, 2014), how can I set that the function in the Interface and Helper automatically sets the date to {0:d}
The problem was that using GET method doesn't consider uiCulture, therefor it's set as default. To solve that you need a Model Binder, like this
Model Binder
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.