mvc entity framework : login using a database - asp.net-mvc-2

I have created a database in Microsoft sql server express. I need to be able to login on Mvc 2 app, using my database ( not the one existing on AcountController meaning MembershipService )
I just need to replace MemeberAhipService with my database. How can I do that ( i'm using entity framework code first ) . I don't need to create a model in visual studio. I have the usermodel, userContext: Db . I think i need repository also. Can anyone show me an example, of tell me the steps ?

You can create your own MembershipService.
Example:
New MembershipService.cs (or whatever you want)
public class MembershipService
{
public bool IsUserValid(string username, string password)
{
var db = new DatabaseContext();
var user = db.GetUser(username, password);
// Or however you want to get your data, via Context or Repository
return (user != null);
}
}
New FormsClass.cs
public class FormService
{
public void SignIn(string username, List&ltstring> roles)
{
FormsAuthenticationTicket authTicket = new
FormsAuthenticationTicket(1, // Version
username, // Username
DateTime.Now, // Creation
DateTime.Now.AddMinutes(30), // Expiration
false, // Persistent
string.Join(",", roles.ToArray())); // Roles
string encTicket = FormsAuthentication.Encrypt(authTicket);
HttpContext.Current.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
GenericIdentity id = new GenericIdentity(username);
HttpContext.Current.User = new GenericPrincipal(id, roles.ToArray());
}
}
In Global.asax:
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
string encTicket = authCookie.Value;
if (!String.IsNullOrEmpty(encTicket))
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(encTicket);
FormsIdentity id = (FormsIdentity)Context.User.Identity;
var roles = ticket.UserData.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
GenericPrincipal prin = new GenericPrincipal(id, roles);
HttpContext.Current.User = prin;
}
}
}

Related

EFCore.BulkExtensions.BulkInsertAsync giving issues when I try create a Identity user

I am busy merging two projects and with that there are certain methods that I now have to use. When I am creating a new user it fails complaining about Primary key constrains. The weird thing is that the primary key is in a different table from the one that it is complaining about. So my thinking is that it has to do with EFCore.BulkExtensions.BulkInsertAsync(Third party tool by borisdj) and how it saves and UserManager.CreateAsync and how it saves.
This is the error that I am getting:
Innermost exception Microsoft.Data.SqlClient.SqlException :
Violation of PRIMARY KEY constraint 'PK_dbo.UserDetail'. Cannot insert
duplicate key in object 'dbo.UserDetail'.
I have a method with this if statement:
if (await CreateUser.CreateUserDetailAsync(model))
{
await CreateAccountUser(model.Email, model.Password, model.Role, model.Fullname);
return RedirectToAction("Index", "ShowUser");
}
I get the error in the CreateAccountUser user method but it complains about the table in CreateUser.CreateUserDetailAsync.
Th error complains about my UserDetail here is how this is saved. This part works because even with the error, the data get saved to the database.
private async Task<boolean> CreateUserDetailAsync(_Models.Settings.User user)
{
var userDetail = new UserDetail
{
Code = user.ERPCode,
Email = user.Email,
Name = user.Name,
Surname = user.Surname
};
//Create the
await UserDetail.BulkInsertAsync(new List<UserDetail>{userDetail});
return true;
}
This is my method for bulk inserts using EFCore.BulkExtensions.BulkInsertAsync:
public Task BulkInsertAsync(IEnumerable<T> entities)
{
if (entities == null)
throw new ArgumentNullException("entity");
foreach (var item in entities)
{
//Attempt to set the Create value of the entity
var created = typeof(T).GetProperty("Created");
if (created == null) created = typeof(T).GetProperty("CreatedOn");
created?.SetValue(item, DateTime.Now, null);
//Attempt to set the Modified value of the entity
var modified = typeof(T).GetProperty("Modified");
if (modified == null) modified = typeof(T).GetProperty("ModifiedOn");
modified?.SetValue(item, DateTime.Now, null);
Entities.Add(item);
}
return Throw(Db).BulkInsertAsync(entities.ToList());
}
I am including this code just for clarity:
private static DbContext Throw(IDataContext context) => context as DbContext;
Then when I get to this method, it fails on await UserManager.CreateAsync.
private async Task CreateAccountUser(string email, string password, string role,
string userFullName = null)
{
//Register User with identity
var accountUser = new Core.Data.Models.User();
accountUser.Email = accountUser.UserName = email;
var result = await UserManager.CreateAsync(accountUser, password);
if (result.Succeeded)
{
return true;
}
else
{
return true;
}
}
There are no linking between my User and UserDetail, they are completely separate.

