Problems with DateTime, it appears with 00:00:00 - asp.net-mvc-3

I have my database which has a DateTime type for Birthdate value when I register the user.
When I receive my data back, to edit the register form, I have my Razor like this:
#Html.TextBoxFor(model => model.Birthdate)
The date shows like this: 28/05/1983 00:00:00
I want only the birthdate, obviously. In my Controller, I have this:
User userset = db.User.Find(id);
return View(userset);
Very simple... Could anyone help me to solve that?

Set the DisplayFormat data annotation above the property in your model.
public class User
{
[DisplayFormat(DataFormatString = "{0:dd/MM/yy}", ApplyFormatInEditMode = true)]
public DateTime Birthdate { get; set; }
...
}
Then instead of using #Html.TextBoxFor(..) use #Html.EditorFor(...).
See the DisplayFormatAttribute MSDN page for more details.
If you have generated your data model using EF you can simply create a meta class for your class to apply data annotations. For example, if my db file is called MyDB.edmx, create a buddy class file called MyDB.cs. Then inside there, I would extend the User class by attaching a metadata class to it and specifying the data annotation in the metaclass:
[MetadataType(typeof(UserMetaData))]
public partial class User{ }
public class UserMetaData
{
[DisplayFormat(DataFormatString = "{0:dd/MM/yy}", ApplyFormatInEditMode = true)]
public DateTime Birthdate { get; set; }
}
See Scott Gu's post on validation, mainly the section 'But what if we are using a graphical tool for our ORM mappings?'.

You can do something like this using Html.TextBox instead of using Html.TextBoxFor.
#Html.TextBox("Birth date", String.Format("{0:dd/MM/yyyy}", Model.Birthdate))

DatePicker from jQuery is a better approach to receive date input from user. It is particularly helpful to avoid various date format confusion.
More details on: http://blogs.msdn.com/b/stuartleeks/archive/2011/01/25/asp-net-mvc-3-integrating-with-the-jquery-ui-date-picker-and-adding-a-jquery-validate-date-range-validator.aspx

Related

Required field not present on all pages leading to problems

I have a ‘Create’ page in my MVC3 application that has 4 input fields that are all required. I also have an ‘Edit’ page in which 3 of these 4 fields can be edited. I do not want to display the 4th field and want to maintain it at its initial value (the field is the date that the entry was created ).
I mark the 4th field as [Required] in the model then this causes the model to be declared as invalid in post action method of the Edit field. If I omit the [Required] annotation then someone can create a user with a null value for this 4th field.
How can I get around this problem?
Model Code:
[Required]
[DisplayName("User Name")]
public string UserName { get; set; }
[Required]
public string Role { get; set; }
[Required]
[DataType(DataType.Date)]
[DisplayName("Insert Date")]
public DateTime? InsertDate { get; set; }
[Required]
[DisplayName("Active")]
public bool ActiveInd { get; set; }
Controller Code:
public ActionResult Edit(int id, ZUserRoleModel mod)
{
if (ModelState.IsValid)
{
// code removed
return RedirectToAction("Index");
}
return View(mod);
}
You can make that field as hidden in edit mode.
#Html.HiddenFor(x => x.EntryDate)
Not sure if you still need an answer for this, but what you need to do in order for the
#Html.HiddenFor(x => x.EntryDate )
to work, is pass an existing model into view. So let's assume that your action for getting the user data looks like this. ( You did not supply it, so I am not sure if this is right )
Public ActionResult GetUser(int UserID)
{
ZUserRoleModel model = new ZUserRoleModel(UserID);
// Maybe this could go to your database and gather user
// It would populate the correct data into a model object
return View("Edit", model);
}
With combination of the hidden field, your view will be populated with the existing user information, and the hidden field will be populated with data, and it will be passed to your edit action.
NOTE: I wrote this without any kind of testing, but it should still work, or at the very least, I hope it points you in the right direction if you still need assistance.
You can use fluentvalidation: http://fluentvalidation.codeplex.com/
Have a rule that's something like
RuleFor(user => user.field4).NotEmpty().When(ViewContext.Controller.ValueProvider.GetValue("action").RawValue <> "edit")

Html.EditorFor nullable DateTime posting back as null from view

