I'm trying to apply a format in a DateTime attribute but it is not working. I have this:
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "dd/MM/yyyy", ApplyFormatInEditMode = true)]
public DateTime DataInscricao { get; set; }
I've tried to do it in many ways (changing the DataFormatString) but none of them are working. I'm also using datepicker for my Date fields.
I also tried to apply the format from jQuery:
$("#DataInscricao").datepicker( {dateFormat: 'dd-mm-yy'});
It almost works, the format is applied in the TextBox but when I try to Save the date format is lost. If I enter a date like 12/01/2013, it changes to 01/01/0001. In the GridView the format is different (mm-dd-yyyy) and the mask of the TextBox is working wrong.
I really don't know what to do to make it work. Is there someone who can help me with this issue?
Thanks!
UPDATE
This is the method in the Controller which returns the entity to edit.
public ActionResult Editar(int id)
{
var agendamento = _repository.GetSingle(a => a.Id == id);
return View("Criar", agendamento);
}
And this is the View:
#model PNCQ2013.Domain.Entities.AgendamentoManutencao
#{
ViewBag.Title = PNCQ2013.Domain.Resources.ItemPatrimonio.ItemPatrimonio.TitleAgendamento + " :: PNCQ - Programa Nacional de Controle de Qualidade";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="section">
#using (Ajax.BeginForm("Salvar", "ManutencaoPreventiva", null, new AjaxOptions { HttpMethod = "POST", LoadingElementId = "loading" }, new { #class = "formee", #id = "frmAgendamentoManutencao", enctype = "multipart/form-data" }))
{
#Html.HiddenFor(m => m.Id)
<div class="box">
<div class="title">
#PNCQ2013.Domain.Resources.ItemPatrimonio.ItemPatrimonio.TitleAgendamento
</div>
<div class="content nopadding">
<div class="grid-4-12">
#Html.LabelFor(m => m.ItemPatrimonioId)
#Html.DropDownListFor(m => m.ItemPatrimonioId, new SelectList(PNCQ2013.Web.Content.Helpers.Util.ListaItemPratrimonio().OrderBy(a => a.NumeroPatrimonio), "Id", "NumeroPatrimonio"), Resources.Geral.Selecione)
#Html.ValidationMessageFor(m => m.ItemPatrimonioId)
</div>
<div class="grid-4-12">
#Html.LabelFor(m => m.DataInscricao)
#Html.TextBoxFor(m => m.DataInscricao, new { #class = "datepicker" })
#Html.ValidationMessageFor(m => m.DataInscricao)
</div>
<div class="grid-4-12">
#Html.LabelFor(m => m.FrequenciaManutencaoId)
#Html.DropDownListFor(m => m.FrequenciaManutencaoId, PNCQ2013.Web.Content.Helpers.HtmlExtensions.ToSelectList(typeof(PNCQ2013.Domain.Enumerators.FrequenciaManutencao), ""), Resources.Geral.Selecione)
#Html.ValidationMessageFor(m => m.FrequenciaManutencaoId)
</div>
</div>
</div>
}
Try like this,
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime DataInscricao { get; set; }
Related
Not working. Date comes back from a database field. Shows as:
When it is not set from a database as there is no birth date, I get a little red dot top left. Shows as:
I don't want the time included. I have a data annotation display format but it does not seem to take affect.
My Model(not showing other fields) is:
using System;
using System.ComponentModel.DataAnnotations;
namespace GbngWebClient.Models
{
public class UserProfileForMaintViewModel
{
// Can be null.
[Required]
[Display(Name = "Birth Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM-dd-yyyy}", ApplyFormatInEditMode = true)]
[RegularExpression(#"(((0[1-9]|1[0-2])\/(0|1)[0-9]|2[0-9]|3[0-1])\/((19|20)\d\d))$", ErrorMessage = "Invalid date format.")]
public DateTime BirthDate { get; set; }
}
}
My view (not showing other fields) is:
#model GbngWebClient.Models.UserProfileForMaintViewModel
<h1 class="page-header">User Profile Maintenance</h1>
#{
ViewBag.Title = "UserProfileMaint";
Layout = "~/Views/Shared/_LayoutUser.cshtml";
}
#using (Html.BeginForm("UpdateUserProfile", "UserProfiler", FormMethod.Post))
{
<div style="margin-top:10px;"></div>
<div class="panel panel-default">
<div class="panel-heading">Your Profile</div>
<div class="panel-body">
<div class="row">
<div class="row">
<div class="col-md-3">
#Html.LabelFor(model => model.BirthDate, new { #class = "manadatory" })
#Html.TextBoxFor(model => model.BirthDate, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.BirthDate, "", new { #class = "text-danger" })
</div>
<div class="col-md-3"></div>
</div>
<div style="margin-top:10px;"></div>
<div class="row">
<div class="form-group">
<div class="col-md-offset-0 col-md-12">
#* Submit button. *#
<input type="submit" value="Save" class="btn btn-info" />
</div>
</div>
</div>
</div>
</div>
}
From my previous experience I found out that it is much easier to deal with a string than a DateTime variable. So I usually use it as a hack. You can have an extra text field in your ViewModel and format it from the controller for the view -
public ActionResult Custom2()
{
var profile = new Profile();
profile.DoB = DateTime.Now.Date;
profile.DoBText = profile.DoB.ToString("yyyy-MM-dd");
return View(profile);
}
Now the view can accept the text data without any problem
#model mvcDeploymentTest.Models.Profile
#{
ViewBag.Title = "Custom2";
}
<h2>Custom2</h2>
#using (Html.BeginForm("PostTest", "Home", FormMethod.Post))
{
#Html.TextBoxFor(model => model.DoBText, new { #class = "form-control", Type = "date" })
<input type="submit" value="Submit" />
}
And once posted, you can parse the changed text value to datetime again with any formatting you want
[HttpPost]
public void PostTest(Profile myProfile)
{
DateTime dateValue;
if (!string.IsNullOrEmpty(myProfile.DoBText))
{
DateTime.TryParseExact(myProfile.DoBText,"yyyy-MM-dd", CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out dateValue);
myProfile.DoB = dateValue;
}
return;
}
ApplyFormatInEditMode is only used/applied when using EditorFor - you have to use the overload for TextBoxFor which accepts a format string in order to get a formatted output in the rendered <input />.
#Html.TextBoxFor(model => model.BirthDate, "{0:d}", new { #class = "form-control" })
{0:d} will apply whatever short date format matches your app's culture settings. Replace that with a custom format string if you want something else.
If you want to use your browser's native date input (<input type="date" />), you'll need to use an ISO-8601 short date, which is YYYY-MM-DD. An example:
#Html.TextBoxFor(model => model.BirthDate, "{0:yyyy-MM-dd}", new { #class = "form-control", #type = "date" })
The default modelbinder knows how to transform that into a DateTime object, which you can then format into whatever else you wanted/needed.
I have two date fields that I want to make sure that the end date is greater than the start date. It seems to work but not always. When testing out with different dates it stops working. I am using foolproof. Here is the code
#using (Html.BeginForm("CreateMeeting", "Home", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h3>Book a new visit</h3>
<div>The information entered below will be sent to the visitors email address #Model.Info.Email</div>
<p> </p>
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.NewMeeting.Title, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.NewMeeting.Title, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.NewMeeting.StartTime, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.NewMeeting.StartTime, new { #class = "datetimepicker form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.NewMeeting.EndTime, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.NewMeeting.EndTime, new { #class = "datetimepicker form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
#Html.HiddenFor(m => m.NewMeeting.SubjectId)
#Html.HiddenFor(m => m.NewMeeting.FirstName)
#Html.HiddenFor(m => m.NewMeeting.LastName)
#Html.HiddenFor(m => m.NewMeeting.Email)
#Html.HiddenFor(m => m.NewMeeting.HostEmail)
#Html.HiddenFor(m => m.NewMeeting.HostMobile)
<input type="submit" class="btn btn-default" value="Send Invite" />
</div>
</div>
}
The model is declared
public class Meeting
{
[Key]
public int Id { get; set; }
[Required]
[Display(Name = "Reason for invitation")]
public string Title { get; set; }
[Required]
[Display(Name = "Start Time")]
[DataType(DataType.DateTime)]
public DateTime StartTime { get; set; }
[Required]
[Display(Name = "End Time")]
[DataType(DataType.DateTime)]
[GreaterThan("StartTime")]
public DateTime EndTime { get; set; }
public string HostEmail { get; set; }
public string HostMobile { get; set; }
public NotificationMethod HostNotificationMethod { get; set; }
public bool HostAlreadyNotified { get; set; }
}
Added the script as a bundle
bundles.Add(new ScriptBundle("~/bundles/foolproof").Include(
"~/Client Scripts/mvcfoolproof.unobtrusive.js"));
And into the _Layout.cshtml page
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/foolproof")
Any ideas whats going on. Seems like first time I pick a date where end date is less than start date, the validation works. However when I start playing around with different dates to break the system it stops working and the form is submitted with end date less than start date. I have even got it sometimes to a state where the end date is greater than the start date but the validation still fails as it thinks the start date is greater still.
See screenshot, after playing with the end and start dates I can get into states like this:
https://postimg.org/image/rki9qfmtz/
I am using the below Ajax form to select and post date ranges.
View Model:
public class ViewFormSubmissionsVM
{
public string FormName { get; set; }
public Guid FormId { get; set; }
[Display(Name="From:")]
public DateTime From { get; set; }
[Display(Name = "To:")]
public DateTime To { get; set; }
}
Razor/HTML:
#model ViewFormSubmissionsVM
#using (Ajax.BeginForm("ViewFormSubmissions", "Form", new AjaxOptions { HttpMethod = "POST", OnSuccess = "onGetSubmissionSuccess", OnFailure = "onGetSubmissionError" }, new { #class = "form-horizontal" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(x => x.FormId)
<div class="row col-md-12">
<div class="pull-right">
<label class="control-label col-md-3">#Html.DisplayNameFor(x => x.From)</label>
#Html.TextBoxFor(x => x.From, "{0:MM/dd/yyyy}", new { #class = "form-control col-md-3", #data_picker = "date-picker" })
<label class="col-md-3">#Html.DisplayNameFor(x => x.To)</label>
#Html.TextBoxFor(x => x.To, "{0:MM/dd/yyyy}", new { #class = "form-control col-md-3", #data_picker = "date-picker" })
<input type="submit" class="btn btn-primary" value="Search" />
</div>
</div>
}
JQuery Date picker:
$(document).ready(function () {
$('*[data-picker="date-picker"]').datepicker();
});
This issue is while submitting the form, the "From" and "To" Datetime properties, received the default date values instead of selected.
Am I missing anything important!! I have already used these codes in different forms, but never experienced this before.
Could any one help me to get out of this one.
Many Thanks.
First of all, I think you should call this overload:
using (Ajax.BeginForm("ViewFormSubmissions", "Form", null, new AjaxOptions{
HttpMethod = "POST",
OnSuccess = "onGetSubmissionSuccess",
OnFailure = "onGetSubmissionError"
},
new {#class = "form-horizontal" }))
with null as 3rd parameter.
Second, check your datetime format. You can find more info here: MVC DateTime binding with incorrect date format, ASP.NET MVC datetime culture issue when passing value back to controller or http://weblogs.asp.net/melvynharbour/mvc-modelbinder-and-localization.
I have code like this that I repeat through many MVC editing views. This example is the default way we display a checkbox, but similar repetition is found with other input types.
<div class="form-group">
#Html.LabelFor(model => model.IsLive, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-8 checkbox">
<div class="col-xs-1">
#Html.EditorFor(model => model.IsLive)
</div>
<div class="col-xs-10">
#Html.CheckboxLabelFor(model => model.IsLive)
</div>
</div>
<a class="infoonclick col-md-1" title="#Html.DisplayNameFor(model => model.IsLive)" data-content="#Html.DescriptionFor(model => model.IsLive)">
<span class="fa fa-info-circle"></span>
</a>
</div>
I am wondering what is the best way to DRY and standardise this?
I want to do something like #Html.DefaultCheckboxEditorFor(model => model.IsLive)
I tried creating a custom HtmlHelper, but this seemed to involve too many hard coded strings to be a good idea.
Rather I feel I should be using EditorTemplates for this, but I can't quite get the syntax right. The model for the view is a bool, but I need to get property specific stuff like the display name and descriptions.
#model bool
<div class="form-group">
#Html.LabelFor(model => model.IsLive, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-8 checkbox">
<div class="col-xs-1">
#Html.EditorFor(model => model.IsLive)
</div>
<div class="col-xs-10">
#Html.CheckboxLabelFor(model => model.IsLive)
</div>
</div>
<a class="infoonclick col-md-1" title="#Html.DisplayNameFor(model => model.IsLive)" data-content="#Html.DescriptionFor(model => model.IsLive)">
<span class="fa fa-info-circle"></span>
</a>
</div>
I have a project where most of my views look like:
(This also works with multi-level deep complex objects, but not with any type of collection, like IEnumerable, although it could be modified to do so)
<h3>Edit existing page</h3>
<div class="col-xs-12">
#using (Html.BeginForm("Edit", "Page", FormMethod.Post, new { role = "role" }))
{
#Html.EditorForModel()
<input type="submit" value="Save" class="btn btn-primary" />
}
</div>
I think that's pretty cool. So the model looks like:
public class PageEditViewModel
{
[Editable(false)]
[DisplayName("Page Id")]
public Guid Id { get; set; }
[Editable(false)]
[DisplayName("Url to resource (format: '/my-resource' or '/sub/resource)'")]
public string Url { get; set; }
[Required]
[MaxLength(50, ErrorMessage = "Maximum Length of 50 Exceeded.")]
[DisplayName("Title for page (must match Url ex: 'My Resource' or 'Sub Resource'")]
public string PageTitle { get; set; }
[MaxLength(int.MaxValue, ErrorMessage = "Content Exceeded Maximum Length")]
[DataType(DataType.MultilineText)]
public string Content { get; set; }
}
I have some editor templates:
\Views\Shared\EditorTemplates\multilinetext.cshtml
#model object
#{
var htmlAttributes = this.ViewData.ModelMetadata.GetHtmlAttributes();
}
<div class="form-group #Html.ErrorClassFor(m => m, "has-error")">
#Html.LabelFor(m => m, new { #class = "control-label" })
<div class="controls">
#Html.TextAreaFor(
m => m,
8, 8,
htmlAttributes)
#Html.ValidationMessageFor(m => m, null, new { #class = "help-block" })
</div>
</div>
And it all magically works with the a modified version of object.cshtml:
#model object
#using System.Text;
#using System.Data;
#{
ViewDataDictionary viewData = Html.ViewContext.ViewData;
TemplateInfo templateInfo = viewData.TemplateInfo;
ModelMetadata modelMetadata = viewData.ModelMetadata;
System.Text.StringBuilder builder = new StringBuilder();
string result;
// DDB #224751
if (templateInfo.TemplateDepth > 2)
{
result = modelMetadata.Model == null ? modelMetadata.NullDisplayText
: modelMetadata.SimpleDisplayText;
}
foreach (var prop in modelMetadata.Properties.Where(pm =>
pm.ShowForEdit
//&& pm.ModelType != typeof(System.Data.EntityState)
&& !templateInfo.Visited(pm)
)
.OrderBy(pm => pm.Order))
{
//Type modelType = Model.GetType();
Type modelType = modelMetadata.ModelType;
System.Reflection.PropertyInfo pi = modelType.GetProperty(prop.PropertyName);
System.ComponentModel.DataAnnotations.DisplayAttribute attribute = pi.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.DisplayAttribute), false).FirstOrDefault() as System.ComponentModel.DataAnnotations.DisplayAttribute;
if (attribute != null
&& !string.IsNullOrWhiteSpace(attribute.GetGroupName()))
{
//builder.Append(string.Format("<div>{0}</div>", attribute.GetGroupName()));
builder.Append(Html.Partial("Partial-GroupName", attribute.GetGroupName()));
}
builder.Append(Html.Editor(prop.PropertyName, prop.TemplateHint ?? prop.DataTypeName).ToHtmlString());
}
result = builder.ToString();
}
#Html.Raw(result)
Example output:
My EditFor templates are versions of MacawNL BootstrapEditorTemplates (which I have no affiliation with).
I have a strange problem, I have a model definied like this:
public class AddEventModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Nazwa wydarzenia")]
public string EventName { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Rodzaj")]
public string EventType { get; set; }
[Required]
[DataType(DataType.DateTime)]
[Display(Name = "Data")]
public System.DateTime EventDate { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Widocznosc")]
public string IsPublic { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Minimalny wiek")]
public int MinimalAge { get; set; }
[Display(Name = "Cena")]
[DataType(DataType.Text)]
public decimal Payment { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Opis")]
public string Description { get; set; }
[Required]
[DataType(DataType.Text)]
[Display(Name = "Miasto")]
public string City { get; set; }
public SelectList EventTypeList { get; set; }
}
What is more i have a page writen in razor like this (i will post just part of it):
<div class="form-group">
#Html.LabelFor(m => m.EventName, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.EventName, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.EventType, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.EventType, Model.EventTypeList, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.EventDate, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.EventDate, new { #class = "form-control", id = "datepicker" })
</div>
<script type="text/javascript">
$(function () {
$('#datepicker').datetimepicker({
minDate: moment()
});
});
</script>
</div>
<div class="form-group">
#Html.LabelFor(m => m.IsPublic, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
<table>
<tr>
<td><label>#Html.RadioButtonFor(m => m.IsPublic, "Prywatne") Prywatne</label></td>
</tr>
<tr>
<td><label>#Html.RadioButtonFor(m => m.IsPublic, "Publiczne") Publiczne</label></td>
</tr>
</table>
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.MinimalAge, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.MinimalAge, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Payment, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Payment, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Description, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextAreaFor(m => m.Description, new { #class = "form-control" })
</div>
</div>
</div>
Okay, so, when I am inserting my new event with a floating point number in field Cena/Payment im getting a strange error like this:
The ViewData item that has the key 'EventType' is of type 'System.String' but must be of type 'IEnumerable'.
It is pretty strange beacuse it is pointing on dropdownlist which is not connected with a Payment field. As I said, when I put a integer into Payment field - everything works fine.
Whats going on guys?
EDIT
Okey guys, i get it that i didnt reassing a SelectList in a post method. I fixed that already. However:
I want to understand why it was apearing only when i put a floating point number in a textbox
How to fix next problem: Value 'x.x' is not valid for Cena
The error is throw because the value of EventTypeList in
#Html.DropDownListFor(m => m.EventType, Model.EventTypeList, new { #class = "form-control" }
is null
This is happening because when you post back, ModelState is invalid and you return the view without re-assigning the SelectList (as you did in the GET method).
The reason ModelState is invalid is because the culture on the server does not accept the . (dot) character as a decimal separator (most likely it is a culture that uses , (comma) as the decimal separator). You need to change the culture in the web.config file, for example to <<globalization culture ="en-US" />