My date is displayed like dd/mm/yyyy. I want it displayed like yyyy-mm-dd.
#Html.EditorFor(x=> x.DateChosen, new { htmlAttributes = new { #id = "choosetime" } })
I already tried
#Html.EditorFor(x=> x.DateChosen, new { htmlAttributes = new { #id = "choosetime", "{0:dd/MM/yyyy}" } })
What you are looking for is DisplayFormatAttribute :
public class MyModel
{
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime DateChosen { get; set; }
// Other properties goes there
}
And use your Html helper like this :
#Html.EditorFor(x=> x.DateChosen, new { htmlAttributes = new { #id = "choosetime" } })
Edit 1 :
Base on comment, if you need to access the string representation of the DateChosen property somewhere else in your code, you can update your model like that :
public class MyModel
{
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime DateChosen { get; set; }
public string DateChosenString
{
return DateChosen.ToString("yyyy-MM-dd");
}
// Other properties goes there
}
Related
I have two text inputs that appear to be set up exactly the same, however while one gets the decimal places automatically added to it when you click out of the text box, the other one does not. I'm at a loss as to why this could be happening, any help would be much appreciated.
Works:
[Display(Name = #"Extra Withholding")]
[UIHint("GridFormFieldDecimal")]
[DisplayFormat(DataFormatString = "{0:0.00}", ApplyFormatInEditMode = true)]
public decimal? Federal2020ExtraWithholding { get; set; }
#Html.EditorFor(m => m.Federal2020ExtraWithholding,
new { SecondaryLabel = "W-4 Step 4 (c)",
OuterCss = "grid_8 alpha",
LabelCss = "grid_4",
InputCss = "grid_4",
HelpCss = "grid_4 display-none",
TextCss = "dollars -disable-on-exempt",
Prefix = "$"
})
Doesn't work:
[Display(Name = #"Other Income")]
[UIHint("GridFormFieldDecimal")]
[DisplayFormat(DataFormatString = "{0:0.00}", ApplyFormatInEditMode = true)]
public decimal? OtherIncomeAmount { get; set; }
#Html.EditorFor(m => m.OtherIncomeAmount,
new { SecondaryLabel = "W-4 Step 4 (a)",
OuterCss = "grid_8 alpha",
LabelCss = "grid_4",
InputCss = "grid_4",
HelpCss = "grid_4 display-none",
TextCss = "dollars -disable-on-exempt",
Prefix = "$"
})
I am having some trouble populating the tables when running the code online. Appointment date that I created in the DbInitializer appears but the StartTime and EndTime aren't showing online.
I think it has something to do with my appointments controller. If anyone can help that would be much appreciated.
This is the index part of the AppointmentController
public async Task<IActionResult> Index(string sortOrder)
{
ViewData["DateSortParm"] = sortOrder == "Date" ? "date_desc" : "Date";
var appointments = from s in _context.Appointments.Include(a => a.Customer).Include(a => a.Staff)
select s;
switch (sortOrder)
{
case "Date":
appointments = appointments.OrderBy(s => s.AppointmentDate);
break;
case "date_desc":
appointments = appointments.OrderByDescending(s => s.AppointmentDate);
break;
default:
appointments = appointments.OrderBy(s => s.AppointmentDate);
break;
}
return View(await appointments.AsNoTracking().ToListAsync());
}
This is the model for the Appointments
{
public class Appointment
{
public int AppointmentID { get; set; }
public int CustomerID { get; set; }
public int StaffID { get; set; }
//[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
//[Display(Name = "Appointment Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Appointment Date")]
public DateTime AppointmentDate { get; set; }
[DataType(DataType.Time)]
[DisplayFormat(DataFormatString = "{00:00:00}", ApplyFormatInEditMode = true)]
[Display(Name = "End Time")]
public DateTime EndTime { get; set; }
[DataType(DataType.Time)]
[DisplayFormat(DataFormatString = "{00:00:00}", ApplyFormatInEditMode = true)]
[Display(Name = "Start Time")]
public DateTime StartTime { get; set; }
public Customer Customer { get; set; }
public Staff Staff { get; set; }
}
}
select s;
switch (sortOrder)
{
case "Date":
appointments = appointments.OrderBy(s => s.AppointmentDate);
break;
case "date_desc":
appointments = appointments.OrderByDescending(s => s.AppointmentDate);
break;
default:
appointments = appointments.OrderBy(s => s.AppointmentDate);
break;
}
return View(await appointments.AsNoTracking().ToListAsync());
}
UPDATE
This is the code that is in my DbInitializer
var appointments = new Appointment[]
{
new Appointment{CustomerID=1,StaffID=1,AppointmentDate=DateTime.Parse("20/07/2017"),StartTime=DateTime.Parse("16:00:00"),EndTime=DateTime.Parse("17:00:00")},
new Appointment{CustomerID=2,StaffID=2,AppointmentDate=DateTime.Parse("20/05/2017"),StartTime=DateTime.Parse("17:00:00"),EndTime=DateTime.Parse("17:00:00")},
new Appointment{CustomerID=3,StaffID=3,AppointmentDate=DateTime.Parse("20/04/2017"),StartTime=DateTime.Parse("17:00:00"),EndTime=DateTime.Parse("17:00:00")},
new Appointment{CustomerID=4,StaffID=4,AppointmentDate=DateTime.Parse("20/03/2017"),StartTime=DateTime.Parse("17:00:00"),EndTime=DateTime.Parse("17:00:00")},
new Appointment{CustomerID=5,StaffID=5,AppointmentDate=DateTime.Parse("20/02/2017"),StartTime=DateTime.Parse("17:00:00"),EndTime=DateTime.Parse("17:00:00")},
new Appointment{CustomerID=6,StaffID=6,AppointmentDate=DateTime.Parse("20/09/2017"),StartTime=DateTime.Parse("17:00:00"),EndTime=DateTime.Parse("17:00:00")},
new Appointment{CustomerID=7,StaffID=7,AppointmentDate=DateTime.Parse("20/08/2017"),StartTime=DateTime.Parse("17:00:00"),EndTime=DateTime.Parse("17:00:00")},
new Appointment{CustomerID=8,StaffID=8,AppointmentDate=DateTime.Parse("20/06/2017"),StartTime=DateTime.Parse("17:00:00"),EndTime=DateTime.Parse("17:00:00")}
};
foreach (Appointment c in appointments)
{
context.Appointments.Add(c);
}
context.SaveChanges();
}
This is a screen shot of the appointments part. I have populated the database to show a start and end time but as you can see nothing is being pulled through.
I have a model defined this way:
public class AdvisoryViewModel : IValidatableObject
{
[Display(Name = "Start Date")]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true, ConvertEmptyStringToNull = true)]
public DateTime? StartDate { get; set; }
[Display(Name = "End Date")]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true, ConvertEmptyStringToNull = true)]
public DateTime? EndDate { get; set; }
[Display(Name = "Instructions")]
[Required(ErrorMessage = "Instructions are required")]
[MaxLength(500, ErrorMessage = "Instructions cannot be longer than 500 characters.")]
public string Instruction { get; set; }
IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)
{
List<ValidationResult> results = new List<ValidationResult>();
if (StartDate.HasValue &&
EndDate.HasValue &&
StartDate.Value > EndDate.Value)
{
ValidationResult result = new ValidationResult("Start date must be after end date.");
results.Add(result);
}
return results;
}
And I am validating it as follows:
var validationResults = new List<ValidationResult>();
if (!Validator.TryValidateObject(advisoryViewModel, new ValidationContext(advisoryViewModel), validationResults, true))
{
return Json(new { success = false, message = string.Join("; ", validationResults.Select(r => r.ErrorMessage)) });
}
What happens on validation is it first only calls the "Required" attributes - for example, if the start date is later than end date AND the instructions are null, it returns with only the message that instructions cannot be null. Once they are not null, it returns the start/end date error message.
Is there a way to have it do ALL of the validations up front rather than two attempts?
Also, is there a way the start/end validation can be added to client side results?
I have a View that contains an Model, this model contains a list(of another Model) and this list is filled in my view with Dynamic repeating fields;
Model:
public class CAOEntry
{
public CAOEntry()
{
this.TimeEntries = new List<TimeEntry>() { new TimeEntry() };
}
public DateTime ValidFrom { get; set; }
public DateTime ValidTo { get; set; }
public List<TimeEntry> TimeEntries {get; set;}
}
My View(the part that creates the handles the TimeEntry List)
#Html.EditorFor(model => model.TimeEntries)
<button data-bind="click: addTimeEntry">Voeg tijdsvak toe</button>
<button data-bind="click: removeTimeEntry">Verwijder laatste</button>:
the data-bind"click:addTimeEntry" is a jQuery/KnockoutJs script that adds new time entries. These are added from an Editor Template.
In this Editor template i got the following line of code:
#Html.EnumDropDownListFor(model => model.DayOfWeekOrHoliday,"--Selecteer een dag--", new { htmlAttributes = new { #class = "form-control", data_bind = "value: DayOfWeekOrHoliday, namePath: true" } })
Now the following happens when i have, for example two, TimeEntries filled in and click on save;
There are three time entries returned to my controller:
One containing the first filled Enum Value, other fields are null.
the other two don't contain any Enum values but have the other fields filled.
When debugging the view, i saw the following problem;
TimeEntry 1:
enum field;
id="TimeEntries_0__DayOfWeekOrHoliday" name="TimeEntries[0].DayOfWeekOrHoliday"
Example of a second field:
id="TimeEntries_1__TimeFrom" name="TimeEntries[1].TimeFrom"
TimeEntry 2:
Enum field;
id="TimeEntries_0__DayOfWeekOrHoliday" name="TimeEntries[0].DayOfWeekOrHoliday"
Example of a second field:
id="TimeEntries_2__TimeFrom" name="TimeEntries[2].TimeFrom"
so the Array is not incremented right for the enum value. Is this because there is an enum field in an EditorFor helper?
I can't figure out how to solve this.
[Edit]
TimeEntry Class:
public class TimeEntry
{
public int ID { get; set; }
//1:Monday,2:Tuesday,3:Wednesday,4:Thursday,5:Friday,6:Saturday,7:Sunday,8:Any Holiday
public enum Days {Maandag =1,Dinsdag =2, Woensdag=3,Donderdag = 4, Vrijdag= 5, Zaterdag=6, Zondag=7, Feestdag = 8}
[Required]
[Display(Name = "Dag")]
[Range(1, int.MaxValue, ErrorMessage = "Selecteer een dag")]
public Days DayOfWeekOrHoliday { get; set; }
[Required]
[Display(Name = "Start Tijdvak(uur:minuten)")]
[StringLength(5, MinimumLength = 5)]
[DataType(DataType.Time)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:hh:mm}")]
public string TimeFrom { get; set; }
[Required]
[Display(Name = "Eind Tijdvak(uur:minuten)")]
[StringLength(5, MinimumLength = 5)]
[DataType(DataType.Time)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:hh:mm}")]
public string TimeTo { get; set; }
[Required]
public decimal Premium { get; set; }
}
EditorFor:
function createViewModel() {
var createTimeEntry = function () {
return {
DayOfWeekOrHoliday: ko.observable(),
TimeFrom: ko.observable(),
TimeTo: ko.observable(),
Premium: ko.observable()
};
};
var addTimeEntry = function () {
TimeEntries.push(createTimeEntry());
};
var removeTimeEntry = function () {
TimeEntries.pop();
};
var ValidFrom = ko.observable();
var ValidTo = ko.observable();
var TimeEntries = ko.observableArray([createTimeEntry()]);
return {
ValidFrom: ValidFrom,
ValidTo: ValidTo,
TimeEntries: TimeEntries,
addTimeEntry: addTimeEntry,
removeTimeEntry: removeTimeEntry
};
}
$(document).ready(function () {
var viewModel = createViewModel();
ko.applyBindings(viewModel);
});
</script>
The context of application the is maintaining security orders from Investment Advisors. On a screen where an users amends his orders is the problem appears. In such screen a I have dropdown list to specify the order type whether its a buy or sell and shows values for security, Quantity and price.
Problem
I have witnessed while being in an Edit screen, after doing an amendment (Tests have performed not by changing the Buy/Sell but others i.e price). If I performed a HTTP Post, the values of the DropDownList returns null. Refer screenshot:
Initialization of SelectList type
public static List<SelectListItem> getBuySellList()
{
List<SelectListItem> buySell = new List<SelectListItem>();
SelectListItem item;
item = new SelectListItem();
item.Text = "BUY";
item.Value = "BUY";
buySell.Add(item);
item = new SelectListItem();
item.Text = "SELL";
item.Value = "SELL";
buySell.Add(item);
return buySell;
}
My Controller as follows:
// GET: OrderFlow/Edit/5
public ActionResult Edit(int id)
{
OrderFlowModel orderFlowModel = db.Find(id);
ViewData["ORDERFLOW_NO"] = id;
ViewBag.OrderFlowBuySell = Utility.UtilityDBContext.getBuySellList();
return View(orderFlowModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(string OrderFlowNo, string OrderFlowSecurityID, string OrderFlowBuySell, string OrderFlowQuantity, string OrderFlowPrice, string OrderFlowTradingDate, string OrderFlowClientAccount, string OrderFlowParticipant, string OrderFlowBuyStatus)
{
if (ModelState.IsValid)
{
OrderFlowModel orderFlowModel = new OrderFlowModel();
orderFlowModel.OrderFlowNo = int.Parse(OrderFlowNo.ToString());
orderFlowModel.EquityID = OrderFlowSecurityID;
orderFlowModel.BuySell = OrderFlowBuySell;
orderFlowModel.Quantity = int.Parse(OrderFlowQuantity);
orderFlowModel.Price = double.Parse(OrderFlowPrice);
DateTime dt;
if (DateTime.TryParseExact(OrderFlowTradingDate, formats, System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.None, out dt))
{
orderFlowModel.TradingDate = dt;
}
else orderFlowModel.TradingDate = DateTime.Today;
orderFlowModel.ClientAccountID = OrderFlowClientAccount;
orderFlowModel.ParticipantAccountID = OrderFlowParticipant;
orderFlowModel.Status = OrderFlowBuyStatus;
try
{
db.Edit(orderFlowModel);
return RedirectToAction("Index");
}
catch (Exception er)
{
TempData["Message"] = er.Message;
}
}
ViewBag.OrderFlowBuySell = Utility.UtilityDBContext.getBuySellList();
return RedirectToAction("Edit", new{id=OrderFlowNo});
}
The OrderFlow Model:
public class OrderFlowModel
{
[Display(Name = "Order Flow No")]
public int OrderFlowNo { get; set; }
[Display(Name = "Valid Till")]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
[DataType(DataType.Date)]
public DateTime TradingDate { get; set; }
[Display(Name = "Client A/c ID")]
public string ClientAccountID { get; set; }
[Display(Name = "Participant ID")]
public string ParticipantAccountID { get; set; }
[Required(ErrorMessage="Security is Required")]
[Display(Name = "Security")]
public string EquityID { get; set; }
[Required(ErrorMessage = "Buy or Sell Needs to specify")]
[Display(Name = "BS")]
public string BuySell { get; set; }
[DefaultSettingValue("0")]
[Display(Name = "Quantity")]
[DisplayFormat(DataFormatString = "{0:N0}")]
public int Quantity { get; set; }
[Display(Name = "Price")]
[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:N2}")]
public double Price { get; set; }
[Display(Name = "Status")]
public string Status { get; set; }
[Display(Name = "User Entered")]
public string UserEntered { get; set; }
[Display(Name = "Effective From")]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime EffectiveStart { get; set; }
[Display(Name = "Effective Till")]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime EffectiveEnd { get; set; }
}
The way I have assigned DropdownListFor in Razor as follows:
#Html.DropDownListFor(model => model.BuySell, new SelectList(ViewBag.OrderFlowBuySell, "Text", "Value"), new { #id = "OrderFlowBuySell", #class = "form-control" })
HTML output from Browser for the Dropdown List
<select class="form-control" data-val="true" data-val-required="Buy or Sell Needs to specify" id="OrderFlowBuySell" name="BuySell"><option selected="selected" value="BUY">BUY</option>
<option value="SELL">SELL</option>
</select>
The value that needs to be in your controller method is BuySell, this is the selected id of the dropdownlist from your mark-up below (the first parameter):
#Html.DropDownListFor(model => model.BuySell,
new SelectList(ViewBag.OrderFlowBuySell, "Text", "Value"),
new { #id = "OrderFlowBuySell", #class = "form-control" })
The OrderFlowBuySell is the collection of options that are used to bind the dropdown, in the post you are usually only concerned with the option a user has selected.
Change it to this and the value will be posted:
Edit(string OrderFlowNo, string OrderFlowSecurityID,
string OrderFlowBuySell, string OrderFlowQuantity,
string OrderFlowPrice, string OrderFlowTradingDate,
string OrderFlowClientAccount, string OrderFlowParticipant,
string OrderFlowBuyStatus, string BuySell)
However I would strongly advise you use ViewModels, that way you can just speficy a single object to your controller post.