0

I'm trying to pull out of database objects where current user Id is in list of those objects.

My model:

 public class Procedure
 {
   ...
   public IList<User> Lawyers{ get; set; }
   ...
 }

And in controller:

    [HttpGet]
    public async Task<IActionResult> MyProcedures()
    {
        var user = await userManager.GetUserAsync(User);
        var procedures = context.Procedures.Where(x => x.Lawyers.Contains(user));
        return View(procedures);
    }

This only selects one object.

EDIT: Problem is in my User class, it takes only one Id from Procedure and that is why its showing my only one (last added). Thanks for help guys!

Petar
  • 3
  • 2
  • Will you include a screenshot of the Procedure table's records, so we could verify if there's more than 1 record there for your user? Also highlight which one is your UserId – Jerdine Sabio Apr 27 '20 at 01:58
  • contains same object relies on they're really same objects. so you could try this instead, ```cs var procedures = context.Procedures.Where(x => x.Lawyers.Any(y => y.Id == user.Id)); ``` – nwpie Apr 27 '20 at 02:19
  • You probably have link table to link `Procedure` and `Lawyers`, you can try to query from there: `context.LawyerProcedures.Where(link => link.LawyerId == user.Id).Select(link => link.Procedure)` – Fabio Apr 27 '20 at 03:07

2 Answers2

0

The way you wrote will work if you have icomparable or something implemented that can tell that a lawyer is “the” user if user id matches.

Without that you would need to do lawyers.Any(x=> x.UserId == user.UserId)

YankTHEcode
  • 634
  • 4
  • 8
0

You are missing something, which user ??

Either pass something into your function signature or get it from HTTPContext you need to get the user you want to find

If you are using ASP core its bit different from the old ways

First this:


var userId = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;

And now..

// make sure you can access/inject it if you want
// private.. _httpContextAccessor 
// then in your action

[HttpGet]
public async Task<IActionResult> MyProcedures()
{
    // again make sure you can access the context _httpContextAccessor
    var userId = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
    var procedures = context.Procedures.Where(x => x.Lawyers.Contains(userId).FirstOrDefault());

    //... fill in whatever logic you want.. 

    return View(parnice);
}

Update 2 based on question/comments:

Do this in two Steps

  1. Step 1: Get the Current User (with claims or HTTPContext as shown below), for e.g. System.Security.Claims.ClaimsPrincipal currentUser = this.User;
  2. Step 2: Using the user, find all the related Lawyers etc. context.Procedures.Where(x => x.Lawyers.Contains(userId)

Make sure to register HttpContextAccessor in your startup... double check this.. to register in your Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}

In the original Core version, I have to double check if it changed now, assuming your code is inside an MVC controller:

public class YourController : Microsoft.AspNetCore.Mvc.Controller

Now, since you have the Controller base class, you can get the IClaimsPrincipal from the User property

System.Security.Claims.ClaimsPrincipal currentUser = this.User;

You can check the claims directly (without a round trip to the database):

var userId = _userManager.GetUserId(User); // Get user id:

To your second comment, you can get either the UserId or UserName

     //  user's userId    
     var userId =  User.FindFirstValue(ClaimTypes.NameIdentifier) 
     //  user's userName
     var userName =  User.FindFirstValue(ClaimTypes.Name) 

A nice reference for you hope it helps :)

Transformer
  • 6,963
  • 2
  • 26
  • 52
  • My User class is inherited from IdentityUser class. I'm using asp.net core mvc and entity framework core. `var procedures = context.Procedures.Where(x => x.Lawyers.Contains(userId).FirstOrDefault());` shows error that cannot convert string to User I've injected `private readonly AppDbContext context;` and in construtor as well. I'm just looking here to get Procedures which have list of Users as a Lawyers and return to View only those Procedures that are linked to currently logged User. – Petar Apr 27 '20 at 19:38
  • you also need the current users `HTTPContext`or the `claims principal` to get the current user – Transformer Apr 27 '20 at 19:51