I'm trying to create my first 3 layers application with C# and MVC 5. I use Identity 2 for my authentication system and I installed it with this command :
Install-Package Microsoft.Aspnet.Identity.samples _pre
I found an article and question like that I need in website. I did step by step exact like this article. Here is Article
I added a class library to my project and move my models in this class library but I got 3 errors on IdentityConfig.cs Startup.Auth.cs and Manage controller about
user.GenerateUserIdentityAsync(UserManager));
Error detail is here:
CS7036 There is no argument given that corresponds to the required formal parameter 'authenticationType' of 'ApplicationUser.GenerateUserIdentityAsync(UserManager, string)' PresentationLayer D:\Projects\Divar\PresentationLayer\App_Start\IdentityConfig.cs 148 Active
When I ctrl+click on GenerateUserIdentityAsync I move to DataAccessLayer and this method.
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> 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;
}
In addition I changed my IdentityModels.cs name space to DataAccessLayer As well but I don't know why I have error Again,
Here Is my error image
enter image description here
You need to provide the authenticationType. There is no overload of user.GenerateUserIdentityAsync with 1 argument.
Should be more like
string a;
user.GenerateUserIdentityAsync(UserManager, a);
Just a small tip as well... I've done this same task before and I got alot of value from looking at different ORMs integrated wit Identity. Maybe you won't but i think this is the one that originally helped me...
https://github.com/JudahGabriel/RavenDB.AspNet.Identity
Related
Is there anyway to override Swagger IO CodeGen naming conventions, when its creating Angular API Service Proxies?
https://editor.swagger.io/
Its naming by this equation: API + Controller Name + Controller Method + HTTP Action.
public apiProductGetProductByProductIdGet(productNumber?: string, observe?: 'body', reportProgress?: boolean): Observable<ProductResponse>;
We want to restructure/reorder the naming convention for our company.
Currently linking Net Core 3 APIs with Angular Typescript.
Will accept javascript answer for CodeGen.
Update Possible Solution:
How do I change the nickname property in C#?
https://docs.swagger.io/spec.html
"Nickname. A unique id for the operation that can be used by tools reading the output for further and easier manipulation. For example, Swagger-Codegen will use the nickname as the method name of the operation in the client it generates. The value MUST be alphanumeric and may include underscores. Whitespace characters are not allowed.
"nickname": "addPet",
You are looking for the operationId property:
operationId is an optional unique string used to identify an
operation. If provided, these IDs must be unique among all operations
described in your API.
https://swagger.io/docs/specification/paths-and-operations/
Example:
/users:
get:
operationId: getUsers
summary: Gets all users
...
post:
operationId: addUser
summary: Adds a new user
...
/user/{id}:
get:
operationId: getUserById
summary: Gets a user by user ID
...
If you're using Swashbuckle, you can specify the operationId a couple of different ways below:
[HttpGet("{id:int}", Name = nameof(GetProductById))]
public IActionResult GetProductById(int id) // operationId = "GetProductById"'
or
[HttpGet("{id:int}", Name = "GetProductById")]
public IActionResult GetProductById(int id) // operationId = "GetProductById"'
See this also
You can also change the generated client SDK service naming conventions using tags (if you're like me and want to prevent conflict with client services).
Instead of tagging as user, and having the client SDK generate the service name as UserService, you can use the tag of user-api and the generated library service will be named UserApiService.
https://swagger.io/docs/specification/2-0/grouping-operations-with-tags/
I'm working on my custom implementation of ASP Identity and I have separated my functions on two C# classes projects, one for Entities and one for business logic. I started by copying the default template of Identity for ASP MVC 5 and moving database entities into the Entities project, but then I had to comment the GenerateIdentityAsync method because the UserManager is in another project:
public class ApptelinkUser : IdentityUser<long, ApptelinkUserLogin, ApptelinkUserRole, ApptelinkUserClaim>
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(ApptelinkUserManager manager, string authenticationType)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
return userIdentity;
}
}
Then I replaced all the calls to this method by calling the CreateIdentityAsync method directly from UserManager, but then I realized the GenerateUserIdentityAsync method was useful for setting up the claims, is there another way to add this method on another project or another workaround for adding the UserClaims?
Currently I Have configured Identityserver4 as separated project + My WebAPI and store in DB Credentials in IdentityServer.
Now i have problem how to make CRUD(In my frontend API) to IdentityServer(I want from my API add Clients to IdentityServer)
How to make property?
From IdentityServer4.EntityFramework and IdentityServer4.EntityFramework.Storage, you have access to IConfigurationDbContext (once you've added the required services in ConfigureServices using e.g. AddConfigurationStore). Because this is registered as part of the Dependency Injection system, you can take a dependency on it in one of your controllers. e.g.:
public class ClientsController : ControllerBase
{
private readonly IConfigurationDbContext _configurationDbContext;
public ClientsController(IConfigurationDbContext configurationDbContext)
{
_configurationDbContext = configurationDbContext;
}
// ...
}
IConfigurationDbContext is an abstraction of a standard DbContext, with the following DbSet<T> properties:
Clients
IdentityResources
ApiResources
It also includes both SaveChanges and SaveChangesAsync - Everything one might expect from a DbContext. Because of all of this, you can CRUD each of these entities just like any other Entity Framework Core driven database.
One final thing to note is that there are both Models (in IdentityServer4.Storage) and Entities (in IdentityServer4.EntityFramework.Storage). There are also a few extension methods for mapping between these (e.g. ClientMappers.ToEntity).
Given all of this, you can create a Model inside of your controller (or perhaps somewhere much better encapsulated than directly there). Here's a basic example for creating a new Client:
var clientModel = new Client
{
ClientId = "",
ClientName = "",
// ...
};
_configurationDbContext.Clients.Add(clientModel.ToEntity());
await _configurationDbContext.SaveChangesAsync();
The Client class here comes from IdentityServer4.Models and is then converted to an Entity using a ToEntity extension method I hinted at above. Working with a Model and converting to an Entity is simpler than trying to manipulate an Entity directly - If you're interested, you can see the mapping that takes place here.
This works in the same way for ApiResources, IdentityResources, etc. Use the source code links I've provided if you want to find out more about those specifically, but the information I've provided here should have you covered.
In order to use IdentityServer4 and IdentityServer4.EntityFramework in your API project, you can just add the two references to your API project. After that, you can configure the DI in the same way (using AddIdentityServer in ConfigureServices), but you don't need to add the middleware (using UseIdentityServer in Configure). You can even just use AddIdentityServer().AddConfigurationStore(...) to set up the relevant services, as you don't need a signing key, etc.
One way you can do this is by bootstrapping the ID4 Quickstart (tutorial located here):
http://docs.identityserver.io/en/release/quickstarts/3_interactive_login.html
Other option is to use their quickstart seeds located here to speed this up:
https://github.com/IdentityServer/IdentityServer4.Samples
Now if you want to implement restfull login there are constraints around it (i wanted to find out as well) check out this question:
IdentityServer 4 Restfull Login/Logout
I've two WCF services connected to my client. I want to use a User-object, retrieved from service #1, and use this as paramter for service #2. Here is my MVC-Controller TournamentController.cs code:
private readonly GCTournamentServiceClient _tournamentClient = new GCTournamentServiceClient();
public ActionResult Join(int id)
{
GCUserServiceClient userClient = new GCUserServiceClient();
// Get current user
var currentUser = userClient.GetUser(0);
if (currentUser != null)
{
// Get selected tournament
var selectedTournament = _tournamentClient.GetTournament(id);
// Check if there are available seats in the tournament
if (selectedTournament.Seats > selectedTournament.RegistredUsers.Count)
{
// Check if user exist amoung registred users
if (!selectedTournament.RegistredUsers.Contains(currentUser))
{
selectedTournament?.RegistredUsers.Add(currentUser);
}
}
}
}
The error Visual Studio prompt me with:
Argument 1: cannot convert from 'GConnect.Clients.WebClient.GCUserService.User' to 'GConnect.Clients.WebClient.GCTournamentService.User'
So the problem is currentUser, which has the type GCUserService.User. I'm unable to use this as parameter for RegistredUsers
The error itself makes perfect sense, however, I'm not quite sure how I'm suppose to convert this type (properly). Some articles states, that a "shared"-service has to be created, which holds the User-type. I just can't believe, that a solution like that, should be necessary.
I might have misunderstood some basic stuff here (working with WCF and MVC), but please enlighten me, if that's the case.
So the problem is currentUser, which has the type GCUserService.User.
I'm unable to use this as parameter for RegistredUsers
There are 2 approaches to solve this problem:
1)
Create a class library project (Visual Studio) and add the User class in that project, compile it and add its assembly's (.dll) reference to both services and the client (your MVC application). Next retrieve that user object as you are already doing it
var currentUser = userClient.GetUser(0);
GetUser will return the type of User that is defined in a separate assembly which is added as reference as suggested above. The TournamentService will also reference the same assembly and the RegistredUsers.Add(User userToadd) method will take the same User object and WCF runtime should be able to serialise/desterilise it.
2)
In your MVC client application, new up the User object that is acceptable by the TournamentService.RegistredUsers.Add method. Populate its properties from the currentUser and pass in that object as parameter to RegistredUsers.Add method.
Best Practice
Ideally, I would recommend the first approach which is more work but a better practice and that your User class is maintained centrally and code is reused.
Hope this helps!
I have a DataBase First Website in mvc.
My Problem is that i want to add some Points to the AspNetUser and be able to show/modify them. For example when register.
So i added for example age to the AspNetUser updated the Database. Then i went to the edmx DataBase and updated my Model so far so good. Everything is working till this point.
Now i went to the IdentityModel and added the age.
public class ApplicationUser : IdentityUser
{
public int Age { 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;
}
}
Then i went to the RegisterViewModel
public class RegisterViewModel
{
.....
public int Age { get; set; }
}
Now when i try to start the Website and to Login, as soon as i press Login i get the Folowing error.
The model backing the 'ApplicationDbContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).
Zeile 77: // This doesn't count login failures towards account lockout
Zeile 78: // To enable password failures to trigger account lockout, change to shouldLockout: true
Zeile 79: var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
Zeile 80: switch (result)
Zeile 81: {
As soon as i comment out the last two changes everything works again.I´m wondering what i`ve done wrong.
In order for your project to work with the additional properties you need to add a "Migration" in order that Entity Framework Code First can update your database automatically-
Open the NuGet package manager console from the "Tools" menu in Visual Studio.
Type "add-migration AddedUserProperties"
Type "update-database"
See Code First Migrations on MSDN for more information.
Depending on your project configuration you may need to type "enable-migrations" which will set up code first migrations for you before this can work (if it is set up already you should have a "Migrations" directory in your project).
It is also possible to set your code first context to drop and recreate the database if the model has changed, or simply every time you run your code.
Obviously dropping the database is going to delete any users already registered, so this is probably best done in the early prototyping stage and with "DropCreateDatabaseWhenModelChanges" initialization rather than "DropCreateDatabaseAlways", or by seeding your test users so that these are automatically recreated with the database.
To do this -
Database.SetInitializer(new DropCreateDatabaseWhenModelChanges<ApplicationDbContext>());
See Understanding Database Initializers in Entity Framework Code First for more.