Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Appropriate way to set default values for ViewModel in MVC4?

I have a viewModel that contains the following:

public class CreateCardViewModel
    {
        [HiddenInput(DisplayValue = false)]
        public int SetId { get; set; }

        [Required]
        public IList<Side> Sides { get; set; }

        [Required]
        public int Stage { get; set; }

        [Required]
        [DataType(DataType.Date)]
        [HiddenInput(DisplayValue = false)]
        public DateTime DateCreated { get; set; }

        [Required]
        public bool IsReady { get; set; }

    }

The model is as follows:

public class Card
    {

        public virtual int CardId { get; set; }

        // belongs to a Set
        public virtual int SetId { get; set; }
        public virtual Set Set { get; set; }

        // has Sides
        public virtual IList<Side> Sides { get; set; }

        // is in a certain Stage
        public virtual int Stage { get; set; }

        // is ready to study
        public virtual bool IsReady { get; set; }

        public virtual DateTime DateCreated { get; set; }

    }

How can I set a default value for DateCreated?

Would the method change if I want to insert a blank Side into Sides upon Card creation?

like image 415
RobVious Avatar asked Feb 11 '13 17:02

RobVious


People also ask

How do I change the default value in ViewBag?

You just need to set ViewBag. Quantity value in your controller's action. No, if you set ViewBag. Quantity = 10 you will se 10 in your form.

Should ViewModel have methods?

At least in my knowledge, as per the design principles, ideally we should not have methods in view model classes and create a separate class to manage interaction between business objects and view models.

What is ViewModel in MVC with example?

In ASP.NET MVC, ViewModel is a class that contains the fields which are represented in the strongly-typed view. It is used to pass data from controller to strongly-typed view.

Can a ViewModel have methods?

Defines a class used to provide values and methods to the component's view.


2 Answers

You could set defaults in the constructor:

public CreateCardViewModel()
{
    DateCreated = DateTime.Now;
    Sides = new List<Side> { new Side() };
}

Caveat: There is an issue with using DateTime.Now from a unit testing perspective. If you're unit testing your ViewModel creation and need to be able to verify that the created date is set to a known value, you can look at creating a separate concept for time, as detailed in Ayende's blog. You basically create a static func, SystemTime, that you can set to a known value in your tests. If you don't set it, it defaults to DateTime.Now:

public static class SystemTime
{
    public static Func<DateTime> Now = () => DateTime.Now;
}

Your constructor code then becomes:

public CreateCardViewModel()
{
    DateCreated = SystemTime.Now();
    Sides = new List<Side> { new Side() };
}

If you need to actually set the time to a known value, you do this:

SystemTime.Now = () => new DateTime(2013, 2, 11, 17, 41, 12);
like image 162
levelnis Avatar answered Oct 20 '22 14:10

levelnis


I agree on The SystemTime approach.

Although, I personally don't like setting the CreatedDate on the constructor, since there can be a short time lapse since you instantiate the object and when you persist it to the database. (And here I am assuming you definitely are)

You could make all your domain objects inherit from an interface like this one:

public interface ITimeStamped
{
    DateTime DateCreated { get; set; }
}

And then on the Commit method int the Context class I would do something like this to set the date for all entities that implement the interface:

foreach (var entry in ChangeTracker.Entries<ITimeStamped>()
                .Where(entry => entry.State == EntityState.Added))
            {
                entry.Entity.DateCreated = SystemTime.Now();
            }

This way you're totally certain that the entity is stored with the correct DateTime when it was persisted on the database.

like image 21
amhed Avatar answered Oct 20 '22 13:10

amhed