How to add more fields to ASP.NET Core Identity? - asp.net-core

I am using .NET 5 - version 5.0.100-rc.1.20452.10 .
I customized table AspNetUsers success, by this way
using Microsoft.AspNetCore.Identity;
using System;
namespace shadow.Models
{
public class ApplicationUser : IdentityUser
{
public string Fullname { get; set; }
public string AliasName { get; set; }
public string SecondMobile { get; set; }
public string About { get; set; }
public string Avatar { get; set; }
public DateTime? Created { get; set; }
public DateTime? Modified { get; set; }
}
}
and
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using shadow.Models;
namespace shadow.Data
{
public partial class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
{
}
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
public virtual DbSet<ApplicationUser> ApplicationUsers { get; set; }
I am looking for a similar solution with table AspNetRoles. I need add filed Description to table AspNetRoles, how to archive this? Please guide me how to make change in ApplicationDbContext.
My effort: I tried
using Microsoft.AspNetCore.Identity;
namespace shadow.Models
{
public class ApplicationRole : IdentityRole
{
public string Description { get; set; }
}
}
but error
I feel hard when decare ApplciationRole to ApplicationDbContext

As we can see in the sourcecode Microsoft.AspNetCore.Identity.EntityFrameworkCore does not have a class for IdentityDbContext<TUser, TRole>. It has classes IdentityDbContext<TUser> and IdentityDbContext<TUser, TRole, TKey>. Hence, as described in point 5 of documentation
If a custom ApplicationRole class is being used, update the class to inherit from IdentityRole. For example:
using System;
using Microsoft.AspNetCore.Identity;
public class ApplicationRole : IdentityRole<Guid>
{
public string Description { get; set; }
}
Update ApplicationDbContext to reference the custom ApplicationRole class. For example, the following class references a custom ApplicationUser and a custom ApplicationRole:
using System;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
public class ApplicationDbContext :
IdentityDbContext<ApplicationUser, ApplicationRole, Guid>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
Where the last parameter Guid above is the type of the primary key for users and roles, as described here

Related

AutoMapperMappingException: Missing type map configuration or unsupported mapping IN .NET 6

I have this entity:
public class Genres
{
public int Id { get; set; }
[Required(ErrorMessage ="the field {0} is required")]
[StringLength(50)]
[FirstLetterUpperCase]
public string Name { get; set; }
}
And this DTO or model:
public class GenresDTO
{
public int Id { get; set; }
public string Name { get; set; }
}
I have initiated my mapper like this:
public class AutoMapperClass : Profile
{
public AutoMapperClass()
{
generateMapper();
}
private void generateMapper()
{
CreateMap<GenresDTO, Genres>().ReverseMap();
CreateMap<GenresCreationDTO, Genres>();
}
}
I have also written this part of code in my program.cs :
builder.Services.AddAutoMapper(typeof(IStartup));
I am using .NET 6 and Visual Studio, and when I run my project, I get an error that is mentioned in the title and its related to this section :
public async Task<ActionResult<List<GenresDTO>>> Get()
{
var genres = await dbContext.Genres.ToListAsync();
return mapper.Map<List<GenresDTO>>(genres);
}
which is in my Controller file, and I initiated the mapper like this :
private readonly ILogger<GenresController> ilogger;
private readonly ApplicationDBContext dbContext;
private readonly IMapper mapper;
public GenresController(ILogger<GenresController> ilogger,
ApplicationDBContext dbContext , IMapper mapper)
{
this.ilogger = ilogger;
this.dbContext = dbContext;
this.mapper = mapper;
}
Should be probably typeof(Program) in registration (assuming that you are using .Net6 where we have only Program.cs)
builder.Services.AddAutoMapper(typeof(Program))
If you have multiple projects in solution,then value used there should be a file in the assembly in which the mapping configuration resides.

Problem with DbContext prop on asp net core 2.1

I have created an api in asp net core 2.1 and I have three layers inside it (PwP.Web).
In the layer (PWP.DomainClasses) I defined a class with the following specifications and in the layer (PWP.DataLayer) a class called PWPDbContext and inside it I want to define the user class as prop but it warns and is not used, how this Solve the problem?
User.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace PWP.DataLayer.User
{
public class User
{
[Key]
[Required]
public int UserId { get; set; }
[Required]
[MaxLength(50)]
public string UserName { get; set; }
[Required]
[MaxLength(32)]
public string Password { get; set; }
[Required]
[MaxLength(150)]
public string Email { get; set; }
[MaxLength(200)]
public string imageAddress { get; set; }
//
public virtual UserInfo.UserInfo UserInfo { get; set; }
}
}
PWPContext.cs:
using Microsoft.EntityFrameworkCore;
using PWP.DomainClasses.user;
namespace PWP.DataLayer.Context
{
class PWPDbContext:DbContext
{
public PWPDbContext(DbContextOptions<PWPDbContext> options): base(options)
{
}
public DbSet<User> Users { get; set; }
public DbSet<UserInfo> UserInfos { get; set; }
public DbSet<Document> Documents { get; set; }
public DbSet<Expertise> Expertises { get; set; }
public DbSet<Message> Messages { get; set; }
public DbSet<Record> Records { get; set; }
public DbSet<STFile> STFiles { get; set; }
}
}
From this line of code:
public virtual UserInfo.UserInfo UserInfo { get; set; }
It can be seen that you named the class with the exact same name as it's namespace.
You should differentiate between them.
Don't (!) do that:
namespace UserInfo
{
public class UserInfo
{
}
}

In EF Code First, How to have ApplicationUser UserId as foreign key in a custom entity?

My Custom Entity:
public class Order
{
[Key,Column(Order=0)]
public int OrderId { get; set; }
//Other properties
public string UserId { get; set; }
[ForeignKey("UserId")]
public virtual ApplicationUser User { get; set; }
}
ApplicationUser Class:
public class ApplicationUser : IdentityUser
{
//one to many relation
public virtual List<Sandwich.Order>Order { get; set; }
public async Task<ClaimsIdentity>
GenerateUserIdentityAsync(UserManager<ApplicationUser> manager){..}
}
I have two DbContexts (One default of AppUser and One I created):
public class ADbContext : DbContext
{
public ADbContext() : base("DefaultConnection")
{
}
public DbSet<Toppings> ToppingsDbset { get; set;}
//I had to comment the line below to in order to work with ToppingDBset but then I can't work with OrderDBSet
//public DbSet<Order> OrderDbSet { get; set; }
}
//Default AppDbContext
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
When I run it just working with ApplicationDbContext it works fine and creates following table with all the relationships.
enter image description here
My problem: is when I try to work with ADbContext with un-commented public DbSet<Order> OrderDbSet { get; set; }
{"One or more validation errors were detected during model generation:\r\n\r\n.IdentityUserLogin: : EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType.\r\n.IdentityUserRole: : EntityType 'IdentityUserRole' has no key defined
Solutions I tried:
//Adding following method on ADbContext
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
}
I am trying to have all tables created in one Database. I am using EF6.
try this in OnModelCreating(DbModelBuilder modelBuilder):
modelBuilder.Entity()
.HasMany(c => c.Order)
.WithOne(e => e.ApplicationUser);
refrence
Solved :
In DbContext file, I added OrderDbSet within ApplicationDbContext class
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<Order> OrderDbset { get; set; }
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
}

