user11739339
user11739339

Reputation:

Getting current logged on user in web api controller

I am trying to retrieve the current logged on user details in a Web API controller to create a user profile page.

I have got the method created but the user keeps returning null in the code was shown below. This works fine in my MVC controller but in Web API controller it throws an error.

[HttpGet]
public IActionResult userProfile()
{
    if (ModelState.IsValid)
    {
        var user = _userManager.Users.First(x => x.Email == User.Identity.Name);
        return Ok(new UserViewModel
        {
            Id = user.Id,
            UserName = user.Email,
            FirstName = user.FirstName,
            LastName = user.LastName
        });
    }
    else
    {
        return BadRequest(ModelState);
    }
}

UPDATE

[HttpGet]
[Authorize(Roles = "Client, Administrator")]
public IActionResult userProfile()
{

    string baseUrl = "https://localhost:5001";
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri(baseUrl);
    var contentType = new MediaTypeWithQualityHeaderValue("application/json");
    client.DefaultRequestHeaders.Accept.Add(contentType);
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", HttpContext.Session.GetString("token"));

    UserViewModel userModel = new UserViewModel();
    HttpResponseMessage response = client.GetAsync("https://localhost:5001/api/UserAPI").Result;
    string stringData = response.Content.ReadAsStringAsync().Result;
    userModel = JsonConvert.DeserializeObject<UserViewModel>(stringData);

    return View(userModel);
}

Error Message:

System.InvalidOperationException: 'Sequence contains no elements

Upvotes: 0

Views: 3144

Answers (4)

Andrei Dragotoniu
Andrei Dragotoniu

Reputation: 6335

An API is stateless meaning that there is no concept of logged in users or sessions. This is because each request is unique, separate and holds all the information required to provide a response.

An API has no way of knowing who is sending a request, there can be 10k people all sending requests at the same time, so who exactly is "logged in"?

So, if you want to load a user profile then send the userID as a parameter, something like:

    [HttpGet]

    public IActionResult userProfile(string userEmail)
    {
         if ( !string.IsNullOrEmpty (userEmail) ) ..... etc etc
         {
            var user = _userManager.Users.First(x => x.Email == userEmail);
            return Ok(new UserViewModel
            {
                Id = user.Id,
                UserName = user.Email,
                FirstName = user.FirstName,
                LastName = user.LastName
            });   
        }
    }

As a side note, if you don't have any input parameters or the input is a primitive type such as string or int, then ModelState.IsValid won't do anything. Only use ModelState.IsValid if you have a model class populated with the right rules.

in my case I could actually replace the string with a class

public class UserProfileRetrieveModel
{
      [Required]
      public string UserEmail { get;set; }
}

then I can do :

[HttpGet]
    public IActionResult userProfile(UserProfileRetrieveModel model)
    {
        if (ModelState.IsValid)
        {
            var user = _userManager.Users.First(x => x.Email == model.UserEmail);
            //etc
        }
        else
        {

            return BadRequest(ModelState);

        }
    }

--- after question updated

so it looks like you have a client application and from that you call the API. everything I said above still applies, simply populate the data you have before calling the API.

Example:

public IActionResult userProfile()
{
//removed code we don't care about

   string userEmail = "";// get your user email here in the MVC controller
   //populate it in the api url.
   //you might need to URL encode it since it will contain dots and @

   string apiUrl = "https://localhost:5001/api/UserAPI/{userEmail}";
   HttpResponseMessage response = client.GetAsync(apiUrl).Result;        
}

you don't need to work out anything in the API, just pass everything you need to the API, from the MVC controller.

Now, all this aside, you have massive async issues. that part needs work although it's not related to the question.

Upvotes: 1

gopi putta
gopi putta

Reputation: 3

From the error message It seems you are trying to retrieve an element from an empty sequence. So check whether you have the the data or not.And also try to use .FirstOrDefault().

Upvotes: 0

Shakir Ahamed
Shakir Ahamed

Reputation: 1308

Instead of .First() change it to .FirstOrDefault()

Upvotes: 0

Riddell
Riddell

Reputation: 1489

Im presuming you're on WebAPI 2.

Try the following:

var user = _userManager.GetUser(HttpContext.User);

or

var user = _userManager.FindById(User.Identity.GetUserId());

Upvotes: 0

Related Questions