use other instead of #Html.DisplayFor in asp.net mvc 3 razor view - asp.net-mvc-3

I am novice to the asp.net mvc3. It's really confusing and difficult to modify single code due to convention used in asp.net mvc3. I was trying to display only Date for BirthDate in the format 5 Sep 1999 instead which shows Date and Time.It's fine in Edit.cshtml, datepicker is used to pick the date and value is saved in database of only date. But, I have BirthDate column of Data type of Date not the DateTime and when using #Html.DisplayFor(model => model.BirthDate); in Details.cshtml shows both date and time. While Searching in google I have found and implement following code for displaying date in desire format:
#Model.BirthDate.ToString("dd MMM YYYY");
and
#Html.DisplayFor(model => model.BirthDate.ToString("dd MMM YYYY"));
It gives error no overload method takes 1 argument. Further I could use like:
[DisplayFormat(DataFormatString = "{0:dd MMM yyyy}")]
pubilc DateTime BirthDate { get; set }
Since, I have used model first approach for Entity Framework. Where Should I implement above DisplayFormat property or what may be razor syntax to display date in right way in Details.csthml in my scenario

ok, I know I'm replying to a question posted 8 month before but my only intention is, this might be useful to others refering this question in future.
I'm also novoice to MVC and I also faced a similar problem where I need to display only the date and not the time and following worked for me.
Instead of #Html.DisplayFor(). Use <span>
So, for the case mentioned in question it would be like this:
<span>#String.Format("{0:D}", model.BirthDate)</span>
Output: Sunday, September 05, 1999
No, need to add extra class/file for formating.

The third approach is the best way according to me cos
your presentation model is dealing with all the aspects of UI and your view doesnt have unnecessary and redundant formatting code especially if you reuse the property.
enables unit testing
Consistent across different pages if you reuse the model.
You could also write an helper method that formats the date and use this consistently across all your presentation/view models.
public string FormattedDate(this DateTime dateTime)
{
return dateTime.ToString("dd MMM YYYY");
}

I like using a kind of decorator pattern to handle this kind of thing. Let's say your model class is called MyModel. Then define a wrapper class like this:
public class MyModelDecorator
{
public MyModel BaseItem { get; set; }
[DisplayFormat(DataFormatString = "{0:dd MMM yyyy}")]
public DateTime BirthDate { get; set; }
public MyModelDecorator(MyModel baseItem)
{
BaseItem = baseItem;
}
}
Then in your Views, you can refer to either the base model properties, or to the decorated properties.
#Html.DisplayFor(m => m.BirthDate)
#Html.DisplayFor(m => m.BaseItem.SomeOtherProperty)
If there's a better solution than this one, then I'd really like to hear it....

For any ASPX user sumbad answer helped but this is how you do it:
<%=Html.Enconde(String.Format("{0:D}", item.yourDate))%>
Hope this helps someone.

Related

How to format date in partial view MVC

