TykiMikk
TykiMikk

Reputation: 1068

Binding Enums in Viewmodels to MVC

Whenever I try to create a ticket my ticket priority is also LOW. I've setup a drop down list for Priority but the assignment of priorities on Tickets doesn't seem to be working. I'm suspecting it has to do with my Views\Ticket\Create.cshtml

I need some clarifications to see if I'm doing this correctly:

Do I need both

In my models I have a class called Ticket and it has enum Priority

public enum Priority
{
    Low, Med, High
}
public class Ticket
{
  ....
}

Configuration.cs (snippet for inserting ticket data)

var tickets = new List<Ticket>
{
    new Ticket {
        UserID = users.Single(s => s.LastName == "Wan").UserID,
        CategoryID = categories.Single(c => c.CategoryName == "Con-X" ).CategoryID,
        Issue = ("Con-X Login Error"),
        Priority = Priority.High
    },
    new Ticket {
        UserID = users.Single(s => s.LastName == "Wan").UserID,
        CategoryID = categories.Single(c => c.CategoryName == "Desktop" ).CategoryID,
        Issue = ("Can't remote access C0123"),
        Priority = Priority.Med
    },
};

In my viewmodel TicketVM I've also setup enum for Priority as well. Since I'm configuring my tickets through this:

            Ticket ticket = new Ticket
            {
                UserID = (int)WebSecurity.CurrentUserId,
                Issue = model.Issue,
                IssuedTo = model.IssuedTo,
                CategoryID = model.CategoryID,
                Priority = model.priority <-- ERROR
            };

Error:

Cannot implicitly convert type 'RecreationalServicesTicketingSystem.ViewModels.TicketVM.Priority' to 'RecreationalServicesTicketingSystem.Models.Priority'. An explicit conversion exists (are you missing a cast?) RecreationalServicesTicketingSystem

Views\Ticket\Create.cshtml

    <div class="form-group">
        @Html.DropDownListFor(m => m.priority, Model.PriorityList, "Please select the priority") 
    </div>

ViewModels\TicketVM.cs

public class TicketVM
{
    public int UserID { get; set; }
    [Required(ErrorMessage = "Please enter the description")]
    public string Issue { get; set; }
    [Display(Name = "Administrator")]
    [Required(ErrorMessage = "Please select the Administrator")]
    public int IssuedTo { get; set; }
    public IEnumerable<SelectListItem> AdministratorList { get; set; }
    public int CategoryID { get; set; }
    public IEnumerable<SelectListItem> CategoryList { get; set; }

    public enum Priority
    {
        LOW = 3,
        MED = 2,
        HIGH = 1,
    }

    public Priority priority { get; set; }
    public IEnumerable<SelectListItem> PriorityList
    {
        get
        {
            var priorityType = typeof(Priority);
            var priorityValues = Enum.GetValues(priorityType).Cast<Priority>();
            var converter = TypeDescriptor.GetConverter(priorityType);

            return
                from priorityValue in priorityValues
                select new SelectListItem
                {
                    Text = converter.ConvertToString(priorityValue),
                    Value = priorityValue.ToString(),
                };
        }
    }
}

TicketController.cs

public ActionResult Create()
{
    TicketVM model = new TicketVM();
    ConfigureViewModel(model);
    return View(model);
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(TicketVM model)
{
    if (!ModelState.IsValid)
    {
        model.CategoryList = new SelectList(db.Categories, "CategoryID", "CategoryName");
        ConfigureViewModel(model);
        return View(model);
    }
    Ticket ticket = new Ticket
    {
        UserID = (int)WebSecurity.CurrentUserId,
        Issue = model.Issue,
        IssuedTo = model.IssuedTo,
        CategoryID = model.CategoryID,
        Priority = model.priority <-- ERROR
    };
    db.Tickets.Add(ticket);
    db.SaveChanges();
    return RedirectToAction("Index");
}

private void ConfigureViewModel(TicketVM model)
{
    IEnumerable<User> admins = db.Users.Where(u => u.IsAdministrator).OrderBy(u => u.LastName);
    model.AdministratorList = admins.Select(a => new SelectListItem
    {
        Value = a.UserID.ToString(),
        Text = string.Format("{0} {1}", a.FirstMidName, a.LastName)
    });
    IEnumerable<Category> categories = db.Categories.OrderBy(u => u.CategoryName);
    model.CategoryList = categories.Select(a => new SelectListItem
    {
        Value = a.CategoryID.ToString(),
        Text = a.CategoryName.ToString()
    });
}

Upvotes: 2

Views: 10422

Answers (3)

user3559349
user3559349

Reputation:

The enums in your Ticket model and TicketVM model are not the same.

One option would be to add a using statement in TicketVM so that you use the enum from RecreationalServicesTicketingSystem.Models (and delete the enum definition in your TicketVM class)

@using RecreationalServicesTicketingSystem.Models
public class TicketVM
{
    ....
    public Priority priority { get; set; } // uses the enum from the Models assembly
}

Another option would be to cast from one to the other. Since you need this inside a object initializer, create a private method in the controller to cast the value

private Models.Priority CastPriority(ViewModels.TicketVM.Priority value)
{
    Models.Priority priority = Models.Priority.Low;
    Enum.TryParse<Models.Priority>(value.ToString(), out priority);
    return priority;
}

and inside the object initializer

Ticket ticket = new Ticket
{
    ....
    CategoryID = model.CategoryID,
    Priority = CastPriority(model.priority)
};

Side note: You can simplify the code for generating the IEnumerable<SelectListItem> to

public IEnumerable<SelectListItem> PriorityList
{
    get
    {
        return Enum.GetNames(typeof(Proprity)).Select(e => new SelectListItem() { Text = e, Value = e });
    }
}

Upvotes: 2

Ivan Gritsenko
Ivan Gritsenko

Reputation: 4236

There is no need in another Priority enum in your ViewModel. Just use one from your models adding a corresponding using reference.

However if you still need to assign a value of one enum to a variable of another do it like this Priority=(int)model.priority.

Note that you model Priority has Low=0,Med=1, High=2 while view model LOW = 3, MED = 2, HIGH = 1.

Upvotes: 1

esiprogrammer
esiprogrammer

Reputation: 1438

it seems that you have two different enum type of priority, TicketVM.Priority& Models.Priority and the error message indicates that system can't implicitly convert these two types.

you could define only one enum type and use it everywhere in your code therefore you don't need enum conversion

Upvotes: 1

Related Questions