I am a newbie to asp.net and trying to figure out a small issue and could not get through.
what I am trying is to access additional user profile details and display the first name in mylogin partial page and giving an exception, any help to shed something really appreciated.
#
{var manager = new UserManager<MyUser>(new UserStore<MyUser>(new MyDbContext ()));
**var currentUser = manager.FindById(User.Identity.GetUserId());**
var myname = currentUser.UserInfo.FirstName;
}
An exception of type 'System.InvalidOperationException' occurred in mscorlib.dll but was not handled in user code
Additional information: The specified cast from a materialized 'System.Data.Entity.DynamicProxies.ApplicationUser_19A2C4C53E8DE616853C0AA38428987A7CBBC56E57FCCF82F04E81B42A687C20' type to the 'BNTracker.Models.MyUser' type is not valid.
MyUser is already inherited from IdentityUser and its available under models
public class MyUser : IdentityUser
{
public virtual UserInfo UserInfo { get; set; }
}
public class UserInfo
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmployeeCode { get; set; }
public string Email { get; set; }
}
public class MyDbContext : IdentityDbContext<MyUser>
{
public MyDbContext()
: base("DefaultConnection")
{
//Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyDbContext>());
}
public System.Data.Entity.DbSet<UserInfo> UserInfo { get; set; }
}
Please try
var manager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(new MyDbContext ())
var currentUser = manager.FindById(User.Identity.GetUserId());
Related
I get this error (An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code
The entity type tblMessage is not part of the model for the current context.) and have tried fixes I found online but they didnt seem to help. I also did somethin similar for another database tabel earlier in the code.
Im trying to retrieve messages form my database table called tblMessages.
Constructor:
public JsonResult ConversationWithContact(int contact)
{
if (Session["UserID"] == null)
{
return Json(new {status = "error", message = "User is not logged in"});
}
//var currentUser = (Models.tblUser)Session["UserID"];
var conversations = new List<Models.tblMessage>();
using (var db = new Models.ChatContext())
{
int currentUserId = (int)Session["UserID"];
var currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);
conversations = db.Conversations.Where(c => (c.receiverId == currentUser.Id
&& c.senderId == contact) ||
(c.receiverId == contact
&& c.senderId == currentUser.Id))
.OrderBy(c => c.created_at)
.ToList();
}
return Json(
new {status = "success", data = conversations},
JsonRequestBehavior.AllowGet
);
}
Context:
public ChatContext() : base("TrinityEntities")
{
}
public static ChatContext Create()
{
return new ChatContext();
}
public DbSet<tblUser> Users { get; set; }
public DbSet<tblMessage> Conversations { get; set; }
Database model class:
public class tblMessage
{
public tblMessage()
{
status = messageStatus.Sent;
}
public enum messageStatus
{
Sent,
Delivered
}
public int Id { get; set; }
public int senderId { get; set; }
public int receiverId { get; set; }
public string message { get; set; }
public messageStatus status { get; set; }
public System.DateTime created_at { get; set; }
}
Here is issue with Table Mapping to database. each entity will be set up to map to a table with the same name as the DbSet<TEntity> property that exposes to the derived context. If no DbSet<TEntity> is included for the given entity, the class name is used.
as you set in your code Users and Conversations is not table name. for that you can customize also refere https://learn.microsoft.com/en-us/ef/core/modeling/relational/tables
and use Data Annotations for specify table name.
public messageStatus status { get; set; }
i think this property is not not part of your table column so you have to specify [NotMapped] Data Annotations.
after changes and adding Data Annotations to table context and table look likes.
public class ChatContext : DbContext
{
public ChatContext()
{
}
public virtual DbSet<tblUser> Users { get; set; }
public virtual DbSet<tblMessage> Conversations { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=test;Trusted_Connection=True;MultipleActiveResultSets=true");
}
}
}
and your models(tables) entities look like.
[Table("tblMessage")]
public class tblMessage
{
public tblMessage()
{
status = messageStatus.Sent;
}
public enum messageStatus
{
Sent,
Delivered
}
public int Id { get; set; }
public int senderId { get; set; }
public int receiverId { get; set; }
public string message { get; set; }
[NotMapped]
public messageStatus status { get; set; }
public System.DateTime created_at { get; set; }
}
[Table("tblUser")]
public class tblUser
{
public int id { get; set; }
public string name { get; set; }
}
now you can access your Conversations and Users after adding [Table("<table-name>")] Data-Annotations.
also you can use Fluent API for table mapping.
after using table mapping table after debug code image like.
i hope it helps you and let me know if require any more information. :)
I have my Accountmodels.cs class like this---
public class UsersContext : DbContext
{
public UsersContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
}
public class RegisterExternalLoginModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
public string ExternalLoginData { get; set; }
}
and my User Profile class is like this---
public class UserProfile
{
public UserProfile()
{
this.Posts = new HashSet<Post>();
}
public int UserId { get; set; }
public string UserName { get; set; }
public string AvatarExt { get; set; }
public virtual ICollection<Post> Posts { get; set; }
and finally my dbContext class is----
public class WallEntities : DbContext
{
public WallEntities()
: base("name=WallEntities")
{
}
public DbSet<Post> Posts { get; set; }
public DbSet<UserProfile> UserProfiles { get; set; }
I am using both WallEntities and DefaultConnection as name in connection string.I am using Simple Membership so i have a InitializeSimpleMembershipAttribute.cs File.Its look like this---
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<UsersContext>(null);
try
{
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}.
My Problem is that It is creating two tables in Sql server.One is UserProfile and another is UserProfiles table.I want to create only 1 table that is UserProfile table with UserId,UserName and AvatarExt Property.After registration, it should store all information.
I want to answer my question is it may be useful for someone---
Just The problem here was not to use the two DbContext.Instead of that, for the code First approach one dbContext is enough.
So, DbContext should be like this----
public class UsersContext : DbContext
{
public UsersContext()
: base("DefaultConnection")
{
}
public DbSet<Post> Posts { get; set; }
it should not be here
// public DbSet<UserProfile> UserProfiles { get; set; }
}
and romove that WallEntities DbContext. and reomove USerFrofile from UserContext as i have commented out and also change all the corresponding codes in the same way.
In my ASP.NET MVC Application, I customized the Identity to use another table for storing the users' infos such as first name, last name and birthdate. Here's the association code:
public class ApplicationUser : IdentityUser
{
public virtual UserInfo Info { get; set; }
}
public class UserInfo
{
public int Id { get; set; }
public string FirstName { get; set;
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
}
But how do you use the primary key of the ApplicationUser class as the primary key of UserInfo so that you know which user accounts the infos belong to?
The primary Key of ApplicationUser will be of a default type String, so first you will need to change your dependent class to also have a key of type string.
public class UserInfo
{
public string Id { get; set; }
public string FirstName { get; set;
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
}
Then in your IdentityDbContext implementation you will need to create a mapping to create the 1:1 relationship you are after like so.
public class MyIdentityDbContext : IdentityDbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ApplicationUser>().HasRequired(x => x.Info).WithRequiredDependent();
base.OnModelCreating(modelBuilder);
}
}
and that should work
I want to create large user table (advance User Profile) and save user's data in my database context. So, I don't want to use 2 DbContexts in my project. When users register to site, they data (UserName, Password etc.) stores my own User table. My classes are like this:
public class ModelBase
{
public int Id { get; set; }
public DateTime CreateDate { get; set; }
public DateTime LastUpdateDate { get; set; }
}
public class User : ModelBase
{
public string UserName { get; set; }
public string Password{ get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public DateTime BirthDate { get; set; }
public string Specialty { get; set; }
}
public class News : ModelBase
{
public int UserId { get; set; }
public string Title { get; set; }
...
}
....
Context is so:
public class MyDBContext : DbContext
{
public MyDBContext()
{
Database.SetInitializer<MyDBContext>(new MyDBContextInitializer());
}
public DbSet<User> UserSet { get; set; }
public DbSet<News> NewsSet { get; set; }
public DbSet<Project> ProjectSet { get; set; }
public DbSet<Section> SectionSet { get; set; }
....
}
class MyDBContextInitializer : DropCreateDatabaseIfModelChanges<MyDBContext>
{
protected override void Seed(MyDBContext context)
{
base.Seed(context);
}
}
I replaced DbContext name with mine and changed connection name in default SimpleMembershipInitializer class like this:
....
Database.SetInitializer<MyDBContext>(null);
try
{
using (var context = new MyDBContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection("MyDBContextConnection", "User", "Id", "UserName", autoCreateTables: true);
....
Finally, I changed RegisterModel and WebSecurity.CreateUserAndAccount() suitable my User class. But, it does not work.
How can I use my own User table for register to site?
You can have Asp.net Membership and your complex classes connected together.
with this approach you will save so much time because asp.net membership is much more robust(you don't need to think about Role and User management) and sure you can make use of existing open source project like this and add it to your project with minimum effort of time.
Then your class will have structure like :
public class CustomUserDetail : ModelBase
{
public string UserName { get; set; } // what you really need is this to be unique for each user in you data base
// public string Password{ get; set; } handled by asp.net Membership
public string FullName { get; set; }
// public string Email { get; set; } handled by asp.net Membership
public DateTime BirthDate { get; set; }
public string Specialty { get; set; }
}
Then you can can add extension method to IPrincipal like :
public static CustomUserDetail CustomUserDetail (this IPrincipal principal)
{
var repository = new YourUserDetailRepository();
return repository.GetCurrentUserDetail();
}
and finnaly in your code easily use
<p> #User.CustomUserDetail.FullName </p>
I'm working on my first MVC 4 app, following the MVC First Web API Tutorial on Asp.net. I've left the names the same, but changed the model and controller code. Here's my model:
public class Product
{
public string SID { get; set; }
public string name { get; set; }
public string givenName { get; set; }
public string sn { get; set; }
public string mail { get; set; }
public string telephoneNumber { get; set; }
public string mobile { get; set; }
public string otherMobile { get; set; }
public string title { get; set; }
public string Manager { get; set; }
public DateTime whenChanged { get; set; }
}
public class ProductModel
{
public ProductModel()
{
ProductList = new List<Product>();
}
public IList<Product> ProductList { get; set; }
}
And here's my APIcontroller:
public class ProductsController : ApiController
{
ProductModel products = new ProductModel();
public IEnumerable<Product> GetAD()
{
DirectoryEntry domainRoot = new DirectoryEntry(LDAP_server);
DirectorySearcher searcher = new DirectorySearcher(searchStr);
SearchResultCollection results = searcher.FindAll();
foreach (SearchResult srchResult in results)
{
DirectoryEntry dirEntry = srchResult.GetDirectoryEntry();
if (dirEntry.Properties["givenName"].Value != null && dirEntry.Properties["sn"].Value != null && !dirEntry.Parent.Name.Contains("Terminated"))
{
products.ProductList.Add(new Product()
{
SID = dirEntry.Properties["sid"].Value.ToString(),
name = dirEntry.Properties["name"].Value.ToString(),
givenName = dirEntry.Properties["givenName"].Value.ToString(),
sn = dirEntry.Properties["sn"].Value.ToString(),
mail = dirEntry.Properties["mail"].Value.ToString(),
telephoneNumber = dirEntry.Properties["telephoneNumber"].Value.ToString(),
mobile = dirEntry.Properties["mobile"].Value.ToString(),
otherMobile = dirEntry.Properties["otherMobile"].Value.ToString(),
title = dirEntry.Properties["title"].Value.ToString(),
Manager = dirEntry.Properties["Manager"].Value.ToString(),
whenChanged = Convert.ToDateTime(dirEntry.Properties["whenChanged"].Value.ToString()),
});
}
}
return products.ProductList;
}
}
I'm getting the NullException on 'products.ProductList.Add(new Product()', am I missing something simple? Please forgive my coding, as I'm just trying to get this up and running, thanks.
the problem mostly likely is dealing with dirEntry, not Web API itself. rather than introduce LDAP into this, just create a bunch of dummy products to return.
FYI... there is also a memory leak issue with the use of LDAP objects. They need to be properly disposed of, both along the happy path and if an exception is thrown.
I'm an idiot. 'sid' is not the correct property name from AD, it is 'objectSid', thus always returning a null. I knew it was something simple.