Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to design a fall back for ObjectContext disposed in .NET MVC

I'm trying to display a property of an object in my view if it exists, otherwise fall back to a default value e.g.

@if(Product.Description != null && Product.Description.Color != null){
    <li>@Product.Description.Color</li>
}

The problem with this is that if I do the null checking in the view, the ObjectContext has been disposed for Product.Description if it doesn't exist and an exception is thrown.

Should I assign a default value/ fall back in my controller or is there a way to handle this in the view?

like image 984
user2865446 Avatar asked Dec 20 '22 06:12

user2865446


2 Answers

Don't ever send a "live" object to the view. If you do that, you are effectively mixing the UI and data layers. Remember that the controller has finished executing by the time the view is rendered.

Instead, send a copy, with the properties you need to use in the view.

I know that some books suggest that the "M" in MVC stands for "Domain Model" and they suggest that this should be an instance of, for instance, an Entity Framework entity. I disagree, and feel that mixes responsibilities.

I have had good luck with the "AutoMapper" tool, which makes it simple to map from the properties of an EF entity and those of the model you use in the view (the ViewModel).

like image 77
John Saunders Avatar answered Apr 13 '23 00:04

John Saunders


As John mentioned in the comments, the following is typically frowned upon:

public ActionResult Index()
{
  var db = new MyDbContext();

  var model = db.Products.FirstOrDefault();

  return View(model);
}

Instead, dispose of the context properly while mapping values to a view model(s):

public ActionResult Index()
{
  var model = new IndexVM();

  using (var db = new MyDbContext())
  {
    // Assuming EF
    var dbProduct = db.Products.FirstOrDefault();
    // Even better performance:
    var dbProduct = db.Products
      // prevent lazy loading
      .Include(p => p.Description.Color)
      .FirstOrDefault()
      // prevent ef tracking with proxy objects
      .AsNoTracking();

    // can be automated with AutoMapper or other .Net Components
    ProductVM productVM = new ProductVM();
    productVM.Id = dbProduct.Id;
    // etc

    // Don't put logic in View:
    productVM.HasDescription = (product.Description != null);
    if (productVM.HasDescription)
    {
       var descriptionVM = new DescriptionVM();
       // map values
       productVM.Description = descriptionVM;
    }

    model.Product = productVM;
  }

  return View(model);
}

Now the view isn't really doing logic per-se:

@if(product.HasDescription && product.Description.HasColor){
  <li>@Product.Description.Color</li>
}
like image 27
Erik Philips Avatar answered Apr 12 '23 23:04

Erik Philips