Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从基类访问异步方法_C#_Asp.net Core_.net Core_Async Await - Fatal编程技术网

C# 从基类访问异步方法

C# 从基类访问异步方法,c#,asp.net-core,.net-core,async-await,C#,Asp.net Core,.net Core,Async Await,我有一个.NETCore2.2WebAPI项目,在这个项目中,我尝试使用异步/等待方法来完成所有工作。我有一个名为“UserController”的控制器。我的“UserController”中有一些方法需要访问LoggedInUserId。因此,为了实现这一点,我创建了一个“BaseController”,这个“UserController”将从中继承 BaseController.cs public abstract class BaseController : ControllerBase

我有一个.NETCore2.2WebAPI项目,在这个项目中,我尝试使用异步/等待方法来完成所有工作。我有一个名为“UserController”的控制器。我的“UserController”中有一些方法需要访问LoggedInUserId。因此,为了实现这一点,我创建了一个“BaseController”,这个“UserController”将从中继承

BaseController.cs

public abstract class BaseController : ControllerBase
{
    public int LoggedInUserId
    {
        get
        {
           Task<int> task = Task.Run(async () => await GetLoggedInUserId());
           return task.Result;
        }
    }
}
[Route("api/[controller]")]
[ApiController]
public class UsersController : BaseController
{
    public UsersController() 
    {

    }

    [HttpPost("create")]
    public async Task<ActionResult<User>> Create([FromBody] userCreate)
    {
        _userService.CreateUser(userCreate, LoggedInUserId);
    }
}
_userService.CreateUser(userCreate, await GetLoggedInUserId());
因此,我的问题如下:

  • 这两种方法都被认为是正确的吗?它们是否都符合异步/等待方式
  • 这两种方法是否完成了相同的任务
  • 这两种方法中的任何一种都有缺点吗
  • 如果有人发现这些方法有任何缺陷,你能提出一种更好/更干净的方法来实现我的目标吗
  • 这两种方法都被认为是正确的吗?它们是否都符合异步/等待方式

    否。使用
    任务。运行
    结果
    未按设计使用
    异步
    /
    等待
    Task.Run
    部分是多余的

    这两种方法是否完成了相同的任务

    它们都获得登录用户。但是,基于
    结果的方法在执行此操作时会阻塞线程

    这两种方法中的任何一种都有缺点吗

    对。基于
    结果的方法会阻塞线程,这会限制您的可伸缩性


    在我看来,有一种更好的方法可以做到这一点。我对ASP.NET核心管道不太熟悉,但在构建控制器之前,应该有一种异步处理身份验证和获取登录用户id的方法。然后可以将其作为属性公开,因为此时它已经加载

  • 这两种方法都被认为是正确的吗?它们是否都符合异步/等待方式
  • 不,第一种方法不是正确的方法,除非您有明确的理由使用
    Task.Result
    ,即使如此,
    Task.Run
    也不需要调用用
    Task
    声明的方法

  • 这两种方法是否完成了相同的任务
  • 不,第一个方法创建一个不需要的线程来同步阻塞它。如果您所在的框架使用SynchronizationContext(想想经典的ASP.NET、WinForms、Xamarin或WPF),您将面临死锁。然而,第二种方法是执行异步调用的正确方法。在这两种情况下,您最终都会得到用户id,至少现在是这样

  • 这两种方法中的任何一种都有缺点吗
  • 是的,如上所述,第一种方法只会造成资源浪费

  • 如果有人发现这些方法有任何缺陷,你能提出一种更好/更干净的方法来实现我的目标吗

  • 嗯,您没有提到您使用什么进行身份验证/授权,但是如果您使用的是ASP.NET核心标识,那么它已经通过
    UserManager
    类为您提供了该功能。否则,您可以使用一个中间件来读取请求并将所需数据添加到控制器。

    关于此问题的多篇文章。让我们看看如何修复它:

    public abstract class BaseController : ControllerBase
    {
        public Task<int> LoggedInUserId()
        {
            return await GetLoggedInUserId();
        }
    }
    
    公共抽象类BaseController:ControllerBase
    {
    公共任务LoggedInUserId()
    {
    返回等待GetLoggedInUserId();
    }
    }
    
    或者只需使GetLoggedInUserId()可访问。你明白了。然后:

    [HttpPost("create")]
    public async Task<ActionResult<User>> Create([FromBody] userCreate)
    {
         int loggedInUserId = await LoggedInUserId();
        _userService.CreateUser(userCreate, loggedInUserId);
        ...
    }
    
    [HttpPost(“创建”)]
    公共异步任务创建([FromBody]userCreate)
    {
    int loggedInUserId=等待loggedInUserId();
    _CreateUser(userCreate,loggedInUserId);
    ...
    }
    
    有一个更好的方法,如果使用ASP.NET Core Identity,或者使用MiddleWareSrry,我使用IdentityServer进行身份验证。因此,在我发送的代码片段中,您没有看到我将“HttpContextAccessor”单例服务注入到“BaseController”中。从那里,我获取“HttpContext.User”对象并获取我需要的声明。在我的例子中,我需要使用“sub”来查询数据库,以获取用户的唯一标识符。因此,从您的意思来看,我可以通过一些自定义中间件或identity server提供的“UserManager”类异步完成所有这些工作?@BryMan否,identity server是一个在ASP.NET Core上运行的开源产品,但它不是ASP.NET Core identity(这是Microsoft产品)。不过,您根本不需要
    HttpContextAccesor
    ,这仅适用于不存在于请求中的类,而控制器实例始终存在于请求中。您可以使用(在实例方法中)
    var userId=User.cluses…
    谢谢你Henk,这正是我最终所做的。但是有一个问题,我可以像这样内联调用GetLoggedInUserId-_userService.CreateUser(userCreate,wait GetLoggedInUserId())而不是在外部调用GetLoggedInUserId()方法吗?是的,很容易尝试。但这纯粹是装饰性的,我不介意额外的变量。