I ran into an issue after finally getting my API call to work where it gives me the following exception
Unhandled Exception:
SQLite.SQLiteException: no such table: Token occurred
I have this class here
public class Token
{
[PrimaryKey]
public int Id { get; set; }
public string accessToken { get; set; }
public string errorDescription { get; set; }
public DateTime expireDate { get; set; }
public int expireIn { get; set; }
public Token() { }
}
here is my ios sqlite class for ios
public class SQLite_iOS : ISQLite
{
public SQLite_iOS() { }
public SQLite.SQLiteConnection GetConnection()
{
var dbName = "mydb.db3";
var documentPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var libraryPath = Path.Combine(documentPath, "..", "Library");
var path = Path.Combine(libraryPath, dbName);
var connection = new SQLite.SQLiteConnection(path);
return connection;
}
}
here is my Api call
public async Task<string> LoginAsync(string email, string password)
{
var db = new SQLiteConnection(dbPath);
var tokenInfo = new Token();
var keyValues = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("email", email),
new KeyValuePair<string, string>("password", password),
new KeyValuePair<string, string>("grant_type", "password")
};
var request = new HttpRequestMessage(HttpMethod.Post, "https://myurl/v1/auth/login");
request.Content = new FormUrlEncodedContent(keyValues);
var client = new HttpClient();
var response = await client.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
JObject jwtDynamic = JsonConvert.DeserializeObject<dynamic>(content);
var accessTokenExpiration = jwtDynamic.Value<DateTime>(".expires");
var accessToken = jwtDynamic.Value<string>("token");
//Settings.AccessTokenExpirationDate = accessTokenExpiration;
Debug.WriteLine(accessTokenExpiration);
Debug.WriteLine(content);
tokenInfo = new Token();
tokenInfo.accessToken = "accessToken";
db.Insert(tokenInfo);
return accessToken;
}
I have been learning this as I go, and have learned a lot, but it's all new to me right now. Thanks for the help
Related
For an application created and configured in Azure Active Directory I am able to request and obtain a token. When I am trying to use this token to read OPTIONS from Exchange ActiveSync, the response is 401 unauthorized. The source code is below. Obviously I am doing something wrong. Any help is greatly appreciated!
Thank you!
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace FAC.ActiveSync.ModernAuth
{
internal partial class Program
{
private static readonly AzureApp app = new AzureApp
{
TenantId = "***",
ClientId = "***",
ClientSecretId = "***",
ClientSecretValue = "***"
};
static async Task Main()
{
var response = await GetOptions();
}
private static async Task<AccessTokenModel> GetToken()
{
var data = new Dictionary<string, string>
{
{ "grant_type", "client_credentials"},
{ "scope", "https://outlook.office365.com/.default"},
{ "client_id", app.ClientId},
{ "client_secret", app.ClientSecretValue}
};
using (var client = new HttpClient())
{
HttpResponseMessage response =
await client.PostAsync(app.UrlGetToken,
new FormUrlEncodedContent(data));
return await response.Content.ReadAsAsync<AccessTokenModel>();
}
}
private static async Task<string> GetOptions()
{
var accessToken = await GetToken();
var request = new HttpRequestMessage(
HttpMethod.Options,
"https://outlook.office365.com/Microsoft-Server-ActiveSync");
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer",
accessToken.access_token);
var response = await client.SendAsync(request);
return await response.Content.ReadAsStringAsync();
}
}
}
public class AccessTokenModel
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public int ext_expires_in { get; set; }
}
public class AzureApp
{
public string TenantId { get; set; }
public string ClientId { get; set; }
public string ClientSecretValue { get; set; }
public string ClientSecretId { get; set; }
public string UrlGetToken
{
get
{
return $"https://login.microsoftonline.com/{TenantId}/oauth2/v2.0/token";
}
}
public string UrlAuthorize
{
get
{
return $"https://login.microsoftonline.com/{TenantId}/oauth2/v2.0/authorize";
}
}
}
}
I want to Save jwt token in the database I share the code of the controller where token generation is done but I don't know how to save the token or that code will work or nor
this is my controller where use jwt token
public class LoginController: Controller
{
private readonly JwtAuthContext _context;
private IConfiguration _config;
public LoginController(IConfiguration config, JwtAuthContext
context)
{
_config = config;
_context = context;
}
[Route("api/Register")]
[HttpPost]
public IActionResult Post([FromBody] Register register)
{
if (ModelState.IsValid)
{
_context.Add(register);
_context.SaveChanges();
}
Console.WriteLine(register);
var ttt = _context.Registers.ToList();
return Ok(new { result = ttt });
}
[HttpPost]
public IActionResult Login([FromBody] Login Login)
{
var user = Authenticate(Login);
if (user != null)
{
var token = Generate(user);
_context.SaveChanges();
return Ok(token);
}
return NotFound("User not found");
}
private string Generate(Register user)
{
var securityKey = new
SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var credentials = new SigningCredentials(securityKey,
SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, user.Email),
new Claim(ClaimTypes.Email, user.FullName),
new Claim(ClaimTypes.Role, user.Role)
};
var token = new JwtSecurityToken(_config["Jwt:Issuer"],
_config["Jwt:Audience"],
claims,
expires: DateTime.Now.AddMinutes(15),
signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(token);
}
private Register Authenticate(Login Login)
{
var currentUser = _context.Registers.FirstOrDefault(o =>
o.Email.ToLower() == Login.Email.ToLower() && o.Password == Login.Password);
if (currentUser != null)
{
return currentUser;
}
return null;
}
this is my login model where I create a table of login
public class login{
public int LoginId{get;set;}
public string Email{get;set;}
public string Password{get;set;}
}
this is my register model where I can create a register model
public class Register{
public int Id{get;set;}
public string FullName{get;set;}
public string Email{get;set;}
public string Password{get;set;}
}
-------------
JwtAuthContext
--------------
public class JwtAuthContext : DbContext
{
public JwtAuthContext(DbContextOptions<JwtAuthContext> options)
: base(options)
{
}
public DbSet<Login> Logins { get; set; }
public DbSet<Register> Registers { get; set; }
public DbSet<AuthenticationToken> authenticationTokens { get;
set; }
}
This is my AuthenticationToken Model
public class AuthenticationToken
{
public string Token{get;set;}
}
Try this.
if (user != null)
{
var token = Generate(user);
_context.authenticationTokens.Add(token); // just add this line
_context.SaveChanges();
return Ok(token);
}
I know this is a very basic question, but I'm creating a browser in wpf (I'm almost done with it) using CEFSharp, but I hit a snag with logging into google on some accounts. I get a "This browser or app may not be secure." message. Now, I've researched using OAuth to get a token for accessing and using certain features of Google, but not just how to log in as a whole. I just want the user to be able to log into Google, just like they would on a Chrome browser (without the Sync option, of course).
I registered my application with Google Console, and received a ClientId and ClientSecret, and I created a window to be called when the sign-in button is clicked on the google page that tries to get the token, but when the user types in their e-mail, they get the same message (See Below).
I'm not sure if there's an API that I can use or something that can let my user login to google through my browser without having to call the Google Chrome browser itself, because that defeats the purpose of my browser being self-sufficient. I've been beating my head on this for days. Can anyone help?
Below is the xaml for my Google Login window:
<Window x:Class="MyProject.Windows.GoogleLoginWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wpf="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
xmlns:local="clr-namespace:NP_Browser.Windows"
mc:Ignorable="d"
Title="Google Login Window" Height="450" Width="800" Icon="../Images/NPBrowserLogo.ico">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="btv" />
</Window.Resources>
<Grid>
<DockPanel Visibility="{Binding State.IsSigned, Converter={StaticResource btv}}">
<Label Content="{Binding State.Token.Name}" />
</DockPanel>
<Grid Visibility="{Binding State.IsNotSigned, Converter={StaticResource btv}}">
<wpf:ChromiumWebBrowser x:Name="Wb" FontSize="16"/>
</Grid>
</Grid>
Below is the code-behind for my Google Login window:
namespace MyProject.Windows
{
public partial class GoogleLoginWindow : Window
{
public GoogleLoginWindow()
{
InitializeComponent();
State = new OAuthState();
DataContext = this;
Topmost = true;
var thread = new Thread(HandleRedirect);
thread.Start();
}
public OAuthState State { get; }
private async void HandleRedirect()
{
State.Token = null;
var request = OAuthRequest.BuildLoopbackRequest();
var listener = new HttpListener();
listener.Prefixes.Add(request.RedirectUri);
listener.Start();
// note: add a reference to System.Windows.Presentation and a 'using System.Windows.Threading' for this to compile
await Dispatcher.BeginInvoke(() =>
{
Wb.Address = request.AuthorizationRequestUri;
});
// here, we'll wait for redirection from our hosted webbrowser
var context = await listener.GetContextAsync();
// browser has navigated to our small http server answer anything here
string html = string.Format("<html><body></body></html>");
var buffer = Encoding.UTF8.GetBytes(html);
context.Response.ContentLength64 = buffer.Length;
var stream = context.Response.OutputStream;
var responseTask = stream.WriteAsync(buffer, 0, buffer.Length).ContinueWith((task) =>
{
stream.Close();
listener.Stop();
});
string error = context.Request.QueryString["error"];
if (error != null)
return;
string state = context.Request.QueryString["state"];
if (state != request.State)
return;
string code = context.Request.QueryString["code"];
State.Token = request.ExchangeCodeForAccessToken(code);
}
}
// state model
public class OAuthState : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private OAuthToken _token;
public OAuthToken Token
{
get => _token;
set
{
if (_token == value)
return;
_token = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Token)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsSigned)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsNotSigned)));
}
}
public bool IsSigned => Token != null && Token.ExpirationDate > DateTime.Now;
public bool IsNotSigned => !IsSigned;
}
// This is a sample. Fille information (email, etc.) can depend on scopes
[DataContract]
public class OAuthToken
{
[DataMember(Name = "access_token")]
public string AccessToken { get; set; }
[DataMember(Name = "token_type")]
public string TokenType { get; set; }
[DataMember(Name = "expires_in")]
public int ExpiresIn { get; set; }
[DataMember(Name = "refresh_token")]
public string RefreshToken { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Email { get; set; }
[DataMember]
public string Picture { get; set; }
[DataMember]
public string Locale { get; set; }
[DataMember]
public string FamilyName { get; set; }
[DataMember]
public string GivenName { get; set; }
[DataMember]
public string Id { get; set; }
[DataMember]
public string Profile { get; set; }
[DataMember]
public string[] Scopes { get; set; }
// not from google's response, but we store this
public DateTime ExpirationDate { get; set; }
}
// largely inspired from
// https://github.com/googlesamples/oauth-apps-for-windows
public sealed class OAuthRequest
{
private const string ClientId = "My-Client-Id";
private const string ClientSecret = "My-Client-Secret";
private const string AuthorizationEndpoint = "https://accounts.google.com/o/oauth2/v2/auth";
private const string TokenEndpoint = "https://www.googleapis.com/oauth2/v4/token";
private const string UserInfoEndpoint = "https://www.googleapis.com/oauth2/v3/userinfo";
private OAuthRequest()
{
}
public string AuthorizationRequestUri { get; private set; }
public string State { get; private set; }
public string RedirectUri { get; private set; }
public string CodeVerifier { get; private set; }
public string[] Scopes { get; private set; }
// https://developers.google.com/identity/protocols/OAuth2InstalledApp
public static OAuthRequest BuildLoopbackRequest(params string[] scopes)
{
var request = new OAuthRequest
{
CodeVerifier = RandomDataBase64Url(32),
Scopes = scopes
};
string codeChallenge = Base64UrlEncodeNoPadding(Sha256(request.CodeVerifier));
const string codeChallengeMethod = "S256";
string scope = BuildScopes(scopes);
request.RedirectUri = string.Format("http://{0}:{1}/", IPAddress.Loopback, GetRandomUnusedPort());
request.State = RandomDataBase64Url(32);
request.AuthorizationRequestUri = string.Format("{0}?response_type=code&scope=openid%20profile{6}&redirect_uri={1}&client_id={2}&state={3}&code_challenge={4}&code_challenge_method={5}",
AuthorizationEndpoint,
Uri.EscapeDataString(request.RedirectUri),
ClientId,
request.State,
codeChallenge,
codeChallengeMethod,
scope);
return request;
}
// https://developers.google.com/identity/protocols/OAuth2InstalledApp Step 5: Exchange authorization code for refresh and access tokens
public OAuthToken ExchangeCodeForAccessToken(string code)
{
if (code == null)
throw new ArgumentNullException(nameof(code));
string tokenRequestBody = string.Format("code={0}&redirect_uri={1}&client_id={2}&code_verifier={3}&client_secret={4}&scope=&grant_type=authorization_code",
code,
Uri.EscapeDataString(RedirectUri),
ClientId,
CodeVerifier,
ClientSecret
);
return TokenRequest(tokenRequestBody, Scopes);
}
// this is not used in this sample, but can be used to refresh a token from an old one
// https://developers.google.com/identity/protocols/OAuth2InstalledApp Refreshing an access token
public OAuthToken Refresh(OAuthToken oldToken)
{
if (oldToken == null)
throw new ArgumentNullException(nameof(oldToken));
string tokenRequestBody = string.Format("refresh_token={0}&client_id={1}&client_secret={2}&grant_type=refresh_token",
oldToken.RefreshToken,
ClientId,
ClientSecret
);
return TokenRequest(tokenRequestBody, oldToken.Scopes);
}
private static T Deserialize<T>(string json)
{
if (string.IsNullOrWhiteSpace(json))
return default(T);
return Deserialize<T>(Encoding.UTF8.GetBytes(json));
}
private static T Deserialize<T>(byte[] json)
{
if (json == null || json.Length == 0)
return default(T);
using (var ms = new MemoryStream(json))
{
return Deserialize<T>(ms);
}
}
private static T Deserialize<T>(Stream json)
{
if (json == null)
return default(T);
var ser = CreateSerializer(typeof(T));
return (T)ser.ReadObject(json);
}
private static DataContractJsonSerializer CreateSerializer(Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
var settings = new DataContractJsonSerializerSettings
{
DateTimeFormat = new DateTimeFormat("yyyy-MM-dd'T'HH:mm:ss.fffK")
};
return new DataContractJsonSerializer(type, settings);
}
// https://stackoverflow.com/questions/223063/how-can-i-create-an-httplistener-class-on-a-random-port-in-c/
private static int GetRandomUnusedPort()
{
var listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
listener.Stop();
return port;
}
private static string RandomDataBase64Url(int length)
{
using (var rng = new RNGCryptoServiceProvider())
{
var bytes = new byte[length];
rng.GetBytes(bytes);
return Base64UrlEncodeNoPadding(bytes);
}
}
private static byte[] Sha256(string text)
{
using (var sha256 = new SHA256Managed())
{
return sha256.ComputeHash(Encoding.ASCII.GetBytes(text));
}
}
private static string Base64UrlEncodeNoPadding(byte[] buffer)
{
string b64 = Convert.ToBase64String(buffer);
// converts base64 to base64url.
b64 = b64.Replace('+', '-');
b64 = b64.Replace('/', '_');
// strips padding.
b64 = b64.Replace("=", "");
return b64;
}
private static OAuthToken TokenRequest(string tokenRequestBody, string[] scopes)
{
var request = (HttpWebRequest)WebRequest.Create(TokenEndpoint);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
byte[] bytes = Encoding.ASCII.GetBytes(tokenRequestBody);
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
var response = request.GetResponse();
using (var responseStream = response.GetResponseStream())
{
var token = Deserialize<OAuthToken>(responseStream);
token.ExpirationDate = DateTime.Now + new TimeSpan(0, 0, token.ExpiresIn);
var user = GetUserInfo(token.AccessToken);
token.Name = user.Name;
token.Picture = user.Picture;
token.Email = user.Email;
token.Locale = user.Locale;
token.FamilyName = user.FamilyName;
token.GivenName = user.GivenName;
token.Id = user.Id;
token.Profile = user.Profile;
token.Scopes = scopes;
return token;
}
}
private static UserInfo GetUserInfo(string accessToken)
{
var request = (HttpWebRequest)WebRequest.Create(UserInfoEndpoint);
request.Method = "GET";
request.Headers.Add(string.Format("Authorization: Bearer {0}", accessToken));
var response = request.GetResponse();
using (var stream = response.GetResponseStream())
{
return Deserialize<UserInfo>(stream);
}
}
private static string BuildScopes(string[] scopes)
{
string scope = null;
if (scopes != null)
{
foreach (var sc in scopes)
{
scope += "%20" + Uri.EscapeDataString(sc);
}
}
return scope;
}
// https://developers.google.com/+/web/api/rest/openidconnect/getOpenIdConnect
[DataContract]
private class UserInfo
{
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "kind")]
public string Kind { get; set; }
[DataMember(Name = "email")]
public string Email { get; set; }
[DataMember(Name = "picture")]
public string Picture { get; set; }
[DataMember(Name = "locale")]
public string Locale { get; set; }
[DataMember(Name = "family_name")]
public string FamilyName { get; set; }
[DataMember(Name = "given_name")]
public string GivenName { get; set; }
[DataMember(Name = "sub")]
public string Id { get; set; }
[DataMember(Name = "profile")]
public string Profile { get; set; }
[DataMember(Name = "gender")]
public string Gender { get; set; }
}
}
}
You are trying to login on a web view and Google blocks that.
Unfortunately, OAuth for desktop apps is tricky. I have some visual blog posts and a code sample you can run to understand behaviour:
Login by invoking the system browser
Receive the response by spinning up a loopback web server
Or receive the response via a private URI scheme (my preference)
My samples are coded in Electron / Javascript. However, the below C# code samples accompany the IdentityModel security library, and I would recommend using this library for your app:
Loopback Sample
Private Scheme Sample
You need to add this line :
settings.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 /CefSharp Browser" + Cef.CefSharpVersion;
after CefSettings settings = new CefSettings();
Google Blocked logins to it from embedded browser as an act against Man In The Middle Attacks.
I am working on a basic MVC project, pretty much out of the box with minor enhancements. I have therefore customized the user properties a bit, but not too much... however, it seems not to be working anymore since then. I've done the exact same before without running into errors. Any ideas where I went wrong??
IdentityModels:
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit https://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
//public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public string DateOfBirth { get; set; }
//public string Email { get; set; }
public string PhoneNumberPrefix { get; set; }
public string PhoneNumberSuffix { get; set; }
//public string PhoneNumber { get; set; }
public bool PhoneNumberVerified { get; set; }
public string BillingAddress { get; set; }
public bool BillingAddressIsShippingAddress { get; set; }
public string ShippingAddress { get; set; }
public string VATNumber { get; set; }
public string PreferredLanguage { get; set; }
public DateTime RegisteredDateTime { get; set; }
public string RegisteredLatitude { get; set; }
public string RegisteredLongitude { get; set; }
public string RegisteredLocation { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
public class UserDbContext : IdentityDbContext<ApplicationUser>
{
public UserDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static UserDbContext Create()
{
return new UserDbContext();
}
}
AccountController:
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
// define variables
var userID = User.Identity.GetUserId();
DateTime nowUTC = DateTime.Now.ToUniversalTime();
DateTime nowLocal = DateTime.Now.ToLocalTime();
// check model state and submit form
if (ModelState.IsValid)
{
var user = new ApplicationUser
{
UserName = model.UserName,
FirstName = model.FirstName,
LastName = model.LastName,
Gender = model.Gender,
DateOfBirth = model.DateOfBirth,
Email = model.Email,
PhoneNumberPrefix = model.PhoneNumberPrefix,
PhoneNumberSuffix = model.PhoneNumberSuffix,
PhoneNumber = model.PhoneNumberPrefix + model.PhoneNumberSuffix,
BillingAddress = model.BillingAddress,
VATNumber = "MwSt-Nummer",
PreferredLanguage = model.PreferredLanguage,
RegisteredDateTime = nowUTC,
RegisteredLatitude = model.RegisteredLatitude,
RegisteredLongitude = model.RegisteredLongitude,
RegisteredLocation = model.RegisteredLocation
};
// send confirmation email
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new
{
userId = user.Id,
code /*= code*/
}, protocol: Request.Url.Scheme);
await UserManager.SendEmailAsync(user.Id, "Bestätige Dein Konto", "Bitte bestätige Dein Konto indem Du hier klickst.");
ViewBag.Message = "Fast geschafft! Du hast eine Email mit weiteApplicationDbContextren Instruktionen erhalten um die Anmeldung abzuschliessen.";
// track user activity: post method includes activity name and timestamp along with location
var SUCCESS = new UserActivities
{
UserID = userID,
ActivityName = "Register_Success",
ActivityTimeStampUTC = nowUTC,
ActivityLatitude = model.RegisteredLatitude,
ActivityLongitude = model.RegisteredLongitude,
ActivityLocation = model.RegisteredLocation
};
DATADB.UserActivityList.Add(SUCCESS);
DATADB.SaveChanges();
return View("PostRegistration");
}
AddErrors(result);
}
var FAILURE = new UserActivities
{
UserID = userID,
ActivityName = "Register_Failure",
ActivityTimeStampUTC = nowUTC,
ActivityLatitude = model.RegisteredLatitude,
ActivityLongitude = model.RegisteredLongitude,
ActivityLocation = model.RegisteredLocation
};
DATADB.UserActivityList.Add(FAILURE);
DATADB.SaveChanges();
// repopulate dropdownlists
ViewBag.gender = DATADB.GenderList.Select(m => new SelectListItem()
{
Text = m.Gender,
Value = m.Gender
}).ToList();
ViewBag.countryCode = DATADB.CountryCodeList.Select(m => new SelectListItem()
{
Text = m.CountryCode,
Value = m.CountryCode
}).ToList();
ViewBag.preferredLanguage = DATADB.LanguageList.Select(m => new SelectListItem()
{
Text = m.Language,
Value = m.Language
}).ToList();
return View(model);
}
I am working on a Asp.Net Core 2.0 project and i want to seed AspnetUser, AspNetRoles and AspNetUserRoles tables. I create a class to seed database like this:
public class SeedData
{
public SeedData()
{
}
public static async Task Seeding(UserManager<ApplicationUser> userManager, RoleManager<ApplicationRole> roleManager, ApplicationDbContext context)
{
if (!context.Roles.Any())
{
context.Roles.AddRange(
new ApplicationRole
{
Id = "b562e963-6e7e-4f41-8229-4390b1257hg6",
Description = "This Is Admin User",
Name = "Admin",
NormalizedName = "ADMIN"
});
context.SaveChanges();
}
if (!context.Users.Any())
{
ApplicationUser user = new ApplicationUser
{
FirstName = "MyName",
LastName = "MyFamily",
PhoneNumber = "9998885554",
UserName = "saedbfd",
Email = "myEmail#email.com",
gender = 1
};
IdentityResult result = await userManager.CreateAsync(user, "123aA#");
if (result.Succeeded)
{
ApplicationRole approle = await roleManager.FindByIdAsync("b562e963-6e7e-4f41-8229-4390b1257hg6");
if (approle != null)
{
await userManager.AddToRoleAsync(user, "Admin");
}
}
}
}
}
Above code is my seed class that insert data in 3 tables : AspNetUsers,AspNetRolse and AspNetUserRoles
ApplicationRole Model :
public class ApplicationRole : IdentityRole
{
public string Description { get; set; }
}
ApplicationUser Model :
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public byte gender { get; set; }
}
And Finally this is my Program.cs Class:
public class Program
{
public static void Main(string[] args)
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var userManager = services.GetRequiredService<UserManager<ApplicationUser>>();
var roleManager = services.GetRequiredService<RoleManager<ApplicationRole>>();
var context = services.GetRequiredService<ApplicationDbContext>();
SeedData.Seeding(userManager,roleManager,context);//<---Do your seeding here
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding the database.");
}
}
host.Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
And i add this code to configure method in startup.cs:
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
context.Database.Migrate();
}
Everithing is good and after run application database create automatically and all tables created and insert recodes in AspNetUsers and AspNetRoles but there is a problem. The problem is not inserted any rows in AspNetUserRoles in seed class.
What's wrong with my code?
I could solve my problem by changing in SeedData class
public class SeedData
{
public SeedData()
{
}
public static async Task Seeding(UserManager<ApplicationUser> userManager, RoleManager<ApplicationRole> roleManager, ApplicationDbContext context)
{
if (!context.Roles.Any())
{
context.Roles.AddRange(
new ApplicationRole
{
Id = "b562e963-6e7e-4f41-8229-4390b1257hg6",
Description = "This Is AdminUser",
Name = "Admin",
NormalizedName = "ADMIN"
});
context.SaveChanges();
}
if (!context.Users.Any())
{
ApplicationUser user = new ApplicationUser
{
FirstName = "MyFirstName",
LastName = "MyLastName",
PhoneNumber = "9998885554",
UserName = "saedbfd",
NormalizedUserName = "SAEDBFD",
Email = "MyEmail#Email.com",
NormalizedEmail="MYEMAIL#EMAIL.COM",
gender = 1,
PasswordHash = "AQAAAAEAACcQAAAAEH9MTIiZG90QJrMLt62Zd4Z8O5o5MaeQYYc/53e2GbawhGcx2JNUSmF0pCz9H1AnoA==",
LockoutEnabled = true,
SecurityStamp = "aea97aa5-8fb4-40f2-ba33-1cb3fcd54720"
};
context.Users.Add(user);
context.SaveChanges();
IdentityUserRole<string> ur = new IdentityUserRole<string>();
ur.RoleId = "b562e963-6e7e-4f41-8229-4390b1257hg6";
ur.UserId = user.Id;
context.UserRoles.Add(ur);
context.SaveChanges();
}
}
all data inserted correctly in database and everything is ok.