The only other alternative to generic repositories is to create custom repositories that are still based on IRepository<TEntity, TPrimaryKey>.
Since I don't want ABP in my Windows Service, you are saying I'm out of luck trying to maintain centralized Core and EntityFramework projects and a shared Service project that holds a couple "Domain" services?
What did you mean initially by "If you want to use your regular classes in ABP, it will not be a problem"?
Thank you for replying.
Regarding your statement "If you want to use your regular classes in ABP, it will not be a problem.", I swapped out my website's Entities (the ones that inherit from Abp's Entity) with my POCO entities (basically the same classes but keeping their primary key IDs in the class and not inheriting from anything.)
Now Application services that inject the entities (wrapped in an IRepository) are complaining. For example:
private readonly IRepository<User, long> userRepository;
public UsersApplicationService
(
IRepository<User, long> userRepo
)
{
userRepository = userRepo;
}
The error is:
The type 'MyProject.Core.User' cannot be used as a type parameter 'TEntity' in the generic type or method 'IRepository<TEntity, TPrimaryKey>'. There is no implicit reference conversion from 'MyProject.Core.User' to 'Abp.Domain.Entities.IEntity<long>'.
My classes that use a int instead of a long (e.g. IRepository<Company>) give a similar error. I thought maybe since Entity automatically adds 'Id' to each descendent, that adding 'Id' to my POCO would help but the error persists.
With respect to Dependency Injection, I think I get the concept and don't expect that to be a problem.
I wrote a nice website using Abp 1.0. Since I was only focusing on it at the time, my solution has the usual layout:
SLN Application (IDomainService, IApplicationService) Core (Entity) EntityFramework (AbpDbContext, IRepository) Web Api
Now I have a new project - a Windows Service - that uses the same database. Hence, I could reuse Core and EntityFramework, however I don't need Abp for a Window Service. Therefore, the exact same entities and dbContext can't be shared.
Also, both Web and Windows Service have similar services but in the latter I don't have IDomainService/DomainService or IApplicationService.
I'd like to have neutral projects that implement Core without Entity, EntityFramework using the regular DbContext, my own Install code that registers with Castle Windsor and common Services that don't need to inherit from DomainService.
I know that sound like I should just dump Abp from the web, however Abp makes working with Angular really nice. I just want to include my neutral Core, EntityFramework and Service projects (and register them with Castle Windsor using plain Castle instead of Abp's wrappers) in the Web and also use them in my Windows Service.
I've read all the Abp documentation and still don't know how to do this.
What I ended up doing is to add a new ASPNET controller (I just added it to the existing HomeController) that takes a non # url and rewrites it and then calls the Angular url.
For example, in Angular I have routes that look like #/page1/10 #/page2/3 etc
My new ASPNET controller can take routes that look like /home/page/1/10 /home/page/2/3
Those routes call this controller
public ActionResult page()
{
return Redirect(Request.Url.OriginalString.Replace("home", "#").Replace("page/", "page"));
}
It does the trick because I have only a specialized need for non-# urls in embedded email links. Users don't have to know or use these urls directly. And I don't have to have a raft of custom ASPNET controllers to make it happen since my Angular view names follow a strict pattern.
Note: I also added the non-# route structure to RouteConfig.cs
According to [https://www.codeproject.com/tips/826753/removing-sharp-from-url-in-angularjs]), we can get rid of the # from our routes.
I need this to happen because my corporate authentication system removes everything after a # so the call back to my site can't deep link.
The tip on codeproject doesn't seem to work with Abp. I'm using Abp 1.0.0.0. What is your way to make this happen?
<cite>hikalkan: </cite> I assume that you are using ABP v1.0.
Can you try to add this into your module's PreInitialize:
Configuration.ReplaceService<IPermissionChecker, PermissionsChecker>(DependencyLifeStyle..Transient);
Be sure that the PermissionsChecker is your class (since abp.zero has same class name). To be sure, rename your class to CustomPermissionsChecker or something you more like.
I am using ABP 1.0. I renamed my checker to MyPermissionChecker.
When I try to add that line of code to my MyApplicationModule.PreInitialize()
using Abp.Authorization;
using Abp.Dependency;
...
Configuration.ReplaceService<IPermissionChecker, MyPermissionsChecker>(DependencyLifeStyle.Transient);
Visual Studio says "<span style="color:#FF0040">CS0308: This non-generic method 'IAbpStartupConfiguration.ReplaceService(Type,Action)' cannot be used with type arguments</span>."
I'm using vanilla Abp and am trying to secure my public AppService methods. The PermissionChecker I defined is getting ignored.
I have a couple of permissions defined
public class MyAuthorizationProvider : AuthorizationProvider
{
public override void SetPermissions(IPermissionDefinitionContext context)
{
context.CreatePermission("CurrentState");
context.CreatePermission("UpdateState");
}
}
In PreInitialize() of my AppService module, I add it to the configuration
Configuration.Authorization.Providers.Add<MyAuthorizationProvider>();
I implemented IPermissionChecker
public class PermissionsChecker : IPermissionChecker, ITransientDependency
{
public Task<bool> IsGrantedAsync(string permissionName)
{
return CheckAccess(permissionName);
}
public Task<bool> IsGrantedAsync(UserIdentifier user, string permissionName)
{
return CheckAccess(permissionName);
}
}
and put AbpAuthorize attribute on an AppService method
[AbpAuthorize("CurrentState")]
public CurrentState GetCurrentState(int Id)
{
// do stuff
}
Neither IsGrantedAsync methods get called. The method just executes. (AbpSession.UserId is correctly set via the NameIdentifier claim.) I've looked over the guide <a class="postlink" href="http://aspnetboilerplate.com/Pages/Documents/Authorization">http://aspnetboilerplate.com/Pages/Docu ... horization</a> but can't see what I'm missing.
I added [DisableAbpAntiForgeryTokenValidation] to the abstract base class
[DisableAbpAntiForgeryTokenValidation]
public abstract class MyControllerBase : AbpController
Without doing anything else, I verify that the usual login page comes up and I can still log in as admin/123qwe
Now I uncomment the PostInitialize() filters to remove and add filters. The definition of MyMvcAuthorizeFilter is still the same as shown above.
public override void PostInitialize()
{
GlobalFilters.Filters.Remove(GlobalFilters.Filters.Single(f => f.Instance is AbpMvcAuthorizeFilter));
GlobalFilters.Filters.Add(IocManager.Resolve<MyMvcAuthorizeFilter>());
base.PostInitialize();
}
Now when I run, the login page still comes up and I can log in as admin\123qwe. The home page starts to render, but an Abp error dialog "An error has occurred!" pops up. Then I notice that the upper right user badge shows {{vm.getShownUserName()}} instead of '.\admin' and view isn't getting rendered.
This is really frustrating. All I want to do is programmatically log in so that the Log in page doesn't appear. Should I just rip AbpZero out of my solution and just do plain old claims based authentication and authorization?
By userIddo you mean the PK of AbpUsers (ID)? Before I change the schema, I tried to test it first. I created a new user by logging in as Admin and going to the Users tab of the UI.
I then looked in AbpUsers and see that this new user has ID = 3.
I tried "3" in
new Claim(ClaimTypes.NameIdentifier, "3")
but the Login page still displays and while the MyMvcAuthorizeFilter is in place, I cannot login with Admin or the new account via the Login page. It throws "Empty or invalid anti forgery header token".
I've tried three claims
new Claim(ClaimTypes.Name, "3"),
new Claim(ClaimTypes.NameIdentifier, "3"),
new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "3")
I hope I interpreted your suggestion correctly!
It is still a mystery.
I don't know how to get AbpZero to realize that I'm already authenticated and look for my employee id in the Headers (every single web server in my intranet is behind WSSO so it is not possible to be unauthenticated prior to AbpZero taking over.)
var empid = filterContext.HttpContext.Request.Headers["employeeid"];
Then, how to bypass the Login page and tie my empid to whatever necessary records in the Abp tables. (e.g. Does my empid need to be in AbpUsers? If so, does it go in UserName field? What about the password field, which is superfluous in my case.)
Since I don't need AbpZero for Authentication, it still would be nice to take advantage Authorization features. But maybe that too much to hope for.