I'm using the MVC4 Internet Application and I am trying to change the account model to use my context. I cannot seem to get it to work. I tried to delete the context and include the user profile in my context and I could log on etc but when I check for profiles by user id it returns a null value.
public DbSet<FightCard> FightCards { get; set; }
public DbSet<Fight> Fights { get; set; }
public DbSet<Fighter> Fighters { get; set; }
public DbSet<UserProfile> UserProfiles { get; set; }
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
When I try to do this:
public ActionResult Profile(int id)
{
UserProfile profile = uc.UserProfiles.Find(id);
ViewBag.Name = profile.UserName;
}
I get a null value return. Anyone know how to successfully use the simple membership with a different context?
Solved it there. But to be honest I'm not exactly sure what fixed it. Here is the link I used and one part of it solved my problem.
http://dansgreenshoes.com/2013/03/10/mvc4usertable/
Related
I am using ASP.NET Core 6 to make a simple Blog website.
I have the 2 following classes:
AppUser.cs
public class AppUser : IdentityUser
{
public ICollection<Blog>? Blogs { get; set; }
public string? Name { get; set; }
}
Blog.cs
public class Blog
{
public int ID { get; set; }
public string Title { get; set; }
public string UserID { get; set; }
}
}
Below is suppose to get the current users info when creating a blog:
public async Task<IActionResult> OnPostAsync()
{
var user = await _userManager.GetUserAsync(User);
Blog.UserID = user.Id;
if (!ModelState.IsValid)
{
return Page();
}
_context.Blog.Add(Blog);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
For some reason, the ModelState is not valid when attempting to create the new Blog.
When I print to console the Blog.UserID and Blog.Title I get the correct data, but it still does not work.
Potentially unrelated, but the table Entity Framework made for the Blog is:
Which I also don't understand why there is a UserID and AppUserId column.
Any help would be greatly appreciated!
Update
I seem to have fixed it by making the UserID a nullable field.. I'm not sure if that is ideal...
First, for your ModelState problem. I recommend you to check this ModelState.IsValid.Question
And another problem is "Which I also don't understand why there is a UserID and AppUserId column."
I think you would like to use Navigation Property.
So you should change your entities like;
public class AppUser : IdentityUser
{
public string Name { get; set; }
public ICollection<Blog> Blogs { get; set; }
}
public class Blog
{
public int Id { get; set; }
public string Title { get; set; }
public string AppUserId { get; set; }
public AppUser AppUser {get;set;}
}
I'm using EF Core with ASP Core 2.0. Using latest Identity framework. I get this exception on page All.
InvalidOperationException: The property 'User' is not a navigation property of entity type 'Gallery'. The 'Include(string)' method can only be used with a '.' separated list of navigation property names.
ApplicationUser looks like:
public class ApplicationUser : IdentityUser<Guid>
{
public ICollection<Gallery> Galleries { get; set; }
}
Entity Gallery looks like:
public class Gallery
{
public int Id { get; set; }
public Guid UserId { get; set; }
public string Title { get; set; }
public int? ArticleId { get; set; }
public string Photos { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public Article Article { get; set; }
public ApplicationUser User { get; set; }
[NotMapped]
public List<string> PhotosList
{
get { return Photos?.Split('|').ToList(); }
set { Photos = string.Join("|", value); }
}
}
Controller for View looks like:
public async Task<IActionResult> All()
{
var databaseContext = db.Galleries.Include(x => x.Article).Include(x => x.User);
return View(await databaseContext.ToListAsync());
}
I have no idea why it dont crash on Article..
Database is up-to-date.
add a ForeignKey attribute
using System.ComponentModel.DataAnnotations.Schema;
...
[ForeignKey("Article")]
public int? ArticleId { get; set; }
[ForeignKey("User")]
public Guid UserId { get; set; }
You can also put the attribute on the navigation property
[ForeignKey("UserId")]
public ApplicationUser User { get; set; }
Also, make sure your dbContext inherits from IdentityDbContext<ApplicationUser, ...>
You can run into this if you manually add extra properties to Models.
To troubleshoot it, run SQL Profiler and capture the RAW SQL, execute the SQL against the database and see why the query doesn't work, ie which property 'x' is not a navigation property of entity type 'y'.
Then go to the model and remove the extra property you added manually.
PS: If you don't have a SQL dB you can use another profiler. Alternatively just check the diffs in source control.
I have a UserRoles table with just two columns userId and RoleId and entityframework doesn't bring that class in. How can save the association without the userroles class?
my users and roles classes in EntityFramework are like this.
public partial class aspnet_Users
{
public aspnet_Users()
{
this.aspnet_Roles = new HashSet<aspnet_Roles>();
}
public System.Guid ApplicationId { get; set; }
public System.Guid UserId { get; set; }
public string UserName { get; set; }
public string LoweredUserName { get; set; }
public string MobileAlias { get; set; }
public bool IsAnonymous { get; set; }
public System.DateTime LastActivityDate { get; set; }
public virtual aspnet_Applications aspnet_Applications { get; set; }
public virtual aspnet_Membership aspnet_Membership { get; set; }
public virtual ICollection<aspnet_Roles> aspnet_Roles { get; set; }
}
public partial class aspnet_Roles
{
public aspnet_Roles()
{
this.aspnet_Users = new HashSet<aspnet_Users>();
}
public System.Guid ApplicationId { get; set; }
public System.Guid RoleId { get; set; }
public string RoleName { get; set; }
public string LoweredRoleName { get; set; }
public string Description { get; set; }
public virtual aspnet_Applications aspnet_Applications { get; set; }
public virtual ICollection<aspnet_Users> aspnet_Users { get; set; }
}
EF doesn't give me UserRoles class in model but it shows up in XML.
when i try to add a new user, i am accessing like this
var role = new Data.aspnet_Roles();
role.RoleId = userItem.roles.First().RoleId;
role.RoleName = userItem.roles.First().RoleName;
user.aspnet_Roles.Add(role);
This gives a error
InnerException {"Cannot insert duplicate key row in object 'dbo.aspnet_Roles' with unique index 'aspnet_Roles_index1'.\r\nThe statement has been terminated."} System.Exception {System.Data.SqlClient.SqlException}
the answer here suggest that it should work. i cant figure out what i am doing wrong.
Entity Framework Add User to Role
It also makes sense that i get this error. But I am clueless on how else i can store the userroles relationship without having userroles EF class. I am really stuck. Any help is appreciated. Thank you.
The way you are doing this job, you are creating a new role with the same id and name that exists in database now, because you are using an instance of role that doesn't exists in context and this way, context thinks it is a new role and should be added.
You should inform the context that this is not a new role, to do so:
you can load the role you need, using a query, into the same context that you will use to save user
or you can attach (entry) the role object to the same context that you will use to save user, and set its state to unchanged.
For example you can first find the role yo want:
var db= new YourContext();
var role = db.aspnet_Roles.Where(....).FirstOrDefault();
then using that instnace of role and that instance of context:
user.aspnet_Roles.Add(role);
db.SaveChanges();
I walked through a couple of tutorials and it seems they all leave out how you can utilize the logged in user to store information to a database. To help me illustrate my point, here is a model I've been using.
public class Note
{
public int ID { get; set; }
public int UserId { get; set; }
public string Text { get; set; }
}
This each user can write a note to the database. When I created the CRUD controller for this model I then updated the UserId property to the WebSecurity.CurrentUserId when doing Update/Create. Then when retrieving data back I filter the notes using Where in the linq expression. For some reason this just feels wrong.
Trolling through even more examples I came across someone doing it like so.
public class Note
{
public int ID { get; set; }
public virtual UserProfile User { get; set; }
public string Text { get; set; }
}
public class NoteDbContext : DbContext
{
public DbSet<Note> Notes { get; set; }
}
This looks a lot cleaner since the models are properly linked in C#. And wow, it actually builds! So now in my controller I will first get the user object from the database, then using a Where list their notes.
//First get the logged in user
var user = dbUser.UserProfiles.Where(x => x.UserId == WebMatrix.WebData.WebSecurity.CurrentUserId).First();
//Now get all their notes
var notes = db.Notes.Where(x => x.User == user);
However, this unexpectedly fails. So could someone please provide a sample of a good way to store the UserProfile object against other objects in the database? Basically, I just need a good example that shows now the UserProfile object can be linked to a Note object, and how you should properly query for Notes of a specific UserId.
The way you've defined your relationship, is that you are creating a one-to-one relationship between a Note and a User. I would expect that a user can have multiple notes, based on the query that you're having trouble with. Thus, in order to create a one-to-many between a user and their notes, you should create a collection on your UserProfile object. For instance,
public class UserProfile
{
...
public List<Note> Notes {get; set;}
}
...and to query, loading your Notes associated with that user,
var user = myUsers.Include(n=>n.Notes)
.Single(x => x.UserId == WebMatrix.WebData.WebSecurity.CurrentUserId);
Each user can have many notes, right? If so, change your class like this:
public class Note
{
public int ID { get; set; }
public int UserId { get; set; }
public string Text { get; set; }
public virtual UserProfile User { get; set; }
}
[Table("UserProfile")]
public class UserProfile
{
public UserProfile()
{
this.Notes = new HashSet<Note>();
}
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public virtual ICollection<Note> Notes{ get; set; }
}
Now, have users and notes connecting correctly. So, you can easily achive your goal like the following. You also don't need to struggle with WebMatrix.WebData.WebSecurity to get the current user! just use User.Identity.Name :
// ...
var notes = db.Notes.Where(x => x.User.UserName == User.Identity.Name).AsQueryable();
I'm working on a EF5 code-first database and it is giving me a lot of trouble on a foreign key. Also sorry if this is already answered somewhere else but I looked at countless of questions on here already and none helped so far.
I have this user class
public class User
{
[Key()]
[HiddenInput(DisplayValue=false)]
public int UserId { get; set; }
[Required]
public string Username { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[ScaffoldColumn(false)]
public CustomClass Custom { get; set; }
}
And this custom class
public class CustomClass
{
[Key()]
[HiddenInput(DisplayValue = false)]
public int CustomClassId { get; set; }
[Required]
public string Name { get; set; }
}
And this DataContext
public class SilkDbContext3 : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<CustomClass> CustomClasses { get; set; }
}
Now, the problem is I can save a PoseAnimation perfectly through the controller. I can also post and update an user with the basic properties (Username, Password), but when I add a custom class to the user, it saves it as a foreign key in the database row, but when I want to retrieve the user, the dbcontext just gives me back null for the custom class (whether I'm retrieving through GET or intellisense). Can anyone help me out here?
You'll need to either explicitly or eagerly load the related data, or mark the Custom property as virtual if you're using lazy loading.