locked
invalid objectname - MVC Models - AspNetUser RRS feed

  • Question

  • User-1577696302 posted

    I made a script joining 2 tables in the Controller.  I already succeeded joining 3 tables, but now for this one I a getting a strange error

    I have looked everywhere for making my application work, but it is telling me that it needs a table with the name "aspnetuser1", alhtough it is aspnetuser and I did not program another table anywhere.

    I made a special file amongst the Model. Class with 2 Models together.

    namespace test.Models
    {
        public class ViewModelopmerkingen
        {
     
            public Opmerkingen opmerkingen { getset; }
            public AspNetUser aspnetusers { getset; }
     
        }
    }
    I also made a query joining the models, so the right information can combined for the user.

    public
     ActionResult Index() {     List<Opmerkingen> opmerkingens = db.Opmerkingens.ToList();     List<AspNetUser> aspnetusers = db.AspNetUsers.ToList();     var opmerkingsRecord = from e in opmerkingens                            join b in aspnetusers on e.user equals b.Email into table1                            from b in table1.ToList()                            select new ViewModelopmerkingen                            {                                opmerkingen = e,                                aspnetusers = b                            };     return View(opmerkingsRecord); }

    If I change the name of the table to AspNetUser1, then my script works, but the rest of the application is stuck.  What happened and where, I still cannot find.

    Monday, September 23, 2019 11:58 PM