Working on pre-operation plug-in to update "Modified By" field in MSCRM -- Need help fixing code

I am trying to update the "Modified By" field based on a text field called "Prepared By", which contains the name of a user. I've created a pre-operation plug-in to do this and believe I am close to done. However, the "Modified By" field is still not successfully getting updated. I am relatively new to coding and CRM, and could use some help modifying the code and figuring out how I can get this to work.
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Linq;
namespace TimClassLibrary1.Plugins
{
public class CreateUpdateContact : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
var factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service = factory.CreateOrganizationService(context.UserId);
tracingService.Trace("Start plugin");
tracingService.Trace("Validate Target");
if (!context.InputParameters.Contains("Target") || !(context.InputParameters["Target"] is Entity))
return;
tracingService.Trace("Retrieve Target");
var target = (Entity)context.InputParameters["Target"];
String message = context.MessageName.ToLower();
SetCreatedByAndModifiedBy(tracingService, service, target, message);
}
private void SetCreatedByAndModifiedBy(ITracingService tracingService, IOrganizationService service, Entity target, string message)
{
tracingService.Trace("Start SetPriceList");
tracingService.Trace("Validate Message is Create or Update");
if (!message.Equals("create", StringComparison.OrdinalIgnoreCase) && !message.Equals("update", StringComparison.OrdinalIgnoreCase))
return;
tracingService.Trace("Retrieve Attributes");
var createdByReference = target.GetAttributeValue<EntityReference>("new_createdby");
var modifiedByReference = target.GetAttributeValue<EntityReference>("new_modifiedby");
tracingService.Trace("Retrieve And Set User for Created By");
RetrieveAndSetUser(tracingService, service, target, createdByReference, "createdby");
tracingService.Trace("Retrieve And Set User for Modified By");
RetrieveAndSetUser(tracingService, service, target, modifiedByReference, "modifiedby");
}
private void RetrieveAndSetUser(ITracingService tracingService, IOrganizationService service, Entity target, EntityReference reference, string targetAttribute)
{
tracingService.Trace("Validating Reference");
if (reference == null)
return;
tracingService.Trace("Retrieving and Validating User");
var user = RetrieveUserByName(service, reference.Name, new ColumnSet(false));
if (user == null)
return;
tracingService.Trace("Setting Target Attribute");
target[targetAttribute] = user.ToEntityReference();
}
private Entity RetrieveUserByName(IOrganizationService service, string name, ColumnSet columns)
{
var query = new QueryExpression
{
EntityName = "systemuser",
ColumnSet = columns,
Criteria = new FilterExpression
{
FilterOperator = LogicalOperator.And,
Conditions =
{
new ConditionExpression
{
AttributeName = "fullname",
Operator = ConditionOperator.Equal,
Values = { name }
}
}
}
};
var retrieveResponse = service.RetrieveMultiple(query);
if (retrieveResponse.Entities.Count == 1)
{
return retrieveResponse.Entities.FirstOrDefault();
}
else
{
return null;
}
}
}
}
If you do get use from method Retreiveusernyname then you have to use below code
target[“modifiedby”] = new EntityRefrence(user.logicalname,user.id);
I don't see anything obviously wrong with your update, however you are taking a complicated and unnecessary step with your RetrieveUserByName() method. You already have EntityReference objects from your new_createdby and new_modifiedby fields, you can simply assign those to the target:
if (message.Equals("create", StringComparison.OrdinalIgnoreCase))
{
target["createdby"] = target["new_createdby];
}
else if (message.Equals("update", StringComparison.OrdinalIgnoreCase))
{
target["modifiedby"] = target["new_modifiedby];
}
If new_createdby and new_modifiedby are not entity references, then that would explain why your existing code does not work, if they are, then use my approach.

Seed data to UserRole table .net core

I want to seed the default DB with an admin user before I start the project on .NET Core Default MVC application. The code is as below:
public void SeedDb(ApplicationDbContext Context, IServiceProvider ServiceProvider, IConfiguration Configuration)
{
if (Context.Users.Count() > 0) return;
var UserManager = ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
var ApplicationUser = new ApplicationUser()
{
Email = Configuration["Email"],
NormalizedEmail = Configuration["Email"],
LockoutEnabled = false,
NormalizedUserName = Configuration["Email"],
SecurityStamp = "579355dd - a64c - 498d - a0b5 - 9e55754c9109",
EmailConfirmed = true,
ConcurrencyStamp = null,
Id = "977ec1a5-1ae7-4658-952a-6b5dccd75a85",
PasswordHash ="",
PhoneNumber = "333333333333",
LockoutEnd = null,
AccessFailedCount = 1,
PhoneNumberConfirmed = true,
TwoFactorEnabled = false,
UserName = Configuration["Email"]
};
var Password = HashPassword(ApplicationUser, Configuration["Password"]);
if (VerifyHashedPassword(ApplicationUser, Password, Configuration["Password"]) == PasswordVerificationResult.Success)
{
ApplicationUser.PasswordHash = Password;
}
Context.Users.Add(ApplicationUser);
Context.SaveChanges();
var RoleManager = ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
string[] Roles = { "Admin", "Manager", "User" };
foreach (string RoleName in Roles) {
RoleManager.CreateAsync(new IdentityRole(RoleName));
}
var Admin = Context.Users.SingleOrDefault(m => m.Email == Configuration["Email"]);
var Role = Context.Roles.SingleOrDefault(m => m.Name == Configuration["Role"]);
IdentityUserRole<string> UserRole = new IdentityUserRole<string>() { UserId = Admin.Id, RoleId = Role.Id };
Context.UserRoles.Add(UserRole);
Context.SaveChanges();
}
Everything runs perfect except I can't seed the UserRole DB with Data. From DBContext I add IdentityUserRole entity and save the changes to DB. Although nothing passed under the DB. Any suggestion?
Create a class named StartupDbInitializer:
using System;
using System.Collections.Generic;
using System.Linq;
using Core.Entities;
using Microsoft.AspNetCore.Identity;
namespace Core.Startups
{
public class StartupDbInitializer
{
private const string AdminEmail = "admin#admin.com";
private const string AdminPassword = "StrongPasswordAdmin123!";
private static readonly List<IdentityRole> Roles = new List<IdentityRole>()
{
new IdentityRole {Name = "Admin", NormalizedName = "ADMIN", ConcurrencyStamp = Guid.NewGuid().ToString()}
};
public static void SeedData(ApplicationDbContext dbContext, UserManager<User> userManager)
{
dbContext.Database.EnsureCreated();
AddRoles(dbContext);
AddUser(dbContext, userManager);
AddUserRoles(dbContext, userManager);
}
private static void AddRoles(ApplicationDbContext dbContext)
{
if (!dbContext.Roles.Any())
{
foreach (var role in Roles)
{
dbContext.Roles.Add(role);
dbContext.SaveChanges();
}
}
}
private static async void AddUser(ApplicationDbContext dbContext, UserManager<User> userManager)
{
if (!dbContext.Users.Any())
{
var user = new User {
UserName = AdminEmail,
Email = AdminEmail,
IsEnabled = true,
EmailConfirmed = true,
};
await userManager.CreateAsync(user, AdminPassword);
}
}
private static void AddUserRoles(ApplicationDbContext dbContext, UserManager<User> userManager)
{
if (!dbContext.UserRoles.Any())
{
var userRole = new IdentityUserRole<string>
{
UserId = dbContext.Users.Single(r => r.Email == AdminEmail).Id,
RoleId = dbContext.Roles.Single(r => r.Name == "Admin").Id
};
dbContext.UserRoles.Add(userRole);
dbContext.SaveChanges();
}
}
}
}
Then call it in your Startup's Configure method:
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ApplicationDbContext dbContext,
UserManager<User> userManager,
)
{
// rest of code...
StartupDbInitializer.SeedData(dbContext, userManager);
}
Above, I inject my DbContext and UserManager<T>.
Try this line... it must work.
ApplicationUser user = await _usermanager.FindByEmailAsync("your.email#mymail.com");
if (!await _usermanager.IsInRoleAsync(user, "Admin"))
{
await _usermanager.AddToRoleAsync(user, "Admin");
}
When you tried it and it works, change it to your config parameters if you prefer them. It's not that hard to get it to work, you have everything you need in UserManager and RoleManager classes.
I still say you have to check if the role exist in table before you insert it, I got all my roles populated every time I run the application before I added the check.
if ((await _roleManager.FindByNameAsync("Admin")) == null)
{
await _roleManager.CreateAsync(new IdentityRole { Name = "Admin" });
}

RoleStore and Role management in Asp.NET Identity Without Entity Framework

I am writing WCF Services, I authenticate User who will have access to my WCF Services through ASP.NET Identity without Entity Framework. Now I got an issue on Role Authorization. I am using custom way without Entity Framework so for it to achieve authentication I created User class and UserStore Class. And how could I authorize the role?
[Note:I have Role in Database table (ASPNetRoles and ASPNetUserRoles) that can only access WCF Services and I know I have to decorate the method with principalpermission.]
namespace CalculatorService
{
public class IdentityValidator : UserNamePasswordValidator
{
public override void Validate(string UserName, string Password)
{
using (var userManager = new UserManager<User>(new UserStore("data=source=pcb-sql01;initial catalog=InsitePCB;integrated security=True;MultipleActiveResultSets=True")))
{
var user = userManager.Find(UserName, Password);
if (user == null)
{
var msg = string.Format("Unknown Username {0} or incorrect password {1}", UserName, Password);
Trace.TraceWarning(msg);
throw new FaultException(msg);
// //the client actually will receive MessageSecurityException. But if I throw MessageSecurityException, the runtime will give FaultException to client without clear message.
}
}
}
}
public class RoleAuthorizationManager : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
using (var userStore = new UserStore("data source=pcb-sql01;initial catalog=InsitePCB;integrated security=True;MultipleActiveResultSets=True"))
{
using (var userManager = new UserManager<User>(userStore))
{
var identity = operationContext.ServiceSecurityContext.PrimaryIdentity;
var user = userManager.FindByName(identity.Name);
if (user == null)
{
var msg = string.Format("Unknown Username {0} .", user.UserName);
Trace.TraceWarning(msg);
throw new FaultException(msg);
}
//Assign roles to the Principal property for runtime to match with PrincipalPermissionAttributes decorated on the service operation.
var roleNames = userManager.GetRoles(user.Id).ToArray();//users without any role assigned should then call operations not decorated by PrincipalPermissionAttributes
operationContext.ServiceSecurityContext.AuthorizationContext.Properties["Principal"] = new GenericPrincipal(operationContext.ServiceSecurityContext.PrimaryIdentity, roleNames);
return true;
}
}
}
}
}

