locked
Navigation Properties null exception MVC Model RRS feed

  • Question

  • Hello, I try to add new entity in database in controller action.
    This is my model class

    public class Product
    {
        public int ProductID { get; set; }
    
        [Required(ErrorMessage = "Please enter product name")]
        public string Name { get; set; }
    
        [Required(ErrorMessage = "Please enter product model")]
        public string Model { get; set; }
    
        [Required(ErrorMessage = "Please enter product serial")]
        public string Serial { get; set; }
    
        [Required(ErrorMessage = "Please choose dealer")]      
        public int DealerID { get; set; }
    
        [Required]        
        public Guid ClientID { get; set; }
    
        [Required(ErrorMessage = "Please choose employee")]
        public Guid EmployeeID { get; set; }
    
        public virtual Dealer Dealer { get; set; }
        public virtual Client Client { get; set; }
        public virtual Employee Employee { get; set; }
    
        [DisplayName("Commercial use")]
        public bool UseType { get; set; }
    }

    Model has virtual properties,as you see.  I know that i have to allocate memory for using this Model.

    When i try to use this model without manually allocation i get NullReference Exception in my Controller Action.

    BUT if i use ViewModel like code below

    public class ProductViewModel
    {
        public Product Product { get; set; }
    }

    I don't have any exceptions and it works without manually allocation memory. I don't understand it. Maybe EF allocate memory somehow?

    Just in case:

    This is my Controller Actions code

     public ViewResult Create()
     {
            PopulateDropDownLists();
            var model = new Product();
            return View(model);
     }
    
     [HttpPost]
     public ActionResult Create(Product model)
     {
         try
         {
             if (ModelState.IsValid)
             {
                 _repo.GetRepository<Product>().Add(model);
                    _repo.Save();
                    TempData["message"] = "Product was successfully created";
                    return RedirectToAction("List");
                }
            }
            catch (DataException)
            {
                TempData["error"] =
                    "Unable to save changes. Try again, and if the problem persists, see your system administrator.";
                return View("Error");
            }
    
            PopulateDropDownLists();
            return View("Create");
        }

    Can you explain me why this is so? cause i can't sleep anymore))

    Thanks in advance 

    • Moved by CoolDadTx Tuesday, December 3, 2013 6:26 PM EF related
    Monday, December 2, 2013 7:35 PM

Answers

  • You are mixing up POCOs and ViewModels.  They are different things.  If you're using most sample code that you'll see online then you'll often see the POCOs in EF being used directly as the view models.  This is a convenience in most cases but starts to fall apart for any reasonably complex project.

    Product is a POCO.  You would use it in EF to get and set data.  By marking the properties as virtual you are allowing EF to handle the loading of the property based upon the data that is being retrieved.  For example if you load a Product from the database and the database has a relationship between the products table and the dealers table and the specific product has a dealer value in the database then EF can load the dealer information as well.  It can still be null (if the database column were null or this was a new product). 

    ProductViewModel is a view model designed to be used in MVC.  It should expose to the view the properties that the view wants to display (not necessarily all the views).  In general you should not simply add your POCO object to the view model as you just defeated the purpose of the view model.  A view model should, in general, flatten the data to be displayed so the view is referencing nothing but simple properties.  The view should not know or care about the underlying database design (but your POCO does).

    MVC is pretty flexible when working with data so null properties won't generally cause it a problem unless you reference an object (i.e. Model.Product.ProductID when Product is null).    However, as already mentioned, you shouldn't have that sort of hierarchy in most cases.  Modify your ProductViewModel to directly expose the core properties that the view needs to display (ID, Name, Serial, etc).  If you need to display child property info then flatten the hierarchy so the view doesn't care (i.e. DealerName, DealerId, etc).  You can create a mapping class (or use an auto mapper) to handle the mapping between POCO and view model. 

    As a final note, data annotations related to the display of data should be placed on the view model (required, error messages, etc).  POCOs should have the annotations associated with data storage (key, column name, etc).  It is fine to have some annotations on both (required, string length) but it can introduce maintenance issues.

    Michael Taylor
    http://msmvps.com/blogs/p3net

    • Marked as answer by Fred Bao Tuesday, December 10, 2013 7:15 AM
    Tuesday, December 3, 2013 6:25 PM

All replies

  • Hi Alinaish,

    I think this thread is specific to ASP. NET forum. This form is to discuss problems about CLR development. Please post a new thread on that forum for more effective response. http://forums.asp.net/.

    Thank you for your understanding.

    Best Regards,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, December 3, 2013 5:47 AM
  • You are mixing up POCOs and ViewModels.  They are different things.  If you're using most sample code that you'll see online then you'll often see the POCOs in EF being used directly as the view models.  This is a convenience in most cases but starts to fall apart for any reasonably complex project.

    Product is a POCO.  You would use it in EF to get and set data.  By marking the properties as virtual you are allowing EF to handle the loading of the property based upon the data that is being retrieved.  For example if you load a Product from the database and the database has a relationship between the products table and the dealers table and the specific product has a dealer value in the database then EF can load the dealer information as well.  It can still be null (if the database column were null or this was a new product). 

    ProductViewModel is a view model designed to be used in MVC.  It should expose to the view the properties that the view wants to display (not necessarily all the views).  In general you should not simply add your POCO object to the view model as you just defeated the purpose of the view model.  A view model should, in general, flatten the data to be displayed so the view is referencing nothing but simple properties.  The view should not know or care about the underlying database design (but your POCO does).

    MVC is pretty flexible when working with data so null properties won't generally cause it a problem unless you reference an object (i.e. Model.Product.ProductID when Product is null).    However, as already mentioned, you shouldn't have that sort of hierarchy in most cases.  Modify your ProductViewModel to directly expose the core properties that the view needs to display (ID, Name, Serial, etc).  If you need to display child property info then flatten the hierarchy so the view doesn't care (i.e. DealerName, DealerId, etc).  You can create a mapping class (or use an auto mapper) to handle the mapping between POCO and view model. 

    As a final note, data annotations related to the display of data should be placed on the view model (required, error messages, etc).  POCOs should have the annotations associated with data storage (key, column name, etc).  It is fine to have some annotations on both (required, string length) but it can introduce maintenance issues.

    Michael Taylor
    http://msmvps.com/blogs/p3net

    • Marked as answer by Fred Bao Tuesday, December 10, 2013 7:15 AM
    Tuesday, December 3, 2013 6:25 PM