简体   繁体   English

在Web API控制器中获取当前登录的用户

[英]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. 我试图在Web API控制器中检索当前登录的用户详细信息,以创建用户个人资料页面。

I have got the method created but the user keeps returning null in the code was shown below. 我已经创建了方法,但是用户在代码中始终返回null,如下所示。 This works fine in my MVC controller but in Web API controller it throws an error. 这在我的MVC控制器中可以正常工作,但在Web API控制器中会引发错误。

[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 System.InvalidOperationException:'序列不包含任何元素

Im presuming you're on WebAPI 2. 我假设您正在使用WebAPI 2。

Try the following: 请尝试以下操作:

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

or 要么

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

代替.First()将其更改为.FirstOrDefault()

An API is stateless meaning that there is no concept of logged in users or sessions. API是无状态的,这意味着没有登录用户或会话的概念。 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"? API无法知道谁在发送请求,可能有1万个人同时发送请求,那么到底谁在“登录”呢?

So, if you want to load a user profile then send the userID as a parameter, something like: 因此,如果要加载用户配置文件,则将userID作为参数发送,如下所示:

    [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. 附带说明一下,如果您没有任何输入参数,或者输入是原始类型(例如string或int),则ModelState.IsValid将不执行任何操作。 Only use ModelState.IsValid if you have a model class populated with the right rules. 仅当您使用正确的规则填充模型类时,才使用ModelState.IsValid。

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. 因此看起来您有一个客户端应用程序,并从中调用API。 everything I said above still applies, simply populate the data you have before calling the API. 我上面说的所有内容仍然适用,只需在调用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. 您无需在API中进行任何操作,只需将所需的所有内容从MVC控制器传递给API。

Now, all this aside, you have massive async issues. 现在,除了所有这些,您还有大量的异步问题。 that part needs work although it's not related to the question. 该部分需要工作,尽管与问题无关。

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(). 因此,请检查您是否有数据,并尝试使用.FirstOrDefault()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM