My Post method
[HttpPost]
public async Task<IActionResult> Register()
{
User user = new User { Email = "asfa#gmail.com", UserName = "asfa#gmail.com" };
var result = await _userManager.CreateAsync(user, "SS22!faasd");
if (result.Succeeded)
{
// install cookie
await _signInManager.SignInAsync(user, false);
}
else
{
foreach (var error in result.Errors)
{
//how can i see my errors here
}
}
return Ok();
}
I am trying to create user with UserManager and CreateAsync method, but it doesn't work. In postman I always get 200 OK.
UserManager is connected to my database, because I can get my users with get method.
Also I dont have any cshtml files, so I cant output errors on page.
In postman I always get 200 OK.
You are always getting 200 OK because at the end of a method you are returning OK() method.
In order to have some other status messages consider checking if the user is created and only then return OK() method otherwise either throw an exception, like this:
throw new ArgumentException("Wasn't able to add user")
or return some HTTPError, like this:
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Not able to create user");
Note: you can also throw an exception if the user already exists when you try to add a new user.
I am trying to create user with UserManager and CreateAsync method, but it doesn't work.
This is connected with your _userManager.CreateAsync methods logic. Please revisit it.
To find error, I return OK(result), and see this error in postman.
Related
I implemented an IUserRepository, where I implement login and registration in my UserRepository; this is my code
public async Task<IActionResult> LoginAsync([FromBody] UserCred user)
{
var result = await _signInManager.PasswordSignInAsync(user.username, user.password, user.rememberMe, false);
if (result.Succeeded)
{
var token = _jwtAuthenticationManager.Authenticate(user.username, user.password);
if (token == null)
return Unauthorized();
return Ok(token);
}
return BadRequest();
}
However, I'm getting an error of:
The name "BadRequest" does not exist in the current context
Same for the Ok and Unauthorized.
However, I did not have this issue when I was implementing these calls directly in my userController. I suppose I can only return BadRequest in the controller? Is there any way I can overcome this since, if it's not IActionResult, how will I check if results.Succeeded?
Moreover, this is my UserController:
[HttpPost]
[AllowAnonymous]
[Route("login")]
public async Task<IActionResult> Login([FromBody] UserCred user)
{
return await _userRepository.LoginAsync(user);
}
BadRequest() is a method of the controller itself.
It's better to return a value from IUserRepository, e.g. null or token, and then in the controller map that value to Ok or BadRequest response.
Making a decision about the response type is the responsibility of the controller itself.
Code like this placed in the controller should do the job:
token = await _userRepository.LoginAsync(user);
return token == null ? BadRequest() : Ok(token);
It is possible by returning EG.
new BadRequestObjectResult("some error");
But, you shouldn't be doing anything web related in a repository!
Instead you should throw an appropriate exception from your repository and catch it in the controller. Then, when you catch the exception, return BadRequest from there.
Also, be sure you are returning the correct response.
BadRequest means there was something wrong with the request - maybe the username or password was null, etc. This should be checked before even attempting to hit the repository.
Unauthorized may be a better response if authentication fails.
Then, if there is genuinely an error, don't hide it, it will cause problems later when you have lots of endpoints you can't debug, return a 500 response (but don't include the exception details in production)
I am trying to create user with UserManager and CreateAsync method, but it doesn't work. Im postman I always get 200 OK
My Post method
[HttpPost]
public async Task<IActionResult> Register()
{
User user = new User { Email = "asfa#gmail.com", UserName = "asfa#gmail.com" };
var result = await _userManager.CreateAsync(user, "SS22!faasd");
if (result.Succeeded)
{
// install cookie
await _signInManager.SignInAsync(user, false);
}
else
{
foreach (var error in result.Errors)
{
//how can i see my errors here
}
}
return Ok();
}
Also I dont have any cshtml files, so I cant output them on page.
Or you can just explain, why my CreateAsync method doesn't work.
You could just return the result from the server every time:
return Ok(result);
It will be serialized so you can see it.
I have a standard form made with Html.BeginForm that posts to an async action in a controller. It looks like this (this is an outline, not the actual code):
[HttpPost]
public async Task<ActionResult> Index(UserCreds creds)
{
try
{
if (ModelState.IsValid)
{
var user = await loginRep.Login(creds.Username, creds.Password);
if (user != null)
{
_context.SetAuthenticationToken(user);
return RedirectToAction("Index", "Landing");
}
else
{
ModelState.AddModelError("", "Login failed.");
}
}
else
{
_logger.Debug(string.Format("User failed authentication."));
}
}
catch (Exception ex)
{
throw new HttpException(500, string.Format("An error occured during the execution of the action {0} from Controller {1}", "Index", "Login"), ex);
}
return View();
}
Upon submitting the form for the first time, the browser will be awaiting indefinitely for a response, even though one can see stepping with the debugger that the RedirectToAction is reached. If one then stops the request in the browser, and simply submit again, the redirect happens. All subsequent attempts to login also redirect successfully. The authentication token is also somehow not set during that first attempt.
This likely has something to do with delegate usage inside loginRep.Login. Inside it eventually does something like this:
private async Task<LoginResponse> SendLoginRequest(string username, string password)
{
TaskCompletionSource<LoginResponse> tcs = new TaskCompletionSource<LoginResponse>();
LoginResponseCallback callback = null;
callback = new LoginResponseHandler(delegate (response) {
securityService.OnLoginResponse -= callback;
tcs.SetResult(response);
});
securityService.OnLoginResponse += callback;
securityService.SendLoginRequest(username, password);
return await tcs.Task;
}
Does anyone understand what is happening? If it's a deadlock, I wouldn't have expected to see the debugger reach the redirect, nor would I have expected the login to work for all attempts other than the first.
Note the form does work the first time if one just skips sending a login request and just hardcode what a successful response would look like.
Ok. The issue was resolved. There was nothing wrong with the two code samples I showed. The error was with setting up my security service, so it was unfortunately rather specific to this application.
That said, the infinite waiting happened because the Application_Error in Global.asax.cs was effectively swallowing certain exceptions. Once I changed it to always redirect to my error page no matter what, at least it immediately redirected to the error page when the issue happened, instead of hanging from the user's perspective.
All I have installed the latest ASP.NET Identitiy following http://blogs.msdn.com/b/webdev/archive/2014/03/20/test-announcing-rtm-of-asp-net-identity-2-0-0.aspx. Following the NuGet installation, I have intellisense access to the DeleteUser/DeleteUserAsync methods and the code compiles fine. However, at run-time when I invoke this method I get
Specified method is not supported.
Stack Trace:
[NotSupportedException: Specified method is not supported.]
Microsoft.AspNet.Identity.EntityFramework.UserStore`1.DeleteAsync(TUser user) +59
The cause is clear, but how can I compile this and it now execute? What do I have to do to be able to delete a user using UserManager?
The current code I am using to do this is
[AllowAnonymous]
public async Task<ActionResult> RemoveUser(string userName)
{
ApplicationUser user = null;
if (ModelState.IsValid)
{
user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (user.IsAdmin != null && (bool)user.IsAdmin)
{
var userToRem = await UserManager.FindByNameAsync(userName);
IdentityResult result = await UserManager.DeleteAsync(userToRem); <- EXCEPTION
// If successful
if (!result.Succeeded)
return new HttpStatusCodeResult(HttpStatusCode.ServiceUnavailable);
}
}
return RedirectToAction("Index", "Tools");
}
I am not interested in anything fancy, all I want to do is remove a user and for some reason it is giving me a royal ball ache. Any other method would be appreciated.
Thanks for your time.
In ASP.NET Identity v1, DeleteAsync was not supported. Based on the error message you are seeing, it looks like you are referencing v1.
Try updating your ASP.NET Identity packages to v2.1.0 via Nuget.
I have an MVC5 application, ASP.NET, that, when creating a new record and clicking submit, it calls my WebAPI (version 2 - the new one) to insert the record into the database. Problem is, it's not hitting the POST method in my WebAPI. Anyways, here's my MVC5, front end application code for "Create":
[HttpPost]
public ActionResult Create(BulletinBoard bulletinBoard)
{
bulletinBoard.CreatedDate = DateTime.Now;
bulletinBoard.CreatedBy = HttpContext.User.Identity.Name;
response = client.PostAsJsonAsync("api/bulletinboard", bulletinBoard).Result;
if (response.IsSuccessStatusCode)
{
return View("Index");
}
else
{
LoggerHelper.GetLogger().InsertError(new Exception(string.Format(
"Cannot create a new feedback record due to HTTP Response Status Code not being successful: {0}", response.StatusCode)));
return View("Problem");
}
}
I already defined "client" in my constructor and gave it the base URL for my WebAPI - keep in mind that GET works - so it's not a problem with my URL. I can also manually go to my WebAPI URL and get data back in my browser.
Here's my WebAPI code:
// POST api/bulletinboard
public HttpResponseMessage PostBulletinBoard(BulletinBoard bulletinBoard)
{
if (ModelState.IsValid)
{
db.BulletinBoards.Add(bulletinBoard);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, bulletinBoard);
return response;
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
This worked when I was using WebAPI version 1 which had a different naming convention for the GET and POST and PUT methods.
So, when the URL for the POST request is called (the line that's response = client.PostAsJsonAsync...), the request never hits my POST method in my WebAPI and consequently, no records are inserted into my database. What am I doing wrong?
According to the comments it appears that you have POSTed invalid data (according to the validation rules you defined in your BulletinBoard model) and this validation simply fails. So to fix the issue make sure you are sending valid data.
I think there might be a few reasons why it doesn't hit your post method. Here is my example of Post method. The things you should note is method name and FromBody attribute
public async Task<HttpResponseMessage> Post([FromBody]FoodProduct foodProduct)
{
UnitOfWork.FoodRepository.Edit(foodProduct);
await UnitOfWork.SaveAsync();
return Request.CreateResponse(HttpStatusCode.OK);
}
I also like to use this new RoutePrefix Attribute on my controller, it works perfectly and looks good.
[RoutePrefix("api/Food")]
public class FoodController : BaseApiController
{
///some code here
}