Excellent Videos!! learning alot. Did notice that the result.Succeeded check at the bottom of the loop is not needed. also there is no reaction to if result does not succeed. i realise with the if statements that it would never fail however for the pedantic people out there: I added a validation summary div above the card footer div and changed the result.Suceeded if statement at the bottom of the loop to pickup any failures and add messages to the ModelState. Then as there is a failure I wanted the user not to redirect away but show this view with actual information so the user can try again.. so I corrected the IsSelected for the failed item. Like so: @for (int i = 0; i < Model.Count; i++) {
@Model[i].UserName
}
Cancel and instead of the result.Succeeded if statement at the bottom of the loop.. if (!result.Succeeded) { foreach (var error in result.Errors) { ModelState.AddModelError(string.Empty, $"User '{user.UserName}' : {error.Description}"); model[i].IsSelected = await this.userManager.IsInRoleAsync(user, role.Name); } if (i >= (model.Count - 1)) { return View(model); } } Hope this satisfies the pedantic! :)
FYI: If you use, foreach in the EditUsersInRole view, it won't work properly. The input-id tag won't be different, clicking won't work properly, and it will return no list in the post request. Thank youu
Had an error with the foreach loop in the code. Saying datareader need to be closed, fixed it by adding "MultipleActiveResultSets=True;" to my connecting string in appsettings.json It looks like this now: "EmployeeDBConnection": "server=(localdb)\\MSSQLLocalDB;database=EmployeeDB;Trusted_Connection=true;MultipleActiveResultSets=True;" Dont know if its only in ASP.NET core 3 its an error
The best way to fix this is convert 'ToListAsync' var users = await userManager.Users.ToListAsync(); var model = new List(); foreach(var user in users) { var userRoleViewModel = new UserRoleViewModel { UserId = user.Id, UserName = user.UserName }; or foreach(var user in await userManager.Users.ToListAsync()) {
The video is great as usual keep it up bro. I'm working with ASP(3.1) and i encountered a problem: i have chose 2 users in a role and checked them out in the db they were there,, but when i come back to the "/Administration/EditRole/" to uncheck or check other,, I found all the checkboxs are unchecked already
If I block this portion of the code, the functionality is still intact: if (result.Succeeded) { if (i < model.Count - 1) continue; else return RedirectToAction("EditRole", new { Id = role.Id }); } Anybody found otherwise. I am trying to slice and dice from all possible aspects. Great content as always. Sometimes it feels overwhelming when presented with so much knowledge at one shot.
In additional to this I guess it is possible to remove result variable // IdentityResult result = null; if (model[i].IsSelected && !(await userManager.IsInRoleAsync(user, role.Name ))) { /*result =*/ await userManager.AddToRoleAsync(user, role.Name); } else if (!model[i].IsSelected && await userManager.IsInRoleAsync(user, role.Name)) { /*result =*/ await userManager.RemoveFromRoleAsync(user, role.Name); } else { continue; }
hi Venkat, I have a question: In the view you use a for-loop. I tried myself before watching you, and choiced a foreach loop, but the post method received an empty list as the model ... Why? what's the difference between for and foreach loop? I always thought, they are same, as long as you don't need the indexes.
Very good question. We discussed exactly that in the following video. This explains why the default model binder failed to bind the values from the HTML input elements to the list parameter on the controller action. ruclips.net/video/Qobkh8gEP6Q/видео.html
Dear Instructor, Thanks for the awesome course. I do have a doubt since I'm using .net core 6. The said method in the video works flawlessly for retrieving users in a role. Can we use GetUsersInRoleAsync in this same example and retrieve the details in The Role Edit View?
Error open DataReader Solution: For anyone experiencing an error with their DataReader solution already being open the problem is that "userManager.Users" is not asynchronous. One solution to this is to extend it with the following: "userManager.Users.ToListAsync()" be sure to #include Microsoft.EntityFrameworkCore; in order to access this extension method. CODE FROM VIDEO WITH ERROR //foreach (var user in userManager.Users) //{ // if (await userManager.IsInRoleAsync(user, role.Name)) // { // model.Users.Add(user.UserName); // } //} NEW CODE WITH EXTENSION //foreach (var user in await userManager.Users.ToListAsync()) //{ // if (await userManager.IsInRoleAsync(user, role.Name)) // { // model.Users.Add(user.UserName); // } //} A proposed solution for some is to add MultipleActiveResultSets=True; to their connection string however, if you're using MySQL Server instead of SQLServer this will not be available.
Even better is to include "MultipleActiveResultSets=True;" in your connection string as noted by Mikkel Heyberg below. This is "better" because using "ToList" will read all user accounts into memory. The alternative approach using "MultipleActiveResultSets=True;" iterates through each user one at a time without reading all users into memory at once. This obviously matters when you have a very large user database.
@@rogerwarford1517 I have this solution at the end of my comment already for those that can use it. The problem is that multiple active result sets are not supported on every type of SQL server. For instance, in my personal use case, we were using MySQL Server rather than the default Microsoft SQL Server. MySQL Server doesn't support such a connection string.
Hi Venkat, thanks for the awesome tutorial, Just wanted to check how is roleId is passed from the view to the controller as we didn't specify it as a routing parameter in the submit button, or did the model binder could bind the value to the parameter in the action method?
I think it's because the "roleId" query string still appears in the URL when the form is submitted. The HttpPost action method knows to get the "roldId" from the URL as it "sees" roleId there.
Thank you for a video. Could you please explain why do we need this code: if (result.Succeeded) { if (i < (model.Count - 1)) continue; else return RedirectToAction("EditRole", new { Id = roleId }); } If remove that part we will have same functionality, loop in "for" loop and RedirectToAction("EditRole", new { Id = roleId }); after loop
In EditUsersInRole View if I change for loop to foreach I dont get any information to List model. Please could you explain me why it is? @foreach (var user in Model) {
Hello Martin - This is a great question. I am glad you asked this question. When we use foreach loop the following are the Names of the dynamically generated html elements.
pragim@pragimtech.com
test1@pragimtech.com However when we use a for loop with an indexer, the following are the Names. Notice the names are using with integral indexer. Model binder in ASP.NET Core MVC uses the unique names of these html input elements to automatically map the values to the controller action list parameter. When we use a foreach loop the names are not unique so the model binder has no clue that these values must be mapped to the action list parameter. Hence the list parameter is empty. Hope this answers your question.
hi venkat i have one doubt, how can we determine result = await userManager.AddToRoleAsync(user, role.Name); method is used to add the rows to this ' AspNetUserRoles' table by viewing in code only? . In the this video you identified and showed the 'bridge table' directly.... how could we know that in code on which table this AddToRoleAsync method going to insert the rows without going to see the tables directly in sql server object explorer. am waiting for your reply ;)
Dear Kudvenkat! Very thanks for your video! Could you explain please, why are there no any users in "Users in this role" section on "EditRole" post method?
Kudvenkat I wish you give us some tutorial about CQRS in c# entity framework . I have seen lots of videos on this topic but nothing can match your tutorial skills I must say.
Dear kudvenkat Sir, Your tutorials are excellent and very easy to understand and implelment. However, I have encountered a problem though. At this step, at tutorial no. 80, If I try to login, it throws the validation error "The ReturnUrl Field is Required." I got the cause of the problem that, since Login method uses ReturnUrl as a parameter, and ModelState.Isvalid() methos is in place, it doesn't allow me to login unless I want to go to any other page which requires login. Please help me solve this. Thanking you in advance. 😊
one question that's answer i didn't get in any where. if roles are created in runtime by administrator and that role name we dont know then how to set access of controller and action with that role. you are assigining role here manually with control level and action level. pl help me urgently. thanks in advance
If each IsInRoleAsync call results to a database call, calling it in 'if' and then again in 'else' potentially can double the database access for each user. Also, I do not find any point to do a result.Succeeded check, since there is no handling if error occurred anyway. This means any code within if(result.Succeeded) are also redundant. So, my version is: foreach(var userRole in model) { ApplicationUser user = await _userManager.FindByIdAsync(userRole.UserId); if (user == null) continue; if(await _userManager.IsInRoleAsync(user, role.Name)) { if (!userRole.IsSelected) await _userManager.RemoveFromRoleAsync(user, role.Name); } else { if (userRole.IsSelected) await _userManager.AddToRoleAsync(user, role.Name); } } return RedirectToAction("EditRole", "Administration", new { Id = role.Id }); Or have I missed something?
I am getting an exception when I click the add user to roles button on the editRoles page: An unhandled exception occurred while processing the request. AmbiguousMatchException: The request matched multiple endpoints. Matches: Fitness1stMVCWeb.Controllers.AdministrationController.EditUsersInRole (Fitness1stMVCWeb) Fitness1stMVCWeb.Controllers.AdministrationController.EditUsersInRole (Fitness1stMVCWeb) Microsoft.AspNetCore.Routing.Matching.DefaultEndpointSelector.ReportAmbiguity(CandidateState[] candidateState) Must be in the AdministrationController in the last bit of code. Code: for(int i = 0; i < model.Count; i++) { var user = await userManager.FindByIdAsync(model[i].UserId); IdentityResult result = null; if (model[i].IsSelected && !(await userManager.IsInRoleAsync(user, role.Name))) { result = await userManager.AddToRoleAsync(user, role.Name); } else if (!model[i].IsSelected && await userManager.IsInRoleAsync(user, role.Name)) { result = await userManager.RemoveFromRoleAsync(user, role.Name); } else { continue; } if (result.Succeeded) { if (i < (model.Count - 1)) continue; else return RedirectToAction("EditRole", new { Id = roleId }); } } return RedirectToAction("EditRole", new { Id = roleId}); } } } any help would be great! I love this series, I have learned so much, but I wish I had the code for the AdministrationController to campare with my code. Would make watching a learning a bit less stressful. Thanks again!
submit: The button submits the form data to the server. This is the default if the attribute is not specified, or if the attribute is dynamically changed to an empty or invalid value. reset: The button resets all the controls to their initial values. button: The button has no default behavior. It can have client-side scripts associated with the element's events, which are triggered when the events occur.
Dear Venkat, Regarding the following code that are present in HttpGet EditUsersInRole Action, could you explain why do we need to populate UserId, UserName, and IsSelected properties on the userRoleViewModel ??? var model = new List(); foreach (var user in userManager.Users) { var userRoleViewModel = new UserRoleViewModel { UserId = user.Id, UserName = user.UserName }; if (await userManager.IsInRoleAsync(user, role.Name)) { userRoleViewModel.IsSelected = true; } else { userRoleViewModel.IsSelected = false; } model.Add(userRoleViewModel); } return View(model); }
I think its not working as it is supposed to anymore... After my failure i did ctrl+c, ctrl+v and got same result. - When I want to add user to role and i check one, only this one has this role and other users are no longer admins for example. When I want to uncheck one user, the result is only user i unchecked is admin and no others are. Maybe I did something wrong but I dont see how could I made any mistake when copy-paste :D
I am getting NullReferenceException error in "model.Users.Add(user.UserName)" part while calling async Task EditRole(string id) method .I am not sure why but think it has something to do with the async functionality .
I found a solution for it . I guess it was because the Users property (List) of EditRoleViewModel was not initialized. I added an initialization and now it's working fine. EditRoleViewModel mylocal = new EditRoleViewModel { Id = role.Id, RoleName = role.Name, Users=new List() };
Hi Kudvenket, When i run this code I found Error :-- UserManager was null " foreach (var user in userManager.Users) " and An unhandled exception occurred while processing the request. NullReferenceException: Object reference not set to an instance of an object. Test.Controllers.AdministrationController.EditUsersInRole(string roleId) in AdministrationController.cs, line 150 Controllers.AdministrationController.EditUsersInRole(string roleId) in AdministrationController.cs + foreach (var user in userManager.Users) Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments) System.Threading.Tasks.ValueTask.get_Result() Please suggest or help to remove this Error
hello Thank for your great tutorial I think this part is not important because the loop will continue by its logic and it's will done automatically // HttpPost EditUsersInRole Action else { continue; } if (result.Succeeded) { if (i < (model.Count - 1)) continue; else return RedirectToAction("EditRole", new { Id = roleId }); }
for post one just use like following public async Task EditUsersInRole(List users, string roleId) { var role = await _roleManager.FindByIdAsync(roleId); if (role == null) { ViewBag.ErrorMessage = $"Role with id -{roleId} cannot be found"; return View("NotFound"); } foreach (var user in users) { var applicationUser = await _userManager.FindByIdAsync(user.UserId); var isRoleUserExist = await _userManager.IsInRoleAsync(applicationUser, role.Name); switch (user.IsSelected) { case true when !isRoleUserExist: await _userManager.AddToRoleAsync(applicationUser, role.Name); break; case false when isRoleUserExist: await _userManager.RemoveFromRoleAsync(applicationUser, role.Name); break; } } return RedirectToAction("EditRole", new { Id = roleId }); }
I am getting the error "There is already an open DataReader associated with this Connection which must be closed first." in EditRole controller , please help me
@@danishmalak1520 You can chekc your database connection string. Make sure it has "MultipleActiveResultSets=True" . If it isn't put it there in the connection string and your problem should be solved. :)
Dear Venkat, Could you kindly please explain the following code that is present within the HttpPost EditUsersInRole action because I don't understand the code ? if (result.Succeeded) { if (i < (model.Count - 1)) continue; else return RedirectToAction("EditRole", new { Id = roleId }); } Thanks, Edward
Hello Edward - This code basically checks if there are more users in the collection to process. If there are more users the continue keywords skips the rest of the statements that follow it and picks up the next item in the collection to process. Hope this answers your question.
@@ymtan this is the a logic applied by venkat sir ,if the 'model.count-1>i' then iteration completes (meaning there is no users) then it goes to else block and then control redirects to editRole Acton method
@@ymtan Arrays and lists use indexes starting at 0, not 1. So if there are 2 users (count=2), they would be at index 0 and 1. Thus we subtract 1 from the model count to make sure we don't get an out of bounds error in the loop.
Adding to Tan's question, What is the use of return RedirectToAction("EditRole", new { Id = roleId }); inside for loop above when we have one outside of loop?
Microsoft Identity not providing anything new. Approach of implementation is changed and microsoft increased complexity by top up class of role manager,.... manger...... Too much coding with Identity API ...
Hi Kudvenket, When i run this code I found Error :-- UserManager was null " foreach (var user in userManager.Users) " and An unhandled exception occurred while processing the request. NullReferenceException: Object reference not set to an instance of an object. Test.Controllers.AdministrationController.EditUsersInRole(string roleId) in AdministrationController.cs, line 150 Controllers.AdministrationController.EditUsersInRole(string roleId) in AdministrationController.cs + foreach (var user in userManager.Users) Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments) System.Threading.Tasks.ValueTask.get_Result() Please suggest or help to remove this Error
Absolutely the best tutorials out there. Ever. Full stop. No question. There are none better.
Excellent Videos!! learning alot.
Did notice that the result.Succeeded check at the bottom of the loop is not needed. also there is no reaction to if result does not succeed. i realise with the if statements that it would never fail however for the pedantic people out there:
I added a validation summary div above the card footer div and changed the result.Suceeded if statement at the bottom of the loop to pickup any failures and add messages to the ModelState. Then as there is a failure I wanted the user not to redirect away but show this view with actual information so the user can try again.. so I corrected the IsSelected for the failed item.
Like so:
@for (int i = 0; i < Model.Count; i++)
{
@Model[i].UserName
}
Cancel
and instead of the result.Succeeded if statement at the bottom of the loop..
if (!result.Succeeded)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, $"User '{user.UserName}' : {error.Description}");
model[i].IsSelected = await this.userManager.IsInRoleAsync(user, role.Name);
}
if (i >= (model.Count - 1))
{
return View(model);
}
}
Hope this satisfies the pedantic! :)
This dude is the GOAT...absolute best tutorials on RUclips!!!!!
This is the best on the internet... Thank you
Thank you so much kudvenkat, I'm happy I found this resource, it's gold.
Fantastic to say the least. I have learnt a ton. Thank you so much!!!
FYI: If you use, foreach in the EditUsersInRole view, it won't work properly. The input-id tag won't be different, clicking won't work properly, and it will return no list in the post request. Thank youu
It is really amazing. To get all this from the best man for free.
Clean, smart tutorials.. as usual
Had an error with the foreach loop in the code.
Saying datareader need to be closed, fixed it by adding "MultipleActiveResultSets=True;" to my connecting string in appsettings.json
It looks like this now: "EmployeeDBConnection": "server=(localdb)\\MSSQLLocalDB;database=EmployeeDB;Trusted_Connection=true;MultipleActiveResultSets=True;"
Dont know if its only in ASP.NET core 3 its an error
Had the same error and your solution worked, thanks
The best way to fix this is convert 'ToListAsync'
var users = await userManager.Users.ToListAsync();
var model = new List();
foreach(var user in users)
{
var userRoleViewModel = new UserRoleViewModel
{
UserId = user.Id,
UserName = user.UserName
};
or
foreach(var user in await userManager.Users.ToListAsync())
{
The video is great as usual keep it up bro.
I'm working with ASP(3.1) and i encountered a problem:
i have chose 2 users in a role and checked them out in the db they were there,, but when i come back to the "/Administration/EditRole/" to uncheck or check other,, I found all the checkboxs are unchecked already
If I block this portion of the code, the functionality is still intact:
if (result.Succeeded)
{
if (i < model.Count - 1)
continue;
else
return RedirectToAction("EditRole", new { Id = role.Id });
}
Anybody found otherwise. I am trying to slice and dice from all possible aspects.
Great content as always. Sometimes it feels overwhelming when presented with so much knowledge at one shot.
In additional to this I guess it is possible to remove result variable
// IdentityResult result = null;
if (model[i].IsSelected && !(await userManager.IsInRoleAsync(user, role.Name )))
{
/*result =*/ await userManager.AddToRoleAsync(user, role.Name);
}
else if (!model[i].IsSelected && await userManager.IsInRoleAsync(user, role.Name))
{
/*result =*/ await userManager.RemoveFromRoleAsync(user, role.Name);
}
else
{
continue;
}
your videos are awesome thank you
hi Venkat, I have a question:
In the view you use a for-loop. I tried myself before watching you, and choiced a foreach loop, but the post method received an empty list as the model ...
Why? what's the difference between for and foreach loop? I always thought, they are same, as long as you don't need the indexes.
Very good question. We discussed exactly that in the following video. This explains why the default model binder failed to bind the values from the HTML input elements to the list parameter on the controller action.
ruclips.net/video/Qobkh8gEP6Q/видео.html
@foreach (var role in Model)
{
@role.UserName
}
Dear Instructor,
Thanks for the awesome course. I do have a doubt since I'm using .net core 6. The said method in the video works flawlessly for retrieving users in a role. Can we use GetUsersInRoleAsync in this same example and retrieve the details in The Role Edit View?
Great explanations! Thank you.
Awesome, Many thanks for you great video tutorial.
Error open DataReader Solution:
For anyone experiencing an error with their DataReader solution already being open the problem is that "userManager.Users" is not asynchronous. One solution to this is to extend it with the following: "userManager.Users.ToListAsync()" be sure to #include Microsoft.EntityFrameworkCore; in order to access this extension method.
CODE FROM VIDEO WITH ERROR
//foreach (var user in userManager.Users)
//{
// if (await userManager.IsInRoleAsync(user, role.Name))
// {
// model.Users.Add(user.UserName);
// }
//}
NEW CODE WITH EXTENSION
//foreach (var user in await userManager.Users.ToListAsync())
//{
// if (await userManager.IsInRoleAsync(user, role.Name))
// {
// model.Users.Add(user.UserName);
// }
//}
A proposed solution for some is to add MultipleActiveResultSets=True; to their connection string however, if you're using MySQL Server instead of SQLServer this will not be available.
Even better is to include "MultipleActiveResultSets=True;" in your connection string as noted by Mikkel Heyberg below. This is "better" because using "ToList" will read all user accounts into memory. The alternative approach using "MultipleActiveResultSets=True;" iterates through each user one at a time without reading all users into memory at once. This obviously matters when you have a very large user database.
@@rogerwarford1517 I have this solution at the end of my comment already for those that can use it. The problem is that multiple active result sets are not supported on every type of SQL server. For instance, in my personal use case, we were using MySQL Server rather than the default Microsoft SQL Server. MySQL Server doesn't support such a connection string.
@@Dugz Thank you very much.
Good Job thanks
Hi Venkat, thanks for the awesome tutorial,
Just wanted to check how is roleId is passed from the view to the controller as we didn't specify it as a routing parameter in the submit button, or did the model binder could bind the value to the parameter in the action method?
I think it's because the "roleId" query string still appears in the URL when the form is submitted. The HttpPost action method knows to get the "roldId" from the URL as it "sees" roleId there.
if get methods can read the querystring, can too the post methods
Thank you for a video. Could you please explain why do we need this code:
if (result.Succeeded)
{
if (i < (model.Count - 1))
continue;
else
return RedirectToAction("EditRole", new { Id = roleId });
}
If remove that part we will have same functionality, loop in "for" loop and RedirectToAction("EditRole", new { Id = roleId });
after loop
In EditUsersInRole View if I change for loop to foreach I dont get any information to List model. Please could you explain me why it is?
@foreach (var user in Model)
{
@user.UserName
}
Hello Martin - This is a great question. I am glad you asked this question. When we use foreach loop the following are the Names of the dynamically generated html elements.
pragim@pragimtech.com
test1@pragimtech.com
However when we use a for loop with an indexer, the following are the Names. Notice the names are using with integral indexer. Model binder in ASP.NET Core MVC uses the unique names of these html input elements to automatically map the values to the controller action list parameter. When we use a foreach loop the names are not unique so the model binder has no clue that these values must be mapped to the action list parameter. Hence the list parameter is empty. Hope this answers your question.
pragim@pragimtech.com
test1@pragimtech.com
Hello Martin - FYI, I have also made a short video on this same issue.
ruclips.net/video/Qobkh8gEP6Q/видео.html
⁷ user role I show "System.Security.Claims.ClaimsPrincipal" instead of userlist
very nice
Thanks for your video in a category .
Hi Venkat, what if i am not using the rolemanager built in class, how do i access the userInRole(),
hi venkat i have one doubt, how can we determine result = await userManager.AddToRoleAsync(user, role.Name); method is used to add the rows to this ' AspNetUserRoles' table by viewing in code only? . In the this video you identified and showed the 'bridge table' directly.... how could we know that in code on which table this AddToRoleAsync method going to insert the rows without going to see the tables directly in sql server object explorer. am waiting for your reply ;)
Amazing!!! Good job
Dear Kudvenkat! Very thanks for your video! Could you explain please, why are there no any users in "Users in this role" section on "EditRole" post method?
im getting an error in EditUsersInRole view for
(@for (int i = 0; i < Model.Count; i++)
{
})
Error: operator '
legend!!!
user creation,roles creation assigning roles to user is very easy if implemented manually.
@14:12 I cannot see you put the @model[i].UserID and @model[i].UserName to tag, how the controller can get these value.
Kudvenkat I wish you give us some tutorial about CQRS in c# entity framework . I have seen lots of videos on this topic but nothing can match your tutorial skills I must say.
Dear kudvenkat Sir,
Your tutorials are excellent and very easy to understand and implelment. However, I have encountered a problem though. At this step, at tutorial no. 80, If I try to login, it throws the validation error "The ReturnUrl Field is Required." I got the cause of the problem that, since Login method uses ReturnUrl as a parameter, and ModelState.Isvalid() methos is in place, it doesn't allow me to login unless I want to go to any other page which requires login. Please help me solve this. Thanking you in advance. 😊
one question that's answer i didn't get in any where. if roles are created in runtime by administrator and that role name we dont know then how to set access of controller and action with that role. you are assigining role here manually with control level and action level. pl help me urgently. thanks in advance
If each IsInRoleAsync call results to a database call, calling it in 'if' and then again in 'else' potentially can double the database access for each user.
Also, I do not find any point to do a result.Succeeded check, since there is no handling if error occurred anyway. This means any code within if(result.Succeeded) are also redundant.
So, my version is:
foreach(var userRole in model)
{
ApplicationUser user = await _userManager.FindByIdAsync(userRole.UserId);
if (user == null) continue;
if(await _userManager.IsInRoleAsync(user, role.Name))
{
if (!userRole.IsSelected)
await _userManager.RemoveFromRoleAsync(user, role.Name);
}
else
{
if (userRole.IsSelected)
await _userManager.AddToRoleAsync(user, role.Name);
}
}
return RedirectToAction("EditRole", "Administration", new { Id = role.Id });
Or have I missed something?
I am getting an exception when I click the add user to roles button on the editRoles page:
An unhandled exception occurred while processing the request.
AmbiguousMatchException: The request matched multiple endpoints. Matches:
Fitness1stMVCWeb.Controllers.AdministrationController.EditUsersInRole (Fitness1stMVCWeb)
Fitness1stMVCWeb.Controllers.AdministrationController.EditUsersInRole (Fitness1stMVCWeb)
Microsoft.AspNetCore.Routing.Matching.DefaultEndpointSelector.ReportAmbiguity(CandidateState[] candidateState)
Must be in the AdministrationController in the last bit of code.
Code:
for(int i = 0; i < model.Count; i++)
{
var user = await userManager.FindByIdAsync(model[i].UserId);
IdentityResult result = null;
if (model[i].IsSelected && !(await userManager.IsInRoleAsync(user, role.Name)))
{
result = await userManager.AddToRoleAsync(user, role.Name);
}
else if (!model[i].IsSelected && await userManager.IsInRoleAsync(user, role.Name))
{
result = await userManager.RemoveFromRoleAsync(user, role.Name);
}
else
{
continue;
}
if (result.Succeeded)
{
if (i < (model.Count - 1))
continue;
else
return RedirectToAction("EditRole", new { Id = roleId });
}
}
return RedirectToAction("EditRole", new { Id = roleId});
}
}
}
any help would be great!
I love this series, I have learned so much, but I wish I had the code for the AdministrationController to campare with my code. Would make watching a learning a bit less stressful.
Thanks again!
does this work with asp.net web application .net framework ? or u have separate video
When I try to update the users, I get redirected to my NotFound page because the role variable is null. What could be the cause of this?
Great
Good ,is it finished or not ???!!!
Hello,
can someone explain why we us an inputf or the Update of the userRoles and not a button.
Thanks in advance
submit: The button submits the form data to the server. This is the default if the attribute is not specified, or if the attribute is dynamically changed to an empty or invalid value.
reset: The button resets all the controls to their initial values.
button: The button has no default behavior. It can have client-side scripts associated with the element's events, which are triggered when the events occur.
Dear Venkat,
Regarding the following code that are present in HttpGet EditUsersInRole Action, could you explain why do we need to populate UserId, UserName, and IsSelected properties on the userRoleViewModel ???
var model = new List();
foreach (var user in userManager.Users)
{
var userRoleViewModel = new UserRoleViewModel
{
UserId = user.Id,
UserName = user.UserName
};
if (await userManager.IsInRoleAsync(user, role.Name))
{
userRoleViewModel.IsSelected = true;
}
else
{
userRoleViewModel.IsSelected = false;
}
model.Add(userRoleViewModel);
}
return View(model);
}
I think its not working as it is supposed to anymore... After my failure i did ctrl+c, ctrl+v and got same result. - When I want to add user to role and i check one, only this one has this role and other users are no longer admins for example. When I want to uncheck one user, the result is only user i unchecked is admin and no others are. Maybe I did something wrong but I dont see how could I made any mistake when copy-paste :D
Note: If u are using foeach loop in view, then you wont get the List in controller, so use for loop instead
IMO this part is the most complicated so far.
why u didn't use foreach here instead of for in httpPost EditUsersInRole method ? or it's just u preferred for here with no reason ?
We could use this solution with a Angular 8 application?
Gratz
I am getting NullReferenceException error in "model.Users.Add(user.UserName)" part while calling async Task EditRole(string id) method .I am not sure why but think it has something to do with the async functionality .
I found a solution for it . I guess it was because the Users property (List) of EditRoleViewModel was not initialized. I added an initialization and now it's working fine.
EditRoleViewModel mylocal = new EditRoleViewModel
{
Id = role.Id,
RoleName = role.Name,
Users=new List()
};
the variable result if you declare it null it doesn't work
IdentityResult result;
Hi Kudvenket,
When i run this code I found Error :--
UserManager was null
" foreach (var user in userManager.Users) "
and
An unhandled exception occurred while processing the request.
NullReferenceException: Object reference not set to an instance of an object.
Test.Controllers.AdministrationController.EditUsersInRole(string roleId) in AdministrationController.cs, line 150
Controllers.AdministrationController.EditUsersInRole(string roleId) in AdministrationController.cs
+
foreach (var user in userManager.Users)
Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
System.Threading.Tasks.ValueTask.get_Result()
Please suggest or help to remove this Error
There are an error which shows that userManager does not exist in the current context.
How can I fix that? thanks very much
hello
Thank for your great tutorial
I think this part is not important because the loop will continue by its logic and it's will done automatically
// HttpPost EditUsersInRole Action
else
{
continue;
}
if (result.Succeeded)
{
if (i < (model.Count - 1))
continue;
else
return RedirectToAction("EditRole", new { Id = roleId });
}
for post one just use like following
public async Task EditUsersInRole(List users, string roleId)
{
var role = await _roleManager.FindByIdAsync(roleId);
if (role == null)
{
ViewBag.ErrorMessage = $"Role with id -{roleId} cannot be found";
return View("NotFound");
}
foreach (var user in users)
{
var applicationUser = await _userManager.FindByIdAsync(user.UserId);
var isRoleUserExist = await _userManager.IsInRoleAsync(applicationUser, role.Name);
switch (user.IsSelected)
{
case true when !isRoleUserExist:
await _userManager.AddToRoleAsync(applicationUser, role.Name);
break;
case false when isRoleUserExist:
await _userManager.RemoveFromRoleAsync(applicationUser, role.Name);
break;
}
}
return RedirectToAction("EditRole", new { Id = roleId });
}
Can you please provide the source code of this tutorials?
If we have billion of users in DB so in your method we will retrieve all this users to Clint in Edit Role . I think that will cause low performance
have you found a solution?
I am getting the error "There is already an open DataReader associated with this Connection which must be closed first." in EditRole controller , please help me
apply ToList() to collection whenever you are retrieving the users in loop
var user in userManager.Users.ToList()
@@danishmalak1520 You can chekc your database connection string. Make sure it has "MultipleActiveResultSets=True" . If it isn't put it there in the connection string and your problem should be solved. :)
last else and continue is not necessary. without this else also the for loop will go to next loop. Also u can use for each
Dear Venkat,
Could you kindly please explain the following code that is present within the HttpPost EditUsersInRole action because I don't understand the code ?
if (result.Succeeded)
{
if (i < (model.Count - 1))
continue;
else
return RedirectToAction("EditRole", new { Id = roleId });
}
Thanks,
Edward
Hello Edward - This code basically checks if there are more users in the collection to process. If there are more users the continue keywords skips the rest of the statements that follow it and picks up the next item in the collection to process. Hope this answers your question.
Hello Venkat - Could you explain why we need to subtract 1 from model.Count for the if expression if (i < (model.Count - 1)) ???
@@ymtan this is the a logic applied by venkat sir ,if the 'model.count-1>i' then iteration completes (meaning there is no users) then it goes to else block and then control redirects to editRole Acton method
@@ymtan Arrays and lists use indexes starting at 0, not 1. So if there are 2 users (count=2), they would be at index 0 and 1. Thus we subtract 1 from the model count to make sure we don't get an out of bounds error in the loop.
Adding to Tan's question, What is the use of return RedirectToAction("EditRole", new { Id = roleId }); inside for loop above when we have one outside of loop?
what if we got a million of records? no search functionality.
This is ASP.NET core tutorial for *beginners*. Handling millions of records with search functionality is for *advanced*. 🤣
What you do when you have 10 000+ users and you have to pick 3?
THE LIST MODEL IS RETURNED 0 LINES ANYBODY CAN HELP ? THANKS
i did it with foreach i though it will be same but no, wtf
sir, please upload NODE.js complete playlist
Microsoft Identity not providing anything new. Approach of implementation is changed and microsoft increased complexity by top up class of role manager,.... manger...... Too much coding with Identity API ...
bad algorithm, why not send only updated values?
Hi Kudvenket,
When i run this code I found Error :--
UserManager was null
" foreach (var user in userManager.Users) "
and
An unhandled exception occurred while processing the request.
NullReferenceException: Object reference not set to an instance of an object.
Test.Controllers.AdministrationController.EditUsersInRole(string roleId) in AdministrationController.cs, line 150
Controllers.AdministrationController.EditUsersInRole(string roleId) in AdministrationController.cs
+
foreach (var user in userManager.Users)
Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
System.Threading.Tasks.ValueTask.get_Result()
Please suggest or help to remove this Error