ADO.NET Entity Framework on Vs2012 + WCF = Error

First of all, thanks for reading my question.
I am developing a solution using VS 2012 using ADO.NET Entity Framework (5 i think, the latest version). All is working fine until I introduce a WCF service as a Business Layer (this is an assignment for school, I cannot scrap WCF from Business Layer).
The issue is that when I request data from the database. When I have a method that returns a string from the database, it works just fine (since its a primitive). But when it returns an Entity object (Such as Account), it all goes to hell.
Exception: (Yeah, its very vague).
An error occurred while receiving the HTTP response to http://localhost:8733/Services/AccountsManager. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.
What I tried: I tried modifying the Entites.tt file to add the [DataContract] [DataMember] Attribute. This is because in the older versions of EF, it seemed to be doing it on its own. But I do not know if this is neccessary since it allows me to compile and does not complain that it is not serializable.
This is how it looks at first:
namespace CommonLayer
{
using System;
using System.Collections.Generic;
public partial class Account
{
public Account()
{
this.Transactions = new HashSet<Transaction>();
this.Transactions1 = new HashSet<Transaction>();
}
public System.Guid ID { get; set; }
public int Type { get; set; }
public string Name { get; set; }
public int Currency { get; set; }
public decimal Balance { get; set; }
public System.DateTime DateOpened { get; set; }
public Nullable<int> Duration { get; set; }
public string UserName { get; set; }
public virtual AccountType AccountType { get; set; }
public virtual Currency Currency1 { get; set; }
public virtual User User { get; set; }
public virtual ICollection<Transaction> Transactions { get; set; }
public virtual ICollection<Transaction> Transactions1 { get; set; }
}
}
How it looks after modification:
namespace CommonLayer
{
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
[DataContract] public partial class Account
{
public Account()
{
this.Transactions = new HashSet<Transaction>();
this.Transactions1 = new HashSet<Transaction>();
}
[DataMember] public System.Guid ID { get; set; }
[DataMember] public int Type { get; set; }
[DataMember] public string Name { get; set; }
[DataMember] public int Currency { get; set; }
[DataMember] public decimal Balance { get; set; }
[DataMember] public System.DateTime DateOpened { get; set; }
[DataMember] public Nullable<int> Duration { get; set; }
[DataMember] public string UserName { get; set; }
public virtual AccountType AccountType { get; set; }
public virtual Currency Currency1 { get; set; }
public virtual User User { get; set; }
public virtual ICollection<Transaction> Transactions { get; set; }
public virtual ICollection<Transaction> Transactions1 { get; set; }
}
}
Any pointers are greatly appreciated.
My WCF Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
namespace BusinessLayer
{
[ServiceContract]
interface IAccountsManager
{
[OperationContract]
List<CommonLayer.Account> GetAccounts(String UserName);
[OperationContract]
String GetData();
[OperationContract]
CommonLayer.Account GetAccount(String UserName);
}
class AccountsManager: IAccountsManager, IDisposable
{
public List<CommonLayer.Account> GetAccounts(String UserName)
{
return DataLayer.AccountsRepository.Instance.GetAccountList(UserName).ToList();
}
public String GetData()
{
CommonLayer.Account acc = this.GetAccounts("test").FirstOrDefault();
return acc.DateOpened.ToString();
}
public CommonLayer.Account GetAccount(String UserName)
{
return this.GetAccounts(UserName).FirstOrDefault();
}
public void Dispose()
{
DataLayer.AccountsRepository.Reset();
}
}
}
You need to use a DTO (Data Transfer Object) and map from your EF object to your DTO.
So the service might accept an object called MyDto looking like:
[DataContract]
public class MyDto {
[DataMember]
public int Id {get;set;}
}
and a static mapping class with methods
public static MyEntity Map(MyDto dto) {
return new MyEntity { Id = dto.Id };
}
public static MyDto Map(MyEntity entity) {
return new MyDto { Id = entity.Id };
}
You can then map as required so that the service can use the DTO and Entity Framework can use the Entity.
It seems that when the EF class has Navigation properties (like ICollection<Transaction> Transactions in your class) it will fails when being transferred over WCF.
After many searches I could not find any solution except mapping an EF class into equivalent DTO class that is exactly the same as the EF class except the Navigation propertis and the constructor (i.e. I have stripped all virtual propertis (like ICollection ones) and the ctor from the EF class and have created from that a new class called the same as my EF class plus Dto suffix (e.g. CustomerDto).
I've used AutoMapper to automatically map an EF object into Dto-equivalent one. E.g:
var customer = getCustomer(cid);
var customerDto = Mapper.Map<CustomerDto>(customer);
return customerDto;
My WCF contract includes
[OperationContract]
CustomerDto getCustomerData(int cid);
In addition I needed to do one time initialization of the Mapper. I've done it within Global.asax as follows:
Mapper.CreateMap<Customer, CustomerDto>();
What I have done is changed my Entities.Edmx file. Firstly, I deleted all (2) ".tt" files. Then i changed Code Generation Strategy from None to Default. This seemed to solve all my problems.

New fields not added in the database Code first

I was following this tutorial which is about moving the SimpleMembershipProvider to your own database with custom fields in the userprofile table. I've added some new fields in the code:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string Mobile { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Then I run the Add-Migration command. And it generates a ######.cs file that looks like this:
namespace MVC4SimpleMembershipCodeFirstSeedingEF5.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class test : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
}
The up() and Down() methods have an empty body. Somehow it's not detecting the new changes (added FirstName and LastName fields) i have made.
What am I missing here?
EDIT:
I added the same fields to another table i have created, and that table did get updated in the database.
This is what Add-Migration produced:
namespace MVC4SimpleMembershipCodeFirstSeedingEF5.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class test : DbMigration
{
public override void Up()
{
AddColumn("dbo.TestTabel", "FirstName", c => c.String());
AddColumn("dbo.TestTabel", "LastName", c => c.String());
}
public override void Down()
{
DropColumn("dbo.TestTabel", "LastName");
DropColumn("dbo.TestTabel", "FirstName");
}
}
}
So the problem has been narrowed down to the userprofile table. Whats so special about this table that it can't be altered?