Lets make the following assumptions; ASP.NET MVC 3 Razor C#, a strongly typed view bound to a view model (not entities etc.), using the Html.EditorFor method, to edit a nullable DateTime property in the view model. The two data annotation attributes I added seem to be causing model binding to fail.
Sample view code
#model MyApp.ViewModels.NullableDateTimeViewModel
#using (Html.BeginForm())
{
#Html.EditorFor(m => m.DateOfBirth)
}
Sample ViewModel code
[DataType(DataType.Date,
ErrorMessage = "Please enter a valid date in the format dd MMM yyyy")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MMM yyyy}")]
public class NullableDateTimeViewModel
{
public DateTime? DateOfBirth { get; set; }
}
Sample controller code
[HttpPost]
public ViewResult DoB(NullableDateTimeViewModel nullableDateTimeVM)
{
ContextDB db = new ContextDB();
Customer cust = new Customer();
// DateOfBirth is null so the update fails
cust.DateOfBirth = nullableDateTimeVM.DateOfBirth.Value;
db.Customers.Add(cust);
db.SaveChanges();
}
The data entered in the view is not posting back to the controller when the form in the view is submitted when the data annotation attributes are added. This means that model binding is failing when using EditorFor with those attributes. Model binding works fine with TextBoxFor, the value entered in the TextBoxFor input box is passed back to the view with the view model. What is the problem here with EditorFor and the data annotation validation attributes?
Can we please find a solution that does not involved reinventing the wheel by creating multiple additional classes, helpers, templates and writing a whole lot of additional code? I am looking for a one or two line solution.

MVC3 validate only one entity in ViewModel

I have an mvc3 create page using a View Model with 2 entities
like
class ViewModel1{
public User user{get;set;}
public Company company{get;set;}
}
where User and Company are EF4 entities(tables). I need to use a single page to create both(related) tables. Now the Company entity is optional under some conditions and I use jQuery to hide the corresponding section in the view.
However since company has required fields , the post back create function has ModelState.Valid as false.
What I want to do is if the Company section is hidden, I would like to skip validating the Company entity in ViewModel in Server( I avoid validation of hidden elements in Client).
Maybe there is a better and more proper approach to this?
What you have shown is not a view model. You call it a view model but it isn't because it is referencing your EF domain entities.
A more realistic view model would look like this:
class ViewModel1
{
public UserViewModel User { get;set; }
public CompanyViewModel Company { get; set; }
}
or even flattened out and containing only the properties that your view needs:
class ViewModel1
{
public int UserId { get;set; }
[Required]
public string FullUserName { get;set; }
[Required]
public string CompanyName { get; set; }
}
Now depending on your specific requirements about view model validation your UserViewModel and CompanyViewModel classes will be specifically designed for them.
Instead of putting the entities directly in the view model, put the properties for the entities in the view model and map between the view model and the actual entity objects on the server. That way you can control what properties are required for your view. Create some custom validation rules to validate that the required company properties are there when some company information is required. To do this on the server, you can have your view model implement IValidatableObject and implement the logic in the Validate method. On the client you can add rules to the jQuery validate plugin for the "required if" properties.
public class UserCreationViewModel : IValidatableObject
{
[Required]
public string Username { get; set; }
[Required]
public string FirstName { get; set; }
...
public string CompanyName { get; set; }
public string CompanyEmail { get; set; }
public IEnumerable<ValidationResult> Validate( ValidationContext context )
{
if (!string.IsNullOrEmpty(CompanyName) && string.IsNullOrEmpty(CompanyEmail))
{
return yield new ValidationResult("Company Email is required if you specify a company", new [] { "CompanyEmail" });
}
}
}
I'm not sure what I would do on the client-side. You have a choice of either adding specific rules to the validate plugin directly, but it might be hard to make it look exactly the same as using the unobtrusive validation that MVC adds. Alternatively, you could look at adding/removing the unobtrusive attributes from the "required if" elements using jQuery depending on the state of the elements that trigger their requirement. I suggest trying both ways -- look at the docs for the validate plugin to see how to add custom rules and examine the code emitted by the MVC framework for the unobtrusive validate to see what you would need to add to make that work.
Another possibility would be including/removing a partial view with the company properties in the from based on whether the company information is required or not. That is, type in a company name and use AJAX to grab the inputs required for the company and add them to the form. If the company name is deleted, delete the elements. Leave the server-side validation the way it is, but in the partial view mimic the HTML that the framework would add in for unobtrusive validation. This is sort of the best of both worlds as the jQuery code is much simpler and you get consistent validation, too.
There are many ways you can achieve,
1) more commonly donot use [Required] attribute on Company object, but have proper validation for parameters inside Company object.
In this case if Company object is null still validation will pass, but if Company object isnot null it will validate each properties.
2) If validation involves some complex business logic, then go for Self Validating Model. (inherit from IValiddatableObject, and override Validate(...).
3) By code, in the controller.
if(model.company == null)
this.ModelState.Keys.Where(k => k.Contains("company")).ToList().ForEach(k => this.ModelState.Remove(k));
first two are best approved approaches, third is just another way to achieve your functionalities

