2016-07-26 176 views
0

比方说,我有以下ApiController在我的ASP.NET的WebAPI应用:的WebAPI控制器重用

class MyApiController : ApiController 
{ 
    private string str; 

    [HttpGet] 
    public string SetStr(string str) 
    { 
     this.str = str; 
     MaybeSleep(); // Some executions take longer, some don't. 
     return this.str; 
    } 
} 

(现实情况是比较复杂一点,但是这应该是最重要的事情)

这是在我的环境和某些其他环境中运行良好,即使在繁重的服务器负载下也总是返回输入值。

但是,在两种环境中,即使没有太多的服务器负载,str 有时也会在设置和返回之间“奇迹般”变化。但是,它总是会更改为在那段时间发送到服务器的值,但并不总是在此请求中发送的值。

所以,我的问题是:

  • 是ApiController重用的行为,我只是期望,或者出现新的ApiController创建,使用和销毁的每一个请求的服务器进程?
  • 此行为取决于ASP.NET版本,IIS版本和/或Web.config设置?
  • 是否存在有关Microsoft提供的私人ApiController变量行为的文档?
  • 或者这可能是某个.NET或ASP.NET版本中的已知错误?
+2

为每个请求创建一个新的控制器,以便除非你有一个共享的资源干扰,这应该被隔离。 –

+1

我很肯定你的例子是错误的,并不能反映现实世界的情况。首先,我不认为控制器可以以这种方式重用(如果他们可以的话,我会很担心我的一些项目)。第二个重用或不是你只是返回参数。您将该字段用作一种局部变量。 – Stilgar

+0

除非您对多个调用使用相同的ApiController引用。 (就像创建一个全局控制器并调用方法一样,它将重写每个调用的属性),你应该很好。正如Stilgar所说,这可能不是全部情况,并且可能还有更多的情况,那么似乎 –

回答

1

的请求不应该修改控制器的状态。从入口方法到任何其他被调用的方法,都可以根据需要传递参数,因此不需要根据请求修改控制器对象本身。

如果在整个请求过程中需要维护一些状态,以至于无法将参数传递给其他方法,那么最好的做法是在HttpContext上,因为它始终是特定于请求的。 (即使那样,这种情况可能并不常见。)

代替此:

public string SetStr(string str) 
{ 
    this.str = str; 
    MaybeSleep(); // Some executions take longer, some don't. 
    return this.str; 
} 

此:

public string SetStr(string str) 
{ 
    HttpContext.Items["str"] = str; //I'd declare a constant for "str" 
    MaybeSleep(); 
    return HttpContext.Items["str"]; 
} 
+0

你有链接来备份你的第一句话吗?这似乎与另一个答案以及三条评论相矛盾。 – Alexander

+0

不,我不知道。我也完全不同意其他意见 - 我的回答是相辅相成的。没有规定说控制器不能从请求中获得某种状态,但它违背了谷物。如果你的控制器是无状态的,那么你不必担心它们是否被重用。 –

1

是ApiController重用的行为,我只是期待,或 应新ApiController创建,使用和销毁,每 单个请求的服务器进程?

当收到请求时,ControllerFactory或DependencyResolver会创建一个新的控制器实例。

基本上,主线程创建一个控制器实例,然后在多个线程之间共享相同的实例,直到请求完成。

由于第一个假设不正确,问题的其余部分不再相关。

理想情况下,如果您执行长时间运行的进程,您希望使用调度程序,以便它不会冻结UI。

你可以阅读更多斯科特Hanselman的博客 - How to run Background Tasks in ASP.NET