MembershipCreateUserException: The username supplied is invalid

Im trying to use Facebook registration on my MVC 4 application, but I keep getting this cryptic error System.Web.Security.MembershipCreateUserException: The username supplied is invalid.
when OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName); is run
provider = "facebook"
providerUserId = "token-key"
model.Username = "bobsaget"
Everything is basically set back to a default MVC 4 application at this point. Here is the code I am running.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl)
{
string provider = null;
string providerUserId = null;
if (User.Identity.IsAuthenticated || !OAuthWebSecurity.TryDeserializeProviderUserId(model.ExternalLoginData, out provider, out providerUserId))
{
return RedirectToAction("Manage");
}
if (ModelState.IsValid)
{
// Insert a new user into the database
using (UsersContext db = new UsersContext())
{
UserProfile user = db.UserProfiles.FirstOrDefault(u => u.UserName.ToLower() == model.UserName.ToLower());
// Check if user already exists
if (user == null)
{
// Insert name into the profile table
db.UserProfiles.Add(new UserProfile { UserName = model.UserName});
db.SaveChanges();
db.SaveChanges();
OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("UserName", "User name already exists. Please enter a different user name.");
}
}
}
ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(provider).DisplayName;
ViewBag.ReturnUrl = returnUrl;
return View(model);
}
The MembershipAttribute have always been default, except its getting information from web.config.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<UsersContext>(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
var i = Config.ConnectionStringName;
WebSecurity.InitializeDatabaseConnection(
Config.ConnectionStringName,
Config.UserTableName,
Config.UsersPrimaryKeyColumnName,
Config.UsersUserNameColumnName,
autoCreateTables: true);
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}
}
I have browsed the web, Stackoverflow and even tried to decompile the dll without getting to the root of the problem.
Thanks in advance for your input.
I am not sure but i think you need to make to sure that an entry of user is properly inserted into userprofile table and also the other tables which are required for membership.