MVC3 EditorFor losing value on postback - asp.net-mvc

I've created and date editorfor template but the value is getting lost on postback. Please can anyone help?
Here's my Date.cshtml stored in the 'shared/editortemplates' folder:
#model DateTime
<div class="input-append">
<input type="text" class="input-small datePicker" id="#ViewBag.Id" name="#ViewBag.Id" />
<span class="add-on"><i class="icon-th"></i></span>
</div>
Here's the view:
#Html.EditorFor(m => m.RequiredByDate, new { Id = "RequiredByDate" })
And the property on the viewmodel:
[Display(Name = "Required by date")]
[Required(ErrorMessage = "Required by date is required.")]
[DataType(DataType.Date)]
public DateTime RequiredByDate { get; set; }
Any help greatly appreciated.

I've not set the value on the input. what an idiot.
<input type="text" class="input-small datePicker" id="#ViewBag.Id" name="#ViewBag.Id" value="#Model.ToString("dd/MM/yyyy")" />

Related

Client side validation for model attribute Asp.Net Core MVC

Help me to validate(client side validation) model attribute using asp.net core mvc.
Public class Ticket{
[StringLength(150), Required]
public string Name { get; set; }
[Required] [RegularExpression(#"^[\w-\.]+#([\w-]+\.)+[a-zA-Z+\.]*[a-zA-Z] {2,4}$", ErrorMessage = "Invalid {0}")]
public string Email { get; set; }
}
I am using Ticket model and binding ticket model to html.Html is as below
<label asp-for="Name">Name</label>
#(Html.Kendo().TextBoxFor(x => x.Customer.Name).HtmlAttributes(new { style = "width:100%;", #class = "form-control", }))
<span asp-validation-for="Name" class="text-danger"></span>
<label asp-for="Email">Email</label>
#(Html.Kendo().TextBoxFor(x => x.Customer.Email).HtmlAttributes(new { style = "width:100%;", #class = "form-control"}))
#*<span asp-validation-for="Email" class="text-danger"></span>*#
#Html.ValidationMessageFor(x => x.Customer.Email, "", new { #class = "text-danger" })
But here it is not validating an email input or Name input length. And in html markup their is no required attribute or max-length attributes. Below is Html Markup
<div class="form-group">
<label asp-for="Name">Name</label>
<input class="k-textbox form-control" id="Customer_Name" name="Customer.Name" style="width:100%;" value="">
<span asp-validation-for="Name" class="text-danger"></span>
</div>
Html markup is generated without any required attribute or regex pattern for email.
I am missing anything?. Help me out what i need add more for client side validation.

MVC 5 view still render required field

Initially I have two required date time properties in my model. The client side validation works fine for them. But when i comment out the required DataAnnotation on one of the property, MVC view still generating data-val=true, ect... How to i fix this so that mvc view is rendering field is not required.
I've try $('#endDate').rules('remove', 'required')
but it still checking required field.
Model:
public class mymodel{
...
[Required]
public Datetime startDate { get; set;}
//[Required]
public Datetime endDate {get; set}
}
View:
#Html.LabelFor(model => mode.endDate ....)
#Html.EditorFor(model => model.endDate, new { htmlAttributes = new { #class = "form-control", id="endDate" } })
View Render
<input class="form-control text-box single-line hasDatepicker input-validation-error" data-val="true" data-val-date="The field endDate must be a date." data-val-required="The endDate field is required." id="endDate" ....>
<span class="text-danger field-validation-error" ....>
<span for="endDate" class> The endDate field is required.</span>
</span>
Properties with non-nullable types (such as DateTime) are inherently required, with or without the Required attribute, because they must have some value. To make it optional, you must use a nullable DateTime:
public DateTime? endDate { get; set; }

Input type checkbox with MVC razor

Why is the value of my checkbox not passed to my ViewModel?
My View (I omitted input tags not relevant for this post):
#model Pro.WebUI.ViewModels.UserViewModel
#using (Html.BeginForm("ManageUsers", "Administration", FormMethod.Post,
new { id = "request-form", #class = "form-horizontal" }))
{
<div class="form-group">
<label for="inputAuthorize" class="col-lg-2 control-label">Authorize</label>
<div class="col-lg-8">
<input type="checkbox" id="Authorized" name="Authorized" value="#Model.Authorized" />
</div>
</div>
<div class="form-group">
<div class="col-lg-10 col-lg-offset-2">
<br /><br />
<button type="submit" class="btn btn-primary">Submit Request</button>
</div>
</div>
}
My ViewModel:
public class UserViewModel
{
[Key]
public string UserID { get; private set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool Authorized { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Notes { get; set; }
}
My Controller:
[HttpPost]
public ActionResult ManageUsers(UserViewModel model)
{
if (ModelState.IsValid)
{
ProcurementUser obj = new ProcurementUser();
obj.UserName = model.Email;
obj.FirstName = model.FirstName;
obj.LastName = model.LastName;
obj.Email = model.Email;
obj.Phone = model.Phone;
obj.Authorized = model.Authorized;
UserRepository.SaveUser(obj);
//success message
}
return View(model);
}
I did not include all input tags but when I step through the code without the checkbox, all values are passed. I looked at other checkbox questions on SOF but they mostly use the #Html.Checkbox or #Html.CheckboxFor. I would like to just use input type="checkbox"
If we need to use <input> filed instead of #Html.CheckboxFor, we can use "checked=\"checked\"" syntax as in this code:
<input type="checkbox" id="Authorized" name="Authorized" value="true" #(Model.Authorized ? "checked=\"checked\"" : "") />
As has been hinted at in the comments the issue you're having is that you're not really creating your checkbox correctly:
Assuming your model has Authorized = true your mark-up would be:
<input type="checkbox" id="Authorized" name="Authorized" value="true" />
Similarly the false state would result in:
<input type="checkbox" id="Authorized" name="Authorized" value="false" />
But these aren't "checked" checkboxes - they're still "unchecked", and need the checked attribute setting:
<input type="checkbox" id="Authorized" name="Authorized" value="true" checked />
As Stephen points out - an unchecked checkbox will not send any data back to the server so that you don't get confused about which options where selected.
Finally, as has also been noted, your <label> element is for an non-existent field looking for inputAuthorize instead of Authorized.
All of these issues would be taken care of for you if you were to use the #Html.CheckboxFor and #Html.LabelFor helper classes.

MVC input DateTime

If I use EditFor in MVC my DateTime field show a not formated datetime, If I use a old school html my field don't receive the error class.
<div class="editor-field">
<input type="text" name="EstimateTime" id="EstimateTime" value="<%: (Model != null) ? Model.EstimateTime.ToString("dd/MM/yyyy hh:mm:ss tt") : "" %>" />
<%: Html.TextBoxFor(model => model.EstimateTime, new { #value = (Model != null) ? Model.EstimateTime.ToString("dd/MM/yyyy hh:mm:ss tt") : "" })%>
<%: Html.ValidationMessageFor(model => model.EstimateTime) %>
</div>
result HTML: Look the difference between the value:
<div class="editor-field">
<input type="text" name="EstimateTime" id="EstimateTime" value="31/10/2013 01:54:42 PM" class="hasDatepicker">
<input id="EstimateTime" name="EstimateTime" type="text" value="10/31/2013 1:54:42 PM" class="input-validation-error text-box single-line">
<span class="field-validation-error">Isn't a date/time valid</span>
</div>
What is the best practices to fix it?
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")]
[DataType(DataType.Date)]
public System.DateTime EstimateTime { get; set; }
This is working for me in the latest version of Chrome
Add DataFormatString to the property in your model.
public class YourModel
{
[DisplayName("Estimate Time:"),
DisplayFormat(DataFormatString = "{0:dd/MM/yyyy hh:mm:ss tt}")]
public System.DateTime EstimateTime { get; set; }
...
}
I always use an Editor Template to perfect output control
this is DateTime.cshtml:
#model System.DateTime?
#{
IDictionary<string, object> Attributes = new Dictionary<string, object>();
if (ViewData.ContainsKey("style")) {
Attributes.Add("style", (string)ViewData["style"]);
}
if (ViewData.ContainsKey("autohelp")) {
Attributes.Add("title", (string)ViewData["autohelp"]);
}
if (ViewData.ContainsKey("autofocus")) {
Attributes.Add("autofocus", (string)ViewData["autofocus"]);
}
Attributes.Add("class", "fecha");
Attributes.Add("autocomplete", "off");
}
#Html.TextBox("", (Model.HasValue ? Model.Value.ToShortDateString() : string.Empty), Attributes)

ASP.NET MVC - Can't bind array to view model

I have a view model with a from that includes a set of checkboxes. I need the check boxes to map to an array when binding in the post back method of my controller.
Here's the view model.
#model TMDM.Models.TestSeriesCreateViewModel
#{
ViewBag.Title = "Create";
}
<h2>Create a Test Series</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<h3>Which Test Collections are in this Test Series?</h3>
<div class="editor-field">
#{
var i = 0;
foreach (var testCollection in Model.TestCollections)
{
<input type="checkbox" id="ChosenTestCollectionIds[#i]" name="ChosenTestCollectionIds[#i]" value="#testCollection.Id" />
<span>#testCollection.Title</span>
<br />
i++;
}
}
</div>
<p>
<input type="submit" value="Save" class="medium green awesome" />
#Html.ActionLink("Cancel", "Index", "TestSeries", null, new { #class = "medium black awesome" })
</p>
</fieldset>
The form is rendering fine, I've checked the source and each output check box has a different number for their id and name fields.
<input type="checkbox" id="ChosenTestCollectionIds[0]" name="ChosenTestCollectionIds[0]" value="5" />
<input type="checkbox" id="ChosenTestCollectionIds[1]" name="ChosenTestCollectionIds[1]" value="6" />
//etc...
Here is the view model.
public class TestSeriesModel
{
public int Id { get; set; }
public string Title { get; set; }
}
public class TestSeriesCreateViewModel : TestSeriesModel
{
public List<ITestCollectionDataObject> TestCollections { get; set; }
public int[] ChosenTestCollectionIds { get; set; }
}
Problem I'm having is that when the form posts back the ChosenTestCollectionIds array comes back null. What am I doing wrong here?
ANSWER
I've worked out how to do it:
<input type="checkbox" id="[#i]" name="ChosenTestCollectionIds" value="#testCollection.Id" />
<input type="checkbox" id="[#i]" name="ChosenTestCollectionIds" value="#testCollection.Id" />
I always come back to Phil Haack's post about model binding a list. In addition, I always define my own index because my user's will alter the list on the client side then post back the changes.
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Set the name of the input types to all be the same. You can also create a custom model binder if you are trying to bind a more complex model than just a list. Here is an excellent article on the different ways to bind to your models
Various Model Binding techniques

Resources