Reusable editor template with DropDownList for business objects

I'm using MVC3 with Razor views and would like to build reusable DropDownLists for several of my classes, but after much searching I have not found an example that performs exactly how I need it...
For this example I have two classes like this:-
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
public Group Group { get; set; }
}
public class Group
{
public int ID { get; set; }
public string Name { get; set; }
}
I have a working Controller/View for Person. The view has a DropDownListFor control:
#model Person
...
#Html.DropDownListFor(o => o.Group.ID, (ViewData["groups"] as SelectList))
The view uses the Person class directly, not an intermediary model, as I haven't found a compelling reason to abstract one from the other at this stage.
The above works fine... in the controller I grab the value from Group.ID in the Person returned from the view, look it up, and set Person.Group to the result. Works, but not ideal.
I've found a binder here: MVC DropDownList values posted to model aren't bound that will work this out for me, but I haven't got that working yet... as it only really seems useful if I can reuse.
What I'd like to do is have something like this in a template:-
#model Group
#Html.DropDownListFor(o => o.Group.ID, (ViewData["groups"] as SelectList))
And use it in a view like this:-
#Html.EditorFor(o => o.Group)
However the above doesn't seem to work... the above EditorFor line inserts editors for the whole class (e.g. a textbox for Group.Description as well)... instead of inserting a DropDownList with my groups listed
I have the above template in a file called Group.cshtml under Views/Shared/EditorTemplates
If this worked, then whenever a class has a property of type Group, this DropDownList editor would be used by default (or at least if specified by some attribute)
Thanks in advance for any advice provided...
You can create a drop down list user control to handle this. Under your Shared folder create a folder called EditorTemplates and place your user control there. MVC, by convention, looks in the Shared/EditorTemplates for any editor templates. You can override where it looks for the editor templates but I won't go in to that here.
Once you have your user control created, you'll need to decorate the appropriate property with the "UIHint" attribute to tell the engine what editor it should use for that property.
Following would be a sample implementation.
In the Shared/EditorTemplates folder your user control (_GroupsDropDown.cshtml in this case) would look like:
#model Group
#Html.DropDownListFor(o => o.ID, (ViewData["groups"] as SelectList))
Modify the Group property in the Person to add the UIHint attribute as follows:
**[UIHint("_GroupsDropDown")]**
public Group Group { get; set; }
In your controller you would need
ViewData["groups"] = new SelectList(<YourGroupList>, "ID", "Name");
Once you have the above code you can use the EditorFor syntax like you desire.
Hope this helps.

How do I show a different Required message to instances of the same object in MVC3?

I have a Razor MVC3 project which has two user records in a form, one for the key contact and one for a backup contact. For example;
public class User
{
[Required(ErrorMessage = "First name is required")]
public string FirstName { get; set; }
}
Validation all works well except for the small issue where the user fails to fill out a field, it says 'First name is required' but I'd like to point the user to which one of the first name fields is missing. Such as 'Backup contact first name is required' or 'Key contact first name is required'.
Ideally I'd like to leave the [Required] annotation on the class as it is used elsewhere.
This seems like one of those small cases that might have been missed and is not easily achieved, but please prove me wrong.
Ryan
One way you can accomplish this is with a separate view model for this screen, instead of a single User model with all the error messages. In the new view model, you could have a BackupContactFirstName property, KeyContactFirstName property, etc each with its separate error message. (Alternatively this view model could contain separate User models as properties, but I've found that Microsoft's client validation doesn't play well with complex models and prefers flat properties).
Your view model would look like this:
public class MySpecialScreenViewModel
{
[Required(ErrorMessage = "Backup contact first name is required")]
public string BackupContactFirstName { get; set; }
[Required(ErrorMessage = "Key contact first name is required")]
public string KeyContactFirstName { get; set; }
}
Then pass your view model to the view like this:
#model MySpecialScreenViewModel
...
Your post controller action would collect the properties from the view model (or map them to separate User models) and pass them to the appropriate data processing methods.
An alternative I have stumbled across, just modify the ModelState collection. It will have the elements in a collection named by index, like 'User_0__EmailAddress' and you can adjust / amend / replace the Errors collection associated with that key.
[Required(ErrorMessage = "{0} is required")]
{0}=The DisplayName is automatically placed on it
sample
[DisplayName("Amount per square meter")]
[Required(ErrorMessage = "{0} is required")]
public int PriceMeter { get; set; }
output
Amount per square meter is required

Resources