2
\$\begingroup\$

I have an ASP.NET MVC 5 app and I map properties between model and viewmodel and vice versa.

I could use automapper to do this but since I don't need mapping rules to convince me to use it as I mostly do simple 1 to 1 mapping the performance overhead that automapper will add is not worthwhile.If I have mapping differences I'll map it manually where I reference it in my controller.

Here is my code

public class Dog
{
    public int Id { get; set; }

    public string Name { get; set; }

    public DateTime? BirthDate { get; set; }

    public int? CreatedBy{ get; set; }

    public DateTime? DateCreated { get; set; }
}

public class DogViewModel
{
    public int Id { get; set; }

    public string Name { get; set; }

    public DateTime? BirthDate { get; set; }


    public static implicit operator DogViewModel(Dog dm)
    {
        var vm= new DogViewModel{
            Id = dm.Id,
            Name = dm.Name,
            BirthDate = dm.BirthDate 
       };
        return vm;
    }

    public static implicit operator Dog(DogViewModel vm)
    {
        var dm = new Dog
        {
            Id = vm.Id,
            Name = vm.Name,
            BirthDate = vm.BirthDate 
        };
        return dm;
    }
}

This allows me to in my controller actionmethods easily map one class to another.

e.g.

  public async Task<IActionResult> Edit(int? id)
    {
        var dog= await _db.Dogs.FirstOrDefaultAsync(d => md.Id == id);
        DogViewModel dogVm = dog;
        ...

     }

    [HttpPost]
    public async Task<IActionResult> Edit(DogViewModel dogVm)
    {
       Dog dog= dogVm;
       ...
    }

In my index ActionMethod I need to map a list of items.

  public async  Task<IActionResult> Index()
    {
        var dogs = await _db.Dogs.ToListAsync();

        var dogVms = new List<DogViewModel>();
        foreach (var dog in dogs)
        {
            DogViewModel dogVm = dog;
            dogVms.Add(dogVm);
        }
        return View(dogVms);
    }

Question: Is there a way in LINQ or some other way in C# to eliminate the above foreach clause to simplify this code?

\$\endgroup\$
  • \$\begingroup\$ You crate a List<MonthViewModel>() but you are adding DogViewModels - is this correct? Is DogViewModel derived from MonthViewModel? I cannot try it out because you didn' show the MonthViewModel but I think since you have an implicit cast operator this might work _db.Months.ToListAsync().Cast<DogViewModel>().ToList(); that repaces your loop. \$\endgroup\$ – t3chb0t Oct 23 '15 at 10:25
  • \$\begingroup\$ Sorry was just a typo. I corrected it. Should read dog not month \$\endgroup\$ – devfric Oct 23 '15 at 10:59
  • \$\begingroup\$ I think your understanding of how ViewModel and Model work is not that good yet. Assigning a Model to morph into a VM is not a good practice. \$\endgroup\$ – mr5 Jun 8 '18 at 4:54
3
\$\begingroup\$

Providing

var dogVms = new List<MonthViewModel>();

is meant to actually be

var dogVms = new List<DogViewModel>();

Then to use LINQ you could do

List<DogViewModel> dogVms = (from dog in dogs select (DogViewModel)dog).ToList();
\$\endgroup\$
1
\$\begingroup\$

You could also write;

var dogVms = dogs.Select<Dog, DogViewModel>(dog => dog);

(assuming you have implicit operators)

\$\endgroup\$
  • \$\begingroup\$ Hi! Welcome to Code Review. Please explain more on why your way is better. \$\endgroup\$ – TheCoffeeCup Dec 5 '15 at 21:39
  • \$\begingroup\$ To add on to Coffee's comment: Here, we expect answers that both provide a better way and explain why those ways are better. \$\endgroup\$ – Fund Monica's Lawsuit Dec 5 '15 at 22:02
  • \$\begingroup\$ hi guys. because it's shorter and seems more elegant :) \$\endgroup\$ – Christian Götze Dec 31 '15 at 12:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.