In ASP.NET boilerplate project.
I have a database with users. I am using standard methods for retrieving them _userRepository.GetAll() and deleting _userRepository.Delete(id).
By default when user id deleted it is still kept in database with isDeleted
field marked as true.
My question is: is there in ABP any default method that retrieves exactly all users from database, and what follows:
is there any other possibility to do this than writing stored procedure like
SELECT * FROM dbo.AbpUsers
and using it in repository (and then in service)?
You should disable filter(SoftDelete):
//provided by DI
private readonly IUnitOfWorkManager _unitOfWorkManager;
using (_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.SoftDelete))
//or
//using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.SoftDelete))
{
var completelyAllUsers = _userRepository.GetAllList();
}
Related
I have a new .NET Core application that is using Entity Framework Core. The query against the database returns no data.
The context is created like this:
private readonly ExtensionDataModel.DataSet1 _context = new ExtensionDataModel.DataSet1();
and the method using it is:
public ExtensionDetails GetExtensionDetails(string extension)
{
var users = _context.Users;//.Where(x=>x.activeFlag==true);//.Where(x => x.workPhone.Contains("7029"));
if (!users.Any())
{
return null;
}
var user = users.First();
var detail = new ExtensionDetails()
{
Extension = user.workPhone,
FirstName = user.firstName,
LastName = user.lastName,
Location = user.LocationsRow.LocationDesc
};
return detail;
}
I get no errors, and the users.Any returns false, even through there is data in the database. If I expand the users object in the debugger, and look at the result set, the result set is empty. Also, I have been unable to see the query that it is generating.
When I use SQL Server Profiler, it does not show any database activity.
When I go to the Entity Framework designer (clicking on DataSet1.xsd), I can right click on the users table and choose Preview Data, and it brings back the rows in the table.
I am using a separate SQL Server database server, and created the EF model by extracting it from the database.
My data model has two tables in it, and the user that I am using has only read access to those two tables.
Any help would be appreciated. I am new to .net core, but have been using EF for many years.
I have a new ASP.Net Core website that uses an existing database, to which
I have added ASP.Net Core Identity for user management.
Since there is an existing user table, I simply added the which I have properly added the ASP.Net identity columns.
The additional columns in the existing table are in my IdentityUser-derived class. The site logic works well when I create new users, as well as logging in, logging out, and the like.
The problem is that all of the existing 'user' records (which I will call MyUser) have blank Core Identity fields, and thus are invisible to the identity system calls.
I would like to write a utility that goes through the existing MyUser records, and if the AspIdentityId field is null, set it up as a record manageable by the Identity subsystem.
I'm essentially looking for the 'Create' call, but I can't use UserManager.
CreateAsync because this creates a new record in the table, it doesn't update an existing one.
I do have two DB contexts (IdentityDBContext and OriginalDBContext), so if there is something that allows me to generate the field data, I can then add this to the columns in the table for the associated record.
Ok, I got this to work, not entirely sure why it works, seems like the AspIdentity fields are populated before they are committed. I have only added the specific changes that were the crux of the question, the DI, setup of the contexts, etc are elsewhere in the project.
Essentially, for each 'domain' record, I create a new ApplicationUser (IdentityUser-derived) record, and add the values for the custom fields in the domain record into the ApplicationUser record. Once this object is created, it has the necessary Asp.Net Identity fields already populated. I then get those fields and populate them back onto the domain specific record, then I save this. Once that is done, I re-find the record (this may not be necessary), and add the password based on the plain text password already in the domain record.
var clients = new List<Client>(myService.myContext.Clients);
foreach (var client in clients)
{
var user = new ApplicationUser // Derived from IdentityUser
{
UserID = client.UserID,
FirstName = client.FirstName,
LastName = client.LastName,
UserName = client.UserName,
PhoneNumber = client.Phone,
Email = client.Email // Other fields omitted for brevity.
};
var idUser = user as IdentityUser;
client.AspIdentityId = user.Id;
client.ConcurrencyStamp = user.ConcurrencyStamp;
client.NormalizedEmail = user.NormalizedEmail;
client.NormalizedUserName = user.NormalizedUserName;
client.PasswordHash = user.PasswordHash;
client.SecurityStamp = user.SecurityStamp;
myService.myContext.SaveChanges();
// Can we just use the 'user' object here?
var newUser = await myService.UserManager.FindByIdAsync(client.AspIdentityId);
var result = await myService.UserManager.AddPasswordAsync(newUser, client.Password);
}
Hope this helps someone, this was important to me to get done this way.
While looking for a way to be able to assign and revoke roles via an admin controller for users other than the one making a request, I've implemented a custom IAuthorizeFilter that checks if Guid tag, stored as a Claim, matches to a value in the Entity Framework 7 Code First Identity table for UserClaims.
Essentials, it's this code:
public class RefreshUserClaimsFilterAttribute : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext context)
{
var User = context.HttpContext.User;
var dbContext = context.HttpContext.ApplicationServices.GetRequiredService<ApplicationDbContext>();
var stampFromClaims = User.Claims.FirstOrDefault(Claim => Claim.Type == "ClaimsStamp")?.Value;
var stampFromDb = dbContext.UserClaims.Where(UserClaim => UserClaim.UserId == User.GetUserId()).ToList().FirstOrDefault(UserClaim => UserClaim.ClaimType == "ClaimsStamp")?.ClaimValue;
// Update claims via RefreshSignIn if necessary
}
}
I'm having the problem at the line where I'm assigning var stampFromDb, it could be much more readable in the following way:
var stampFromDb = dbContext.UserClaims.FirstOrDefault(UserClaim => UserClaim.UserId == User.GetUserId() && UserClaim.ClaimType == "ClaimsStamp")?.ClaimValue;
That, however, gives me cached (the same values as the actual claims from User.Identity) results and I could not find any documentation on this. My best guess is that the error is somewhere on my side, but I've never encountered such a problem before. This is the first time I'm using Asp.Net 5 and EF7. I'm using the default connection (LocalDB) to SQL Server 12.0.2000.
Is this a feature and, if yes, can it be turned off or did I make a mistake somewhere?
The issue was caused due to there being two different ways to create a service via dependency injection:
The sample code in my question used
var dbContext = context.HttpContext.ApplicationServices.GetRequiredService<ApplicationDbContext>();
where it should use
var dbContext = context.HttpContext.RequestServices.GetRequiredService<ApplicationDbContext>();
The difference here is between ApplicationServices and RequestServices. It looks like the ApplicationServices injector does have an instance of the database context somewhere which has had the DbSet filled earlier and therefore returning cached data instead of doing a database query.
I am developing an application architecture that uses 2 sub projects:
a) asp.net web application (it covers user interface and business logic) and
b) class library. (it covers data access layer)
After system user successfully logs in , the user information is stored in a session object.
The problem I am facing is when I try to access that session object in class library project(data access layer), it always returns null.
I need to access the session object in class library project because, in my case each user has their own username and password for database access(for security reasons);
So, How how do i read and write from/to session object in class library project
Use the System.Web.HttpContext.Current.Session object.
First of all, as Peri correctly noticed - you need to think again if having separate database logins for each user is a good idea - because you loose connection pooling (different users won't be able to reuse existing connections - and creating a new sql connection is quite expensive).
If you really wish to keep separate database users, I would create interface to abstract session from data access:
public interface ILoginDataService
{
LoginData Current { get; }
}
And implementation would pass login data from session. In such way you won't have session dependency to session in your data access logic - so it will be more testable, also you'll separate concerns.
Here is the code I used within a library to get session information.
public static string Entity()
{
string entity = "";
HttpContext httpContext = HttpContext.Current;
if (httpContext.ApplicationInstance.Session.Count > 0)
entity = httpContext.ApplicationInstance.Session["EntityCode"].ToString();
return entity;
}
I am having an ASP.Net application which uses session. I am able to access it in my app_code files using [WebMethod(EnableSession = true)] for the function. I am not sure whether this is your problem. I also faced session value as null when I removed (EnableSession = true) on the method.
using System.Web;
namespace ClassNameSpace
{
public class Class1 : IRequiresSessionState
{
private string sessionValue => HttpContext.Current.Session["sessionKey"].ToString();
}
}
We have a database that has been deployed to various clients. We are currently introducing a optional new feature that, to be used, will require the customers who want the feature to have a new table added to the existing database.
As we are rolling out a new piece of software that will have to interact with versions of the database both with and without the new table (and as we don't want 2 versions one for customers who have the new table and one for ones who don't) we were wondering if it is possible to programmatically determine (with entity framework) whether a table exists in the database (I can try to access the table and have it throw a exception but was wondering if there was a built in function to do this)
Thanks
Edit: Given that people are telling me i should be using a config file not checking with EF can anyone give me guidence on how to check the config file with, for example, a custom data annotations for a mvc controller. Something like:
[Boolean(Properties.Settings.Default.TableExists)]
public class NamedController : Controller
Which throws a page not found if false?
Edit 2: With the Suggestions given by people to use the config settings i ended up with the following solution
App settings to set whether the table exists
<appSettings>
<add key="tableExists" value="True"/>
</appSettings>
a custom data annotation to say whether to allow access to controller
[AuthoriseIfTableExistsIsTrue]
public class NamedController : Controller
the code for the custom authorise
public class AuthoriseIfTableExistsIsTrue : AuthorizeAttribute
{
private readonly bool _tableExists;
public AuthoriseIfTableExistsIsTrue()
{
_tableExists = string.Equals(bool.TrueString, ConfigurationManager.AppSettings["tableExists"], StringComparison.InvariantCultureIgnoreCase);
}
public AuthoriseIfTableExistsIsTrue(bool authorise)
{
_tableExists = authorise;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (_tableExists)
return base.AuthorizeCore(httpContext);
else
throw new HttpException(404, "HTTP/1.1 404 Not Found");
}
}
Thanks everyone for the help and telling me not to use EF for this and use config setting instead
A much better option would be to store the version differences as configuration. This could be stored in the database itself, a configuration file or even web.config.
Otherwise you'll end up with messy code like:
int result = entity.ExecuteStoreQuery<int>(#"
IF EXISTS (SELECT * FROM sys.tables WHERE name = 'TableName')
SELECT 1
ELSE
SELECT 0
").SingleOrDefault();
The only possible ways are
Query table and get exception
Use native SQL to query system views and look for that table - in EFv4 you can execute query directly from ObjectContext by calling ExecuteStoreQuery.
Your entity model will still have this table so in my opinion you should simply ship your DB with that table and in application code handle if feature is allowed or not (table will not be used but will be in DB).
If you want to make modular system then whole your feature (including application code) should not be present when client don't want to use it.