I am currently developing asp.net core(Framework 3.1) application. I am getting date from database and storing it in string(tried using DateTime but didn't work). Here's my code in model:
public string TranDate { get; set; }
salesList.Add(new SalesData()
{
TranDate = dt.Rows[i]["TRANDATE"].ToString(),
});
It displays date in "2020/06/06 00:00:00" format.
In partial view:
<td>
#Html.DisplayFor(modelItem => item.TranDate)
</td>
Now I want to display date in "dd/MM/yyyy" format like "06/06/2020" in my partial view. I have tried many ways like display templates, editor templates, String.Format but nothing works. Please help!
Please try something like the following;
string formattedDate = DateTime.Now.ToShortDateString(); //set a default date
if (DateTime.TryParse(TranDate, out DateTime usersDate))
{
formattedDate = usersDate.ToShortDateString();
}
TranDate = formattedDate;
Some of this may be too much, but the core premise is that using the DateTime.TryParse method ensures that the date being passed into it (your "TranDate" parameter) can even be converted to a date. I know it is coming from the database and likely a Date field itself, but we really should not trust that, to be sure.

ASP.NET MVC 4 avoid generation of data-val-date for datetime

how can I avoid the generation of the html attribute "data-val-date" for the element created from a Datetime property?
The model:
public class RegisterModel
{
[Required]
[Display(Name = "Date of birth")]
public DateTime? DateOfBirth { get; set; }
}
The view:
#Html.LabelFor(m => m.DateOfBirth)
#Html.EditorFor(m => m.DateOfBirth)
In fact, I'm creating a three drop down lists element for selecting the date of birth, which don't give a value in a date format.
Some solutions I've seen, consisted in a work around: removing the validation with a javascript.
The solution I envisage is to split the DateTime property into three long one for each value (day, month, year).
Ok, this took me an afternoon of work... apparently mvc4 decided that it was time to render a data-val-date="Message" on EVERY datetime property on the viewmodel. I've tried to modify this default behaviour but didn't succeed.
This solved my problems:
$.validator.addMethod('date',
function (value, element) {
return true; // since MVC4 data-val-date is put on EVERY vm date property. Default implementation does not allow for multiple cultures...
});
You can also try to write your own editor template named "DateTime.cshtml" in your shared EditorFor folder, but don't use TextBoxFor there, because that one is polluted as well.
data-val-date is used by the validation system to validate the date. If you remove it, client-side validation won't work.
If that's what you want, then just disable client-side validation.
Add this to your application start in your global.asax file and the form should fire.
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

Automatical bind of datetime fields in MVC3

I have a page with many date fields, which can be dynamically added on client side. I have a DatTime? property on editor template for this field:
[Display(Name = "Bar Admission Date")]
public DateTime? AdmissionDate { get; set; }
When I'm submitting a form I get a null data in AdmissionDate field because binder doesn't know the format of the field.
I have 2 ideas of how t oovercome this issue:
Make a string field in model and parse it on a server side. Simple and pretty quick.
Write a custom model binder for date fields. I don't like this solution because I don't know the keys for all fields that I will use.
Is there better solution? I searched how can I overload TextboxFor method in order to pass it a culture, but I didn't find
Sounds like you should use an enumerable (IList/ICollection) of DateTime?. Phil Haacked has a good article on model binding to a list (even when the number of items is dynamic).
Updated
As for the formatting problem, I would look at how to set the culture for the project/model binder.

Passing a DateTime to controller via URL causing error in ASP .NET MVC 3 (culture)

My application is setted with pt-BR culture (Date is dd-mm-yyyy) in web.config:
<globalization enableClientBasedCulture="false" requestEncoding="utf-8" responseEncoding="utf-8" fileEncoding="iso-8859-15" responseHeaderEncoding="utf-8" resourceProviderFactoryType="string" enableBestFitResponseEncoding="true" culture="pt-BR" uiCulture="pt-BR" />
All DateTime created on my system is in right format, but I created a controller method like that:
public ActionResult Test(DateTime date)
{
}
Calling that method direct in the browser is passing null when the date is with portuguese-br format, like that:
mysite/Test/?date=19/01/2012 => date = null in my controller
mysite/Test/?date=01/01/2012 => date is fine, but in US format (mm-dd-yyyy)
How can I fix that, to accept my date format?
There's a gotcha with the default model binder that is not easy to know about but once you know it you no longer make the same mistake:
When you use a POST request, the default model binder uses your culture settings to parse the dates.
When you use a GET request, the default model binder uses CultureInfo.InvariantCulture to parse the dates and ignores your current culture settings.
Since you are using a GET request and passing the date as a query string parameter, you should format it using the invariant culture format when sending it in the url. The correct way to format your date as a query string parameter is yyyy-MM-dd.
You may take a look at the following blog post which gets into more details.
As someone who does a lot of work with US companies, I've had a lot of experience with date issues.
My best advice is to choose an unambiguous format when transmitting.
dd-MMM-yyyy
and
yyyy-MM-dd
Are safe bets, and will be successfully parsed by DateTime.Parse(obj).
If changing the date format is not an option, you should look at DateTime.ParseExact, which allows you to specify the exact format string you are after.
One approach would be to accept the date as a string and then manipulate it in the controller to the correct locale/culture.
Got the same problem using an #Html.Action(..) in a view. For this situation it can be solved by putting the DateTime in a model:
public class MyModel
{
public DateTime Value {get;set;}
}
and in the view:
#Html.Action("MyAction", new { myModel })
Note the new { } around the instance of MyModel, this way the DateTime is not converted to a string. This solution only works for Html.Action() and not for Html.ActionLink() or Url.Action() since MVC is doing a myModel.ToString() in the URL.

Validate DateTime with FluentValidator

This is my ViewModel class:
public class CreatePersonModel
{
public string Name { get; set; }
public DateTime DateBirth { get; set; }
public string Email { get; set; }
}
CreatePerson.cshtml
#model ViewModels.CreatePersonModel
#{
ViewBag.Title = "Create Person";
}
<h2>#ViewBag.Title</h2>
#using (Html.BeginForm())
{
<fieldset>
<legend>RegisterModel</legend>
#Html.EditorForModel()
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
CreatePersonValidator.cs
public class CreatePersonValidator : AbstractValidator<CreatePersonModel>
{
public CreatePersonValidator()
{
RuleFor(p => p.Name)
.NotEmpty().WithMessage("campo obrigatório")
.Length(5, 30).WithMessage("mínimo de {0} e máximo de {1} caractéres", 5, 30)
.Must((p, n) => n.Any(c => c == ' ')).WithMessage("deve conter nome e sobrenome");
RuleFor(p => p.DateBirth)
.NotEmpty().WithMessage("campo obrigatório")
.LessThan(p => DateTime.Now).WithMessage("a data deve estar no passado");
RuleFor(p => p.Email)
.NotEmpty().WithMessage("campo obrigatório")
.EmailAddress().WithMessage("email inválido")
.OnAnyFailure(p => p.Email = "");
}
}
When trying to create a person with an invalid date format:
Observations
As in my CreatePersonModel class the DateBirth property is a DateTime type, the asp.net MVC validation has done for me.
But I want to customize the error message using the FluentValidation.
I do not want to change the type of property for various reasons such as:
In a CreatePersonValidator.cs class, validation is to check if the date is in the past:
.LessThan (p => DateTime.Now)
Question
How to customize the error message without using DataAnnotations (using FluentValidator).
public CreatePersonValidator()
{
RuleFor(courseOffering => courseOffering.StartDate)
.Must(BeAValidDate).WithMessage("Start date is required");
//....
}
private bool BeAValidDate(DateTime date)
{
return !date.Equals(default(DateTime));
}
Have a look at the Fluent Validation documentation on GitHub:
https://github.com/JeremySkinner/FluentValidation/wiki
Try adding a RegEx Validator to ensure that the user's input (a string) can be parsed as a date correctly, prior to applying the Less Than Validator.
EDIT
Having run few test cases and looked at the source code for Fluent Validator I concede that the above approach won't work.
The standard error you get is added during the Model Binding phase, which happens before the fluent validation framework can access and check the model.
I assumed that the framework's authors had been clever and were injecting their validation code into the model binding phase. Looks like they aren't.
So the short answer is what you want to do does not appear to be possible.
Try this one
RuleFor(f =>
f.StartDate).Cascade(CascadeMode.StopOnFirstFailure).NotEmpty()
.Must(date => date != default(DateTime))
.WithMessage("Start date is required");
As Stewart mentioned, it's not possible to use FluentValidation alone to get in front of the model binding in this way. I'd offer up two ideas/suggestions though:
If you really can't change the ViewModel type from DateTime to string, you could always clear the model state yourself after model binding and then run the validator manually (I'm assuming you've wired FluentValidation to execute automatically after model binding).
In scenarios like this, I would change the property to a string, but then use AutoMapper to map that into a DateTime for whatever business object / domain model / service contract request I need it to ultimately become. That way, you get the most flexibility with parsing and conversion on both sides of the model binding.
I got this to work with DateTime? using really simple code. If you use the built-in validator NotNull(), then you get client side validation, which has 2 benefits.
You don't have to worry about all the model binding stuff people are talking about in other answers. It's client side! ;)
The date the user entered does not get "wiped out". An invalid date will get set by to null by the Post, Model binding to null, Validation error, responding with the view now with a null value in the date. This happens fast, so the user does not see what is wrong with the date.
This is the code I used:
RuleFor(x => x.CompleteDate).NotNull().WithMessage("Complete Date is not a valid date.");
I tested it with a date of 11/31/2021 (There is no day 31 in November) and it worked great with client-side validation.
Win!

Resources