In MVC i want to authenticate users,they must not be able to see other user data when logged on. Users must be able to CRUD their own data only. I have created two model:
public class User
{
public int id { get; set; }
public string Username { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public List<Product> Products { get; set; }
}
public class Product
{
public int productId { get; set; }
public string productName { get; set; }
public double productPrice { get; set; }
public User Users { get; set; }
}
And i have product controller, where i want to authenticate users from CRUD other users data.
You can make your code to perform CRUD operations on only the products available for logged in user.
Use below scenario for your requirement.
public class User
{
public int id { get; set; }
public string Username { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public List<Product> Products {
get{
//get all products from database/storage for this user. for ex: I have called a method to get products
//you can filter products related to this user by sending this user id to database or using code like below
//Writing this code/logic in controller would be preferable
return GetAllProducts().Where(p => p.Users.id == this.id).ToList();
}
set;
}
}
Agree with Rajesh, I would recommend you use Current User's data and filter Rajesh you showed. Current User's Data may include Id of current logged user. If you use cookies to keep user's session, you can retrieve his Id from cookies in controller or filter attribute: HttpContext.Current.Request.Cookies["auth_cookie"].
Related
I have a table in my EF model that is not creating within the database on access.
The table name is "sites" and is linked to a parent table by the use of a foreign key called "CompanyId".
I am attmempting to list all the sites that belong to a specific company (the company table is linked to the ApplicationUser)
I would expect that when i call the database for a list of the sites that it will be created. However i just receive an error that states the table does not exist
My model for the two tables is as follow
public class Company
{
[Key]
public int CompanyId { get; set; }
public string CompanyName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string PostCode { get; set; }
public string County { get; set; }
public string Country { get; set; }
public string TelephoneNumber { get; set; }
public string Email { get; set; }
public virtual IQueryable<Site> Sites { get; set; }
}
public class Site
{
[Key]
public int SiteId { get; set; }
public int CompanyId { get; set; }
public string SiteName { get; set; }
public string Url { get; set; }
}
and my controller
public ActionResult Index()
{
//get the user details
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
var currentuser = manager.FindById(User.Identity.GetUserId());
// search
var company = currentuser.Companies;
var sites = company.Sites;
if (sites == null)
{
sites = db.Sites.Where(c => c.CompanyId == company.CompanyId);
return View(sites.ToList());
}
return View(company.Sites.ToList());
}
You can see which table is created in your database using Database Manager?
Try
1: Change
public virtual IQueryable<Site> Sites { get; set; }
for
public virtual ICollection<Site> Sites { get; set; }
2: Add property to your site class
public Company Company { get; set; }
Did you create a migration for the change? If not the issue the "Add-Migration whateverYouWant" command in your package manager console.
Do you have automatic migrations enabled? If not then you have to auth the command "update-database" in your package manager console.
Look into your Configuration.cs file under the Migrations folder
and check the Configuration constructor. There should be a property called "AutomaticMigrationsEnabled" set to true in order for this to do what you are expecting.
I am currently working on a simple comments system.
I have a table that should store comments by following model:
public class Comments
{
[Key]
public int Id { get; set; }
[DataType(DataType.MultilineText)]
public string Text { get; set; }
public DateTime DateCreated { get; set; }
public int FromUserId { get; set; }
public int ToUserId { get; set; }
}
Comments are being written from one user to another on his UserPage.
I get userId from db, looking for id that corresponds my User.Identity.Name (name of authorized user) and pass it to FromUserId.
The question is How can I track on whoose page user is writing comment, in order to pass this to ToUserId.
UserPage is being created dynamically from db.
I am new to Entity Framework and Asp.NET, and therefore, struggling with creating database relationships within the Entity Framework.
I have two SQLite tables (Ticket and User) and have setup my entity models as follows:
public class Users
{
[ForeignKey("id")]
public int id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public virtual ICollection<Tickets> Tickets { get; set; }
}
public class Tickets
{
public int id { get; set; }
public string summary { get; set; }
public string description { get; set; }
public string c_location { get; set; }
public string c_store_device { get; set; }
public string category { get; set; }
public DateTime? created_at { get; set; }
public DateTime? closed_at { get; set; }
public int priority { get; set; }
public int? assigned_to { get; set; }
public DateTime? due_at { get; set; }
public DateTime? updated_at { get; set; }
public string status { get; set; }
public virtual Users Users { get; set; }
}
I am trying to use Entity Framework 7 to export an IEnumerable<Tickets> that includes the User assigned to each Ticket.
I have tried to create my model relationship in MyDBContext as a single User can have multiple Tickets, and also has a foreign key associated in my Sqlite database (Tickets.assigned_to = User.id):
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Users - > many Tickets
modelBuilder.Entity<Users>()
.HasMany(p => p.Tickets)
.WithOne(e => e.Users)
.HasForeignKey(p => p.assigned_to);
}
My result ends up with Ticket data being exported, but against every ticket I see a null value for User:
[{"id":10002,...,"Users":null}]
When I use .Include() within my Repository to include each User like this:
public IEnumerable<Tickets> GetAll()
{
return _db.Tickets.Include(t => t.Users).ToList();
}
It results in the error
HTTP Error 502.3 - Bad Gateway
The specified CGI application encountered an error and the server terminated the process.
What I'm trying to retrieve is data that looks like:
{"Ticket";[{"id":10002,..."status":"closed"}],"Users":[{"id":"1"..."email":"johndoe#someplace.com"}]}
I know it probably has something to do with my relationship model, but I cannot work out what I am doing wrong.
First you should really derive your Users from IdentityUser. It helps when trying to wire up the relationship, but I will give you the answer based on your current models. Your ForeignKey property should be on the child entity. By naming conventions, which is what EF uses by default, your public Users Users works better if you put a public int UsersId. Then essentially what EF will do is from your public Users Users it will go to the Users table. Then it looks for the ForeignKey which is set to Id, so now we are in the Users Table looking at the id property. Then it looks for the naming convention UsersId and if it sees it, it will set that property to the value that it saw from the Users Table Id column.
Try using this
public class Users
{
public int id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public virtual ICollection<Tickets> Tickets { get; set; }
}
public class Tickets
{
public int id { get; set; }
public string summary { get; set; }
public string description { get; set; }
public string c_location { get; set; }
public string c_store_device { get; set; }
public string category { get; set; }
public DateTime? created_at { get; set; }
public DateTime? closed_at { get; set; }
public int priority { get; set; }
public DateTime? due_at { get; set; }
public DateTime? updated_at { get; set; }
public string status { get; set; }
[ForeignKey("Id")]
public int UsersId { get; set; }
public virtual Users Users { get; set; }
}
and for your Fluent API configuring
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Users - > many Tickets
modelBuilder.Entity<Users>()
.HasMany(p => p.Tickets)
.WithOne();
}
Now all that does is create the relationship. In order to view the specific items you want to view, use a ViewModel. So, pull the two lists you want from where you want. Then use logic to separate the list how you want them to display.
public class UsersViewModel()
{
public UsersViewModel(Users user, List<Tickets> tickets)
{
this.first_name = user.first_name;
this.last_name = user.last_name;
this.email = user.email;
this.Tickets = new List<Tickets>();
foreach(var ticket in tickets)
{
if(ticket.UserId == user.Id)
{
this.Tickets.Add(ticket)
}
}
}
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public List<Tickets> Tickets { get; set;}
}
then in your controller make your list
public IActionResult Index()
{
var usersList = _repository.Users.ToList();
var ticketsList = _repository.Tickets.ToList();
var model = new List<UsersViewModel>();
foreach(var user in usersList)
{
var listItem = new UsersViewModel(user, ticketsList);
model.Add(listItem);
}
return View(model);
}
or use a Linq query
public IActionResult Index()
{
var usersList = _repository.Users.ToList();
var model = new List<UsersViewModel>();
foreach(var user in usersList)
{
var ticketsList = from x in _repository.Tickets where x.UserId.Equals(user.Id) select x;
var listItem = new UsersViewModel(user, ticketsList);
model.Add(listItem);
}
return View(model);
}
then at the top of your view you should have
#model IEnumerable<UsersViewModel>
We have this unique requirement to login to MVC ASP.NET app by adding extra "Tenant Code" next to Username/email and password.
We've created a few class below:
public class UserProfile
{
public Guid Id { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public String Address { get; set; }
public String Postcode { get; set; }
public String State { get; set; }
public String LandLineNo { get; set; }
public String MobileNo { get; set; }
public Tenant Tenant { get; set; }
}
public class Tenant
{
public Guid Id { get; set; }
public String Code { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public Boolean IsActive { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime LastDateModifiedDate { get; set; }
}
We've added properties in class ApplicationUser : IdentityUser
public virtual UserProfile UserProfile { get; set; }
and added on class ApplicationDbContext : IdentityDbContext
public System.Data.Entity.DbSet<UserProfile> UserProfile { get; set; }
The only that we can think of is to override the SignInManager.PasswordSignInAsync is that right? How to achieve this?
I'm appreciated your input.
Thanks
I don't think overriding the PasswordSignInAsync is going to be useful since its signature doesn't take over the user entity. It only takes over username, password, isPersistent & shouldLockout so you don't have any access to any tenant info. If you tried to check for the tenant info buy the username you may end up with multple accounts.
I would recommend creating your own method in a class that derives from the SignInManager. Get this to check the user and tenant info and call SignInAsync or SignInOrTwoFactor (if you're using 2 factor auth).
If you get a bit lost, have a look at the Microsoft.AspNet.Identity.Owin assembly, in your decompiler of choice, and check what those methods are doing.
Is there a built-in way of associating persistent model data with an authenticated user in MVC4, or are you supposed to provide your own implementation?
The MSDN tutorials I've read don't suggest how to do it, but I've seen a WebSecurity.CurrentUserId property I could store. For example, a model for a site that allows the user to upload photos:
public class Photo
{
public int Id { get; set; }
public int UserID { get; set; } // Controller sets WebSecurity.CurrentUserId?
public DateTime Created { get; set; }
...
}
Or is there an "MVC way"?
can you not use something like this:
public class Photo
{
public int Id { get; set; }
public int UserID { get; set; }
public DateTime Created { get; set; }
public UserProfile user {get;set;}
...
}
public class UserProfile
{
public int UserID { get; set; }
}