Asp.net web api 访问其无状态服务实例的WebApi控制器

Asp.net web api 访问其无状态服务实例的WebApi控制器,asp.net-web-api,asp.net-web-api2,azure-service-fabric,Asp.net Web Api,Asp.net Web Api2,Azure Service Fabric,我将WebApi控制器托管在一个带有一个实例的无状态服务中。服务实例(我指的是由SF运行时创建的WebApiService类的实例)维护一些作为成员字段的临时状态,通过内部(线程安全)方法公开状态。WebApi控制器需要调用方法来访问该状态 WebApiService.cs: ----------------- internal sealed class WebApiService : StatelessService { private int _state; internal in

我将WebApi控制器托管在一个带有一个实例的无状态服务中。服务实例(我指的是由SF运行时创建的WebApiService类的实例)维护一些作为成员字段的临时状态,通过内部(线程安全)方法公开状态。WebApi控制器需要调用方法来访问该状态

WebApiService.cs:
-----------------
internal sealed class WebApiService : StatelessService
{
  private int _state;

  internal int GetState() { return this._state; }

ServiceController.cs:
---------------------
public class ServiceController : ApiController
{
  public async Task<IHttpActionResult> GetStateAsync()
  {
    // Here I'd like to grab somehow the WebApiService instance 
    // and call its GetState internal method.
WebApiService.cs:
-----------------
内部密封类WebAPI服务:无状态服务
{
私营国际国家;
内部int GetState(){返回此。_state;}
ServiceController.cs:
---------------------
公共类服务控制器:ApiController
{
公共异步任务GetStateAncy()
{
//在这里,我想以某种方式获取WebApiService实例
//并调用其GetState内部方法。
我的问题是:

  • 控制器如何获取对WebApiService实例的引用

  • 将WebApiService实例存储在静态字段(可能在WebAspiService构造函数中设置)中是否安全


  • 我想你可以使用DI容器来实现这一点。我可以推荐(但是有很多可以这样做),simpleinjector还提供了每个请求的对象生命周期管理和一个web api包。您可以将状态实例作为一个单实例放在容器中,并将其注入控制器中,这将是一种线程安全的方式,最好在多线程web环境中远离静态字段。

    我认为您可以使用DI容器。我可以推荐(但也有很多人可以这样做),simpleinjector还提供了每个请求的对象生命周期管理和一个web api包。您可以将状态实例作为一个单实例放入容器中,并将其注入控制器中,这将是一种线程安全的方式,最好在多线程web环境中远离静态字段。

    您必须在在调用无状态服务的方法之前,请执行以下操作:

    public async Task<IHttpActionResult> GetStateAsync()
    {
         var proxyLocation = new ServiceUriBuilder("WebApiService");
         var svc = ServiceProxy.Create<IWebApiService>(proxyLocation.ToUri());
         return svc.GetState();
    }
    
    公共异步任务GetStateAncy()
    {
    var proxyLocation=new ServiceUriBuilder(“WebApiService”);
    var svc=ServiceProxy.Create(proxyLocation.ToUri());
    返回svc.GetState();
    }
    

    您需要创建一个包含GetState方法的接口IWebAPI服务。WebAPI服务需要实现它。基本上,您需要使用IWebAPI服务接口抽象WebAPI服务。

    在调用无状态服务的方法之前,您必须先解析控制器中的无状态服务:

    public async Task<IHttpActionResult> GetStateAsync()
    {
         var proxyLocation = new ServiceUriBuilder("WebApiService");
         var svc = ServiceProxy.Create<IWebApiService>(proxyLocation.ToUri());
         return svc.GetState();
    }
    
    公共异步任务GetStateAncy()
    {
    var proxyLocation=new ServiceUriBuilder(“WebApiService”);
    var svc=ServiceProxy.Create(proxyLocation.ToUri());
    返回svc.GetState();
    }
    

    您需要创建包含GetState方法的接口IWebAPI服务。WebAPI服务需要实现它。基本上,您需要使用IWebAPI服务接口抽象WebAPI服务。

    通过DI容器将服务实例作为依赖项注入控制器

    下面是一个使用Unity在Katana上托管Web API的示例。它是一个有状态的服务,但对无状态服务的工作方式完全相同:


    下面是一个使用Asp.Net Core及其内置依赖项注入容器(也是有状态的,但同样适用)的示例:

    通过DI容器将服务实例作为依赖项注入控制器

    下面是一个使用Unity在Katana上托管Web API的示例。它是一个有状态的服务,但对无状态服务的工作方式完全相同:


    下面是一个使用Asp.NETCore及其内置依赖项注入容器的示例(也是有状态的,但同样适用):

    那么,让我正确地说:您在无状态服务中实现状态?是的,我在无状态服务中实现一些暂时的内存状态!那么,让我正确地说:您在无状态服务中实现状态?是的,我在无状态服务中实现一些暂时的内存状态!我绝对不建议这样做。这意味着要进行跨服务远程过程调用。最终要做的是打开一个网络通道,返回到服务实例,这意味着每次调用服务实例上的方法时,它都会序列化调用,将调用一直发送到远程处理堆栈,反序列化,调用该方法,序列化结果,返回远程处理堆栈,最后反序列化。感谢@VaclavTurecek!对跨服务远程过程调用的澄清,是否也可以(通过DI)注入依赖项(无状态服务)?您可以使用ServiceProxy创建代理实例(采用目标服务接口的形式)并将其直接注入您的服务实例中。这里的好处是,您的服务与您要调用其方法的目标服务的接口相冲突。但是,这仅在目标服务未分区的情况下有效,因为您在创建代理时指定了分区键。因此,更好的方法是o注入IServiceProxyFactory,并在您的服务中使用它来创建代理(也可以模拟它进行单元测试)。我绝对不建议这样做。这是针对跨服务远程过程调用的。这最终会打开一个网络通道返回到服务实例,这意味着每次调用服务实例上的方法时,它都会序列化调用,将调用一直发送到远程处理堆栈,反序列化,调用该方法,序列化结果,返回远程处理堆栈,最后反序列化。感谢@VaclavTurecek!对跨服务远程过程调用的澄清,是否也可以(通过DI)注入依赖项(无状态服务)?您可以使用ServiceProxy创建代理实例(采用目标服务接口的形式)并将其直接注入到您的服务实例中