C# 如何在 MVC4 中的 UserProfile 中创建自定义附加字段
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12435252/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create custom additional fields in UserProfile in MVC4
提问by testCoder
I faced with new ASP MVC 4 feature, it shipped with new membership db schema and new initialization. In mvc 3 and old versions developer able to create custom user profile fields using specifications in web.config, but now i faced with method in filters namespace in default mvc 4 project:
我遇到了新的 ASP MVC 4 特性,它附带了新的成员数据库架构和新的初始化。在 mvc 3 和旧版本中,开发人员能够使用 web.config 中的规范创建自定义用户配置文件字段,但现在我在默认 mvc 4 项目中面临过滤器命名空间中的方法:
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
and user profile table:
和用户配置文件表:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
But the method InitializeDatabaseConnection generate only UserName and UserId i need to generate other additional fields.
但是方法 InitializeDatabaseConnection 只生成 UserName 和 UserId 我需要生成其他附加字段。
I have good experience in EF codeFirst approach, and in that case i try to edit UserProfile Class:
我在 EF codeFirst 方法方面有很好的经验,在这种情况下,我尝试编辑 UserProfile 类:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
[Column]
[Required]
public string UserName { get; set; }
[Column]
[Required]
public string FirstName { get; set; }
[Column]
[Required]
public string LastName { get; set; }
}
But when i regenerate database, i havent see any changes, Custom Db fields not generated. Help me please, how can i create custom user fields?
但是当我重新生成数据库时,我没有看到任何更改,未生成自定义 Db 字段。请帮助我,我如何创建自定义用户字段?
采纳答案by IMLiviu
Elaborating from the answer above
从上面的答案中详细说明
The WebSecurity.InitializeDatabaseConnectionMethod help states that
该WebSecurity.InitializeDatabaseConnection方法帮助指出
If you want to use a database table that contains user profile information (user names, email addresses, and so on), you specify a connection string and table name that the membership system uses to connect to that information. If you do not want to use an existing user profile table, you can specify that the InitializeDatabaseConnection() method should automatically create the user profile table. (A database for the user profile table must already exist.)
如果要使用包含用户配置文件信息(用户名、电子邮件地址等)的数据库表,请指定成员资格系统用于连接到该信息的连接字符串和表名。如果不想使用现有的用户配置文件表,可以指定 InitializeDatabaseConnection() 方法应自动创建用户配置文件表。(用户配置文件表的数据库必须已经存在。)
So if we want more fields into the UserProfiletable we just need to make sure we are creating a profile table and run the InitializeDatabaseConnectionmethod after the table is already in place.
因此,如果我们想要在UserProfile表中添加更多字段,我们只需要确保我们正在创建配置文件表并InitializeDatabaseConnection在表已经就位后运行该方法。
In the standard MVC4.0 project template from VS2012 I've commented out the Account controller
在 VS2012 的标准 MVC4.0 项目模板中,我注释掉了 Account 控制器
[Authorize]
//[InitializeSimpleMembership]
public class AccountController : Controller
{
and moved InitializeDatabaseConnectioninto the EF Code First Database Initializer
并移入InitializeDatabaseConnectionEF Code First Database Initializer
public class MyDatabaseInit: DropCreateDatabaseAlways<MyDatabaseContext>
{
protected override void Seed(MyDatabaseContext context)
{
SeedMembership();
}
private void SeedMembership()
{
WebSecurity.InitializeDatabaseConnection("MyDatabaseContext",
"UserProfile", "UserId", "UserName", autoCreateTables: true);
}
}
ensuring that the InitializeDatabaseConnectionruns once the table is already in place.
确保InitializeDatabaseConnection在桌子已经就位后运行。
Added the UserProfileclass to my EF Code First model
将该UserProfile类添加到我的 EF Code First 模型中
public class MyDatabaseContext : DbContext
{
public DbSet<UserProfile> UserProfiles { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Added the extra field in the UserProfiletable
在UserProfile表中添加了额外的字段
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string MobilePhone { get; set; }
}
All you need now is to set the database initialization strategy when the application starts and also call a query on the database the make sure it gets created at that point, before any authorization/authentication code is called.
您现在需要做的就是在应用程序启动时设置数据库初始化策略,并在调用任何授权/身份验证代码之前调用数据库查询以确保在该点创建它。
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
Database.SetInitializer<MyDatabaseContext>(new MyDatabaseInit());
new MyDatabaseContext().UserProfile.Find(1);
}
回答by pranav rastogi
Have a look at the MVC4 internet project template that shipped with VS2012 or on VS2010. You need to make sure the database is not created before you modify the columns of your userprofile class. you can add more properties in your POCO classes and then regenerate your database. if you add properties after the database is generated then please make sure that you are using EF migrations to add those new properties to the database
查看 VS2012 或 VS2010 附带的 MVC4 Internet 项目模板。在修改用户配置文件类的列之前,您需要确保未创建数据库。您可以在 POCO 类中添加更多属性,然后重新生成数据库。如果您在数据库生成后添加属性,请确保您使用 EF 迁移将这些新属性添加到数据库
回答by CR41G14
Add a new table to the Database and call it User_Details or similar, on creating a user you can then retrieve the ID of the user and force the details into the new table. This is One simple option.
向数据库添加一个新表并将其命名为 User_Details 或类似名称,在创建用户时,您可以检索用户的 ID 并将详细信息强制添加到新表中。这是一种简单的选择。
回答by Gone Coding
Non-destructive version based on IMLiviu's answer and comments:
基于 IMLiviu 的回答和评论的非破坏性版本:
Just came across this one problem and had to unknotthe correct way to do it from the answer + comments (+ trial and error), so thought I would share the results you can cut & paste. This is based on the answer by IMLiviu, so full credit to them. It modifies the existing UserProfileand UserContextclasses as they appear directly compatible with EF as-is:
刚刚遇到这个问题,不得不从答案+评论(+反复试验)中找出正确的方法,所以我想我会分享你可以剪切和粘贴的结果。这是基于 IMLiviu 的答案,因此完全归功于他们。它修改现有的UserProfile和UserContext类,因为它们看起来直接与 EF 兼容:
I was horrified to see a suggestion that involved completely removing a database, just to add a few tables so after reading all the comments and creating a prototype, here's the result.
我很震惊地看到一个涉及完全删除数据库的建议,只是添加几个表,因此在阅读所有评论并创建原型后,结果如下。
1 - Stop Webmatrix creation
1 - 停止 Webmatrix 创建
Stop the standard webmatrix creation of the membership tables (comment out the [InitializeSimpleMembership] attribute).
停止成员表的标准 webmatrix 创建(注释掉 [InitializeSimpleMembership] 属性)。
[Authorize]
//[InitializeSimpleMembership]
public class AccountController : Controller
2 - Create a migration configuration
2 - 创建迁移配置
Create a migration configuration class like the one below:
创建一个如下所示的迁移配置类:
public class MigrationConfiguration : DbMigrationsConfiguration<UsersContext>
{
public MigrationConfiguration()
{
this.AutomaticMigrationsEnabled = true; // This is important as it will fail in some environments (like Azure) by default
}
protected override void Seed(UsersContext context)
{
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
}
3 - Remove pluralisation from EF creation
3 - 从 EF 创建中删除复数形式
Change the AccountModel.cs file UsersContextclass to remove the pluralisation option (added the OnModelCreating event):
更改 AccountModel.cs 文件UsersContext类以删除复数选项(添加 OnModelCreating 事件):
public class UsersContext : DbContext
{
public UsersContext() : base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
4 - Add new fields to UserProfile
4 - 向 UserProfile 添加新字段
Add the extra fields you need to UserProfile:
将您需要的额外字段添加到 UserProfile:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string UserEmail { get; set; } // <<<<<<<< E.G. THIS ADDED
}
5 - Migrate the tables on app start
5 - 在应用程序启动时迁移表
Now when the app starts you set the database init strategy and trigger it with a read:
现在,当应用程序启动时,您可以设置数据库初始化策略并通过读取触发它:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
Database.SetInitializer(new MigrateDatabaseToLatestVersion<UsersContext, MigrationConfiguration>());
new UsersContext().UserProfiles.Find(1);
}
Obviously you will need to add various using statements to get this all to work, but the right click resolveoption will do that for you.
显然,您需要添加各种 using 语句才能使这一切正常工作,但右键单击解决选项将为您完成此操作。
Additional notes:
补充说明:
If you decide (as I did) to use a table other than UserProfilefor your users, you need to change several entries to match.
如果您决定(像我一样)使用除UserProfile用户以外的表,您需要更改多个条目以匹配。
- In your
SimpleMembershipInitializerclass you need to reference the new table and column names - In the account controller and the various Login and Register views you need to reference your new model fields (if the names have changed)
- In the
UsersContextclass you can leave the Userprofile classname as-is, but you need to change theTableattribute to match your table name. - In the
UserProfileclass you need to rename the fields to match your new table field names. - In the database you need to remove the relationship between
webpages_UsersInRolesandUserProfileand add a relationship between your new user table andwebpages_UsersInRolesor the old referential integrity checks will break you at run-time. (I strongly recommend you delete the existingUserProfiletable and check it is not recreated. if it is you have something left behind in your code).
- 在您的
SimpleMembershipInitializer班级中,您需要引用新的表名和列名 - 在帐户控制器和各种登录和注册视图中,您需要引用您的新模型字段(如果名称已更改)
- 在
UsersContext类中,您可以保持 Userprofile 类Table名不变,但您需要更改属性以匹配您的表名。 - 在
UserProfile课程中,您需要重命名字段以匹配您的新表字段名称。 - 在数据库中,你需要删除之间的关系
webpages_UsersInRoles,并UserProfile和添加新的用户表之间的关系webpages_UsersInRoles还是老的参照完整性检查将打破你在运行时。(我强烈建议您删除现有UserProfile表并检查它是否重新创建。如果是,则您的代码中遗留了一些内容)。
回答by yardpenalty.com
Of course you probably know that you have to make your RegisterModelidentical to UserProfile Model. What I like to do is use Migrations prior to initializing the database and put the following in the Configuration.csfile:
当然,你可能知道,你必须让你的RegisterModel相同UserProfile Model。我喜欢做的是在初始化数据库之前使用迁移并将以下内容放入Configuration.cs文件中:
protected override void Seed(UsersContext context)
{
WebSecurity.InitializeDatabaseConnection(
"DefaultConnection",
"UserProfile",
"UserId",
"UserName", autoCreateTables: true);
if (!WebSecurity.UserExists("yardpenalty"))
WebSecurity.CreateUserAndAccount(
"yardpenalty",
"password",
new
{
Email = "[email protected]",
ImageUrl = "/Content/Avatars/yourname",
DateJoined = DateTime.Now
},
false);
//... rest of model.Builder stuff
}
Then I use the Packet Manager Consoleby these three easy to remember commands:
然后我使用Packet Manager Consoleby这三个好记的命令:
- Enable-Migrations
- Add-Migration MigrationName
- Update-Database // will seed from Configuration.cs
- 启用迁移
- Add-Migration MigrationName
- 更新数据库 // 将从 Configuration.cs 种子
I agree with TrueBlueAussie, and would go as far as saying LazyInitialization is not very helpful anymore and you really don't have to call it they way you did anymore. Anyways, All you have to do is then change you Register Action in your Account Controller to call the Method like this:
我同意TrueBlueAussie,并且会说 LazyInitialization 不再很有帮助,您真的不必再像以前那样称呼它了。无论如何,您所要做的就是在您的帐户控制器中更改您的注册操作以调用这样的方法:
WebSecurity.CreateUserAndAccount(model.UserName, model.Password, propertyValues: new { model.Email, model.ImageUrl, model.DateJoined });
NOTE: MVC5 uses OWIN
注意:MVC5 使用 OWIN

