I've used ASP.NET Identity 2 for creating a registration user logic, and I have an exception at HttpContext.GetOwinContext().GetUserManager().
What could be a problem? Thank you for any advise.
There is registration controller
public class AccountController : Controller
{
private ApplicationUserManager UserManager
{
get
{
return HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
}
public ActionResult Register()
{
return View();
}
[HttpPost]
public async Task<ActionResult> Register(RegisterUserModel model)
{
if (ModelState.IsValid)
{
AppUser user = new AppUser { UserName = model.Email, Email = model.Email };
IdentityResult result = await UserManager.CreateAsync(user);
if (result.Succeeded)
{
return RedirectToAction("Login", "Account");
}
else
{
foreach (string error in result.Errors)
{
ModelState.AddModelError("", error);
}
}
}
return View(model);
}
}
ApplicationUserManager logic
public class ApplicationUserManager : UserManager<AppUser>
{
public ApplicationUserManager(IUserStore<AppUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options,
IOwinContext context)
{
IdentificationContext db = context.Get<IdentificationContext>();
ApplicationUserManager manager = new ApplicationUserManager(new UserStore<AppUser>(db));
return manager;
}
}
Registration model
public class RegisterUserModel
{
[Required]
[StringLength(255)]
[RegularExpression(#"[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,4}")]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
[StringLength(255, MinimumLength = 5)]
public string Password { get; set; }
[Required]
[System.ComponentModel.DataAnnotations.Compare("Password")]
[DataType(DataType.Password)]
public string PasswordConfirm { get; set; }
}
Model that inherit from IdentitiyUSer model
public class AppUser : IdentityUser
{
public AppUser() { }
}
Startup class
public void Configuration(IAppBuilder app)
{
app.CreatePerOwinContext<IdentificationContext>(IdentificationContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
});
}
There is an output of exception
enter image description here
You need to add setting (owin:AutomaticAppStartup) in web.config
<add key="owin:AutomaticAppStartup" value="true"/>
If it still doesn't work, add below setting specifying your startup class. This is because the default convention for the Startup class is [AssemblyName].Startup. If you're no longer following that convention you'll need to specify the full name of your Startup class in the Web.Config.
<add key="owin:AppStartup" value="[Namespace].Startup, [AssemblyName]" />
Hope it helps.
Related
I created a webapi by looking at the ms basic documentation.
ms Doc
it was work
todoitems
Besides todoitems I
Because I wanted to use it in the form of Avatar Chart
Insert the model Avatarchart, create Avatarchartcontext, and make the controller as a scaffold.
solution view
However, when I tried to receive data as a post, the data always came in null.
error
null
this is code
[Route("api/AvatarCharts")]
[ApiController]
public class AvatarChartsController : ControllerBase
{
private readonly AvatarChartContext _context;
public AvatarChartsController(AvatarChartContext context)
{
_context = context;
}
// GET: api/AvatarCharts
[HttpGet]
public async Task<ActionResult<IEnumerable<AvatarChart>>> GetAvatarCharts()
{
return await _context.AvatarCharts.ToListAsync();
}
// GET: api/AvatarCharts/5
[HttpGet("{modelId}")]
public async Task<ActionResult<AvatarChart>> GetAvatarChart(long modelId)
{
var avatarChart = await _context.AvatarCharts.FindAsync(modelId);
if (avatarChart == null)
{
return NotFound();
}
return avatarChart;
}
// PUT: api/AvatarCharts/5
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPut("{modelId}")]
public async Task<IActionResult> PutAvatarChart(long modelId, AvatarChart avatarChart)
{
if (modelId != avatarChart.modelId)
{
return BadRequest();
}
_context.Entry(avatarChart).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!AvatarChartExists(modelId))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
// POST: api/AvatarCharts
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPost]
public async Task<ActionResult<AvatarChart>> PostAvatarChart( AvatarChart avatarChart)
{
_context.AvatarCharts.Add(avatarChart);
await _context.SaveChangesAsync();
return CreatedAtAction("GetAvatarChart", new { modelId = avatarChart.modelId }, avatarChart);
}
// DELETE: api/AvatarCharts/5
[HttpDelete("{modelId}")]
public async Task<IActionResult> DeleteAvatarChart(long modelId)
{
var avatarChart = await _context.AvatarCharts.FindAsync(modelId);
if (avatarChart == null)
{
return NotFound();
}
_context.AvatarCharts.Remove(avatarChart);
await _context.SaveChangesAsync();
return NoContent();
}
private bool AvatarChartExists(long modelId)
{
return _context.AvatarCharts.Any(e => e.modelId == modelId);
}
}
public class AvatarChartContext :DbContext
{
public AvatarChartContext(DbContextOptions<AvatarChartContext> options) : base(options)
{
}
public DbSet<AvatarChart> AvatarCharts { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AvatarChart>().HasKey(c => c.modelId);
}
}
public class AvatarChart
{
[Key]
public long modelId;
public string colorCode;
public long dateTime; //ex 20210101130000
public string name;
public string diagnose;
}
swagger
add postgressql dbenter image description here
Update:
You missed the {get; set;}.
public class AvatarChart
{
[Key]
public long modelId {get; set;}
public string colorCode {get; set;}
public long dateTime {get; set;} //ex 20210101130000
public string name {get; set;}
public string diagnose {get; set;}
}
Can you make these changes and tell me what value is being returned on the variable result. Also, can you validate your ModelState first?
[HttpPost]
public async Task<ActionResult> PostAvatarChart( AvatarChart avatarChart)
{
await _context.AvatarCharts.AddAsync(avatarChart);
var result = await _context.SaveChangesAsync() > 0;
return CreatedAtAction("GetAvatarChart", new { modelId = avatarChart.modelId }, avatarChart);
}
I am a beginner developer and I have an issue in Query handler when using throw new RestException(HttpStatusCode.Unauthorized)
this is my query handler:
namespace Application.User
{
public class Login
{
public class Query : IRequest<AppUser>
{
public string Email { get; set; }
public string Password { get; set; }
}
public class QueryValidator : AbstractValidator<Query>
{
public QueryValidator()
{
RuleFor(x => x.Email).NotEmpty();
RuleFor(x => x.Password).NotEmpty();
}
}
public class Handler : IRequestHandler<Query, AppUser>
{
private readonly UserManager<AppUser> _userManager;
private readonly SignInManager<AppUser> _signUserManager;
public Handler(UserManager<AppUser> userManager, SignInManager<AppUser> signInManager)
{
_userManager = userManager;
_signUserManager = signInManager;
}
public async Task<AppUser> Handle(Query request, CancellationToken cancellationToken)
{
var user = await _userManager.FindByEmailAsync(request.Email);
if (user == null)
throw new RestException(HttpStatusCode.Unauthorized);
var result = await _signUserManager.CheckPasswordSignInAsync(user, request.Password, false);
if (result.Succeeded)
{
//TODO : generate token
return user;
}
throw new RestException(HttpStatusCode.Unauthorized);
}
}
}
}
Trying to do simple chat and sending user to the userTracker when he/she is connected
public override async Task OnConnectedAsync()
{
var user = Helper.GetUserInformationFromContext(Context);
await this.userTracker.AddUserAsync(Context.Connection, user);
await Clients.All.SendAsync("UsersJoined", new UserInformation[] { user });
await Clients.All.SendAsync("SetUsersOnline", await GetOnlineUsersAsync());
await base.OnConnectedAsync();
}
but in the old versions HubCallerContext is like this :
public HubCallerContext(HubConnectionContext connection);
public HubConnectionContext Connection { get; }
public ClaimsPrincipal User { get; }
public string ConnectionId { get; }
the version I am using ( 2.3.0 ) is like
protected HubCallerContext();
public abstract string ConnectionId { get; }
public abstract string UserIdentifier { get; }
public abstract ClaimsPrincipal User { get; }
public abstract IFeatureCollection Features { get; }
public abstract CancellationToken ConnectionAborted { get; }
public abstract void Abort();
So how can I get the missing Connection ?
You simple have to inject it where you use it
Sample:
public class YourClassWhereYouNeedHubContext
{
// Inject into constructor
public YourClassWhereYouNeedHubContext (IHubContext<VarDesignHub> hubcontext)
{
HubContext = hubcontext;
...
}
private IHubContext<VarDesignHub> HubContext
{
get;
set;
}
}
Then you can also call
await this.HubContext.Clients.All.InvokeAsync("Completed", id);
Please read also:
Call SignalR Core Hub method from Controller
Allright! So I extended my IdentityUser but it is not saving my Users anymore. The code samples can be viewed below. I am trying to seed my database with an admin user but it is not being stored. I have tried running a debugger on my seeds, but it doesn't trigger on anything. So I'm kinda lost. So, here is the code.
My extended User Class:
public class User : IdentityUser, IBaseEntity
{
public virtual ICollection<TimeLogEntry> TimeLogEntries { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
public bool IsRemoved { get; set; }
public virtual User CreatedBy { get; set; }
public virtual User UpdatedBy { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User> manager, string authenticationType)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
// Add custom user claims here
return userIdentity;
}
}
Then ofcourse the Context that inherits from the IdentityDbContext:
public class Context : IdentityDbContext<User>, IContext
{
public Context()
: base("MyConnection", throwIfV1Schema: false)
{
Configuration.ProxyCreationEnabled = false;
}
// DBSETS
public static Context Create() => new Context();
// MODELBUILDER
}
and finaly my seed:
protected override void Seed(Context context)
{
// Launch debugger on seeds
//if (System.Diagnostics.Debugger.IsAttached == false)
// System.Diagnostics.Debugger.Launch();
SeedUsers(context);;
}
private void SeedUsers(Context context)
{
var manager = new UserManager<User>(new UserStore<User>(context));
var adminUser = new User
{
UserName = "Admin",
Email = "admin#test.com"
};
if (!manager.Users.Any())
{
manager.Create(adminUser, "Admin");
}
}
I hope someone can help me with this!
The Seed() that is inside your initializer will only run when your database is recreated - for instance when you are using DropCreateDatabaseIfModelChanges.
If you use migrations (MigrateDatabaseToLatestVersion initializer), there is another Seed() that runs every time you apply the migration using update-database.
http://blog.oneunicorn.com/2013/05/28/database-initializer-and-migrations-seed-methods/
I've been trying to inherit IdentityUser to make my own class which uses Identity and still writes to my database and I keep getting this error when I try to call my registration post method:
{
"$id": "1",
"Message": "The request is invalid.",
"ModelState": {
"$id": "2",
"": [
"Name cannot be null or empty."
]
}
}
I tried number of things, but nothing works.For example when I try to set UserName field of IdentityUser it says it's impossible because it doesn't exist in the context.
The important thing to mention would be that I am using ADO.NET database first model for the account :)
This is the class:
public partial class Account :IdentityUser
{
public Account()
{
this.Families = new HashSet<Family>();
}
public long idAccount { get; set; }
public string email { get; set; }
public string password { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public virtual ICollection<Family> Families { get; set; }
}
This is my authentication repository class:
public class AuthRepository :IDisposable
{
private DAKPAKEntities _ctx;
private UserManager<Account> _userManager;
public AuthRepository()
{
_ctx = new DAKPAKEntities();
_userManager = new UserManager<Account>(new UserStore<Account>(_ctx));
}
public async Task<IdentityResult> RegisterUser(Account userModel)
{
Account user = new Account
{
firstName = userModel.firstName,
lastName = userModel.lastName,
email=userModel.email
};
var result = await _userManager.CreateAsync(user,userModel.password);
return result;
}
}
And this is the controller that calls the repository:
// POST api/Account/Register
[AllowAnonymous]
[Route("Register")]
public async Task<IHttpActionResult> Register(Account userModel)
{
IdentityResult result = await _repo.RegisterUser(userModel);
IHttpActionResult errorResult = GetErrorResult(result);
if (errorResult != null)
{
return errorResult;
}
return Ok();
}
I am new to this, and am out of options to try. I did almost everything that's usually suggested for this type of error, please help :)
It looks like you haven't done everything that is required in order to change the way ASPNet Identity stores the user information in the database.
Suggest you start here: Overview of Custom Storage Providers for ASP.NET Identity