【问题标题】:.NET WebApi hits dispose before the action.NET WebApi 在操作之前点击 dispose
【发布时间】:2014-01-02 04:47:38
【问题描述】:

我有管理用户帐户的 WebApi 控制器。控制器有 3 种方法: 构造函数 - 获取类型为 UserManager<IdentityUser> 的参数,该参数由 ninject 自动注入。 Dispose - 处理 UserManager。 Register Action - 注册新用户。

我在Register 动作和Dispose 方法中设置了断点。

注意:Register 操作使用 ajax 调用。

NinjectWebCommon.cs

kernel.Bind<UserManager<IdentityUser>>().ToConstant(Startup.UserManager);

AccountController.cs

private readonly UserManager<IdentityUser> _userManager;


public AccountController(UserManager<IdentityUser> userManager)
{
    _userManager = userManager;
}

[Route("api/Account/Register")]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{ // **<---- Breakpoint**
        // code...
}

protected override void Dispose(bool disposing)
{ // **<---- Breakpoint**
    if (disposing)
    {
        _userManager.Dispose();
    }

    base.Dispose(disposing);
}

在我按下 F5(开始调试)后,Dispose 方法中的断点首先命中。然后我填写表单并将请求发送到Register 操作,其中的断点命中。

问题是UserManager 在操作发生之前被释放,我如何修复代码以便 UserManager 在应用程序停止后释放?

【问题讨论】:

  • 您是否在进行跨域 AJAX 请求?
  • @DarinDimitrov 在“跨域”中 - 您的意思是从域 X.com 到 Y.com?如果是,则否,请求是从 X.com 到 X.com/api/Account/Register。
  • 也许您的控制器操作因其名称而未被调用,而您只是得到 404? Register 不是 RESTful 控制器操作的标准名称。在 ASP.NET Web API 中,标准方法是使用 HTTP 动词之类的操作名称:Get、Post、Put……您确定您有正确的路由设置并且您正在发出正确的 HTTP 请求吗?
  • @DarinDimitrov 我忘了注意我在Register 操作上设置了RouteAttribute[Route("api/Account/Register")]Register 动作处理,但在调用 first.called 的Dispose 方法中配置的UserManager 对象之后。
  • 你有没有感觉到人们对这个 ioc/injection/testing 的东西有点过分了?

标签: asp.net-mvc asp.net-mvc-4 asp.net-web-api


【解决方案1】:

当您在控制器中处置静态对象(即处置每个请求)时,在下一个请求中,您将无法在第二个请求中使用该对象。

此外,没有必要处置使用InSingletonScopeToConstant 绑定的对象,因为它们是由Ninject 自动处置的。 如果您想为一个对象创建一个实例,您应该使用InSingletonScopeToConstant(如Ninject wiki 中所述)绑定他,然后在释放内核时释放您的对象。否则每次注入绑定时,都会创建对象的新实例。

这里是固定版本的代码:

NinjectWebCommon.cs

kernel.Bind<UserManager<IdentityUser>>().ToConstant(Startup.UserManager); // Disposed when the kernel is disposed

AccountController.cs

private readonly UserManager<IdentityUser> _userManager;


public AccountController(UserManager<IdentityUser> userManager)
{
    _userManager = userManager;
}

[Route("api/Account/Register")]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
        // code...
}

【讨论】:

    【解决方案2】:

    控制器在每次请求时都会被实例化和处理。如果您将一个单例传递给 ctor,然后在释放控制器时释放该单例,那么您将无法在第二个请求中使用该单例。

    你为什么不在一些全局应用程序关闭事件中处理 Startup.UserManager?

    【讨论】:

    • 我就是这么做的。我无法回答我的问题 在 8 小时内,当我能够回答时,我将发布我所做的并附有示例和解释。
    猜你喜欢
    • 2022-11-11
    • 1970-01-01
    • 1970-01-01
    • 2013-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-16
    • 2016-09-19
    相关资源
    最近更新 更多