All replies

  • User1120430333 posted

    IMO, the viewmodel is not being used correctly. The viewmodel should be made up of classes/objects that have nothing to do with a EF persistence object, which are independent of the persistence model. I think EF has made an AspNetJser1 to avoid a name collision  with AspNetUser in the query. The AspNetUser1 doesn't exist physically in the database.  

    Keep this in mind when architecting...

    https://www.c-sharpcorner.com/UploadFile/56fb14/understanding-separation-of-concern-and-Asp-Net-mvc/

    I view the viewmodel as a domain model. I  don't view the EF persistence model as a domain model.

    https://blog.sapiensworks.com/post/2012/04/07/Just-Stop-It!-The-Domain-Model-Is-Not-The-Persistence-Model.aspx

    So you could make the viewmodel and map EF entity data over to the viewmodel property by property with the viewmodel having EF entity in it.

    The viewmodel below was created and the EF entity properties were mapped to it.

    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    namespace PublishingCompany.Models
    {
        public class AuthorVM
        {
            public class Author
            {
                public int AuthorID { get; set; }
    
                [Required(ErrorMessage = "First Name is required")]
                [StringLength(50)]
                public string FirstName { get; set; }
    
                [Required(ErrorMessage = "Last Name is required")]
                [StringLength(50)]
                public string LastName { get; set; }
            }
    
            public List<Author> Authors { get; set; } = new List<Author>();
        }
    }
    

    Tuesday, September 24, 2019 2:09 AM
  • User-194957375 posted

    Maybe tables are in different databases? They must be in the same database.

    Tuesday, September 24, 2019 6:35 AM
  • User665608656 posted

    Hi jeronimo,

    According to your description and code , I suggest that you provide the code for db context and the detailed code for AspNetUser.cs for our reference.

    It will help us solve your issue more easily.

    Best Regards,

    YongQing.

    Tuesday, September 24, 2019 9:08 AM
  • User-1577696302 posted

    I already made this script joining 3 tables and it worked fine.  on the same database, with other tables

    Tuesday, September 24, 2019 10:02 AM
  • User-1577696302 posted

    this is AspNetUser.cs

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Web;
     
    namespace test.Models
    {
        public class AspNetUser
        {
            public string Id { getset; }
     
            [Required(AllowEmptyStrings = false)]
            public string FirstName { getset; }
     
            [Required(AllowEmptyStrings = false)]
            public string LastName { getset; }
     
            [Required(AllowEmptyStrings = false)]
            [Display(Name = "Email")]
            [EmailAddress]
            public string Email { getset; }
     
            
        }
    }
    Tuesday, September 24, 2019 10:03 AM
  • User-1577696302 posted

    this is DbContext:

    using System.Data.Entity;
    using System.Security.Claims;
    using System.Threading.Tasks;
    using Microsoft.AspNet.Identity;
    using Microsoft.AspNet.Identity.EntityFramework;
     
    namespace test.Models
    {
        // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit https://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
        public class ApplicationUser : IdentityUser
        {
            //New properties are added
            public string FirstName { getset; }
     
            public string LastName { getset; }
     
            public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
            {
                // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
                var userIdentity = await manager.CreateIdentityAsync(thisDefaultAuthenticationTypes.ApplicationCookie);
                // Add custom user claims here
                return userIdentity;
            }
        }
     
        public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
        {
            public ApplicationDbContext()
                : base("DefaultConnection", throwIfV1Schema: false)
            {
            }
     
            public static ApplicationDbContext Create()
            {
                return new ApplicationDbContext();
            }
     
            public System.Data.Entity.DbSet<test.Models.Leden> Ledens { getset; }
     
            public System.Data.Entity.DbSet<test.Models.Agenda> Agenda { getset; }
            public System.Data.Entity.DbSet<test.Models.AgendaSub> AgendaSub { getset; }
     
            public System.Data.Entity.DbSet<test.Models.Album> Albums { getset; }
     
            public System.Data.Entity.DbSet<test.Models.AspNetUser> AspNetUsers { getset; }
     
            public System.Data.Entity.DbSet<test.Models.Inschrijving> Inschrijvings { getset; }
     
            public System.Data.Entity.DbSet<test.Models.Opmerkingen> Opmerkingens { getset; }
        }
    }
    Tuesday, September 24, 2019 10:04 AM
  • User1120430333 posted

    Maybe tables are in different databases? They must be in the same database.

    Nope, like I have stated, I think EF internally made up the object to not conflict with the real named object.

    Tuesday, September 24, 2019 10:14 AM
  • User-1577696302 posted

    I think the same, although, I have another script that is working fine... combining 3 tables, also within EF

    public ActionResult Index2()
    {
        List<Inschrijving> inschrijvings = db.Inschrijvings.ToList();
        List<AgendaSub> agendaSubs = db.AgendaSub.ToList();
        List<Agenda> agendas = db.Agenda.ToList();
     
        var InschrijvingsRecord = from e in inschrijvings
                                  join b in agendaSubs on e.IdAgendaSub equals b.IdAgendaSub into table1
                                  from b in table1.ToList()
                                  join c in agendas on b.Id equals c.Id into table2
                                  from c in table2.ToList()
                                  
                                  select new ViewModel
                                  {
                                      inschrijving = e,
                                      agendasub = b,
                                      agenda = c
                                  };
        return View(InschrijvingsRecord);
    
    }
    Tuesday, September 24, 2019 10:17 AM
  • User-1577696302 posted

    and of course...

    if I rename the table aspnetuser to aspnetuser1, the script is working fine, and the view is working fine.

    But than I have the other pages that are having a problem... even f I rename the other things with a "1"

    Tuesday, September 24, 2019 10:23 AM
  • User1120430333 posted

    and of course...

    if I rename the table aspnetuser to aspnetuser1, the script is working fine, and the view is working fine.

    But than I have the other pages that are having a problem... even f I rename the other things with a "1"

    The way you are using the object in the viewmodel and involving it in a query too has got things jacked-up. Think about making a new object/class call User and populating Users with User mapped from the results of the Linq query involving ASPNetUser will solve the problem.

    Why are you even using an EF entity in a view? To me that's something that should never happen. If you were doing Seperation of Concerns properly, the controller should never be using EF directly or doing any database activity directly.

    https://en.wikipedia.org/wiki/Separation_of_concerns

    Do you see the controller doing an DB activity directly?

    using Microsoft.AspNetCore.Mvc;
    using PublishingCompany.Models;
    
    namespace PublishingCompany.Controllers
    {
        public class AuthorController : Controller
        {
            private IAuthorDM adm;
            public AuthorController(IAuthorDM authorDM)
            {
                adm = authorDM;
            }
    
            public IActionResult Index()
            {
                return View(adm.GetAll());
            }
    
            public IActionResult Detail(int id = 0)
            {
                return id == 0 ? null : View(adm.Find(id));
            }
    
            public IActionResult Create()
            {
                return View(adm.Add());
            }
    
            [HttpPost]
            public ActionResult Create(AuthorVM.Author author, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
    
                if (!ModelState.IsValid) return View(author);
    
                adm.Add(author);
                return RedirectToAction("Index");
            }
            
            public ActionResult Edit(int id = 0)
            {
                return id == 0 ? null : View(adm.Update(id));
            }
            
            [HttpPost]
            public ActionResult Edit(AuthorVM.Author author, string submit)
            {
                if (submit == "Cancel") return RedirectToAction("Index");
                            
                if (!ModelState.IsValid) return View(author);
                           
                adm.Update(author);
                return RedirectToAction("Index");
            }
            public IActionResult Delete(int id = 0)
            {
                if (id > 0) adm.Delete(id);
    
                return RedirectToAction("Index");
            }
    
            public ActionResult Cancel()
            {
                return RedirectToAction("Index", "Home");
            }
        }
    }

     https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/overview/understanding-models-views-and-controllers-cs

    An MVC model contains all of your application logic that is not contained in a view or a controller. The model should contain all of your application business logic, validation logic, and database access logic. For example, if you are using the Microsoft Entity Framework to access your database, then you would create your Entity Framework classes (your .edmx file) in the Models folder.

    A view should contain only logic related to generating the user interface. A controller should only contain the bare minimum of logic required to return the right view or redirect the user to another action (flow control). Everything else should be contained in the model.

    In general, you should strive for fat models and skinny controllers. Your controller methods should contain only a few lines of code. If a controller action gets too fat, then you should consider moving the logic out to a new class in the Models folder.

    Tuesday, September 24, 2019 10:57 AM
  • User-1577696302 posted

    Thank I have a better look at your informations.

    yes, of course, I already know about separation of concerns

    and I also know about MVC, and I program regularly with and without EF.

    But it seemed this solution worked fine even with 3 tables

    Tuesday, September 24, 2019 12:39 PM
  • User1120430333 posted

    jeronimo008

    Thank I have a better look at your informations.

    yes, of course, I already know about separation of concerns

    and I also know about MVC, and I program regularly with and without EF.

    But it seemed this solution worked fine even with 3 tables

    Well, what can I tell you. It ain't working now. And I have seen this error message you have encountered on a couple of occasions in ASP.NET forums and the MSDN EF forum. I have seen no resolution either. EF doesn't like what you're doing, and maybe you need to take another path.

    https://juristr.com/blog/2012/10/lessions-learned-dont-expose-ef-entities-to-the-client-directly/

    I app;y the above to any ORM not just EF.

    Tuesday, September 24, 2019 1:25 PM
  • User753101303 posted

    Hi,

    I suspect it happens because you add again a DbSet<AspNetUser> to your context while another one is handled already IdentityDbContext.

    What if you drop your own and try to use Users instead ? Also it seems you relate data based on an email ? What if this value is later updated or is this really what you need rather than the user id ?

    Tuesday, September 24, 2019 2:37 PM