从另一个调用一个ServiceStack 4服务并引入文件上传以获得乐趣

时间:2014-10-01 21:37:27

标签: c# servicestack

我在4.0.31中有一个工作服务,如下所示:

public object Post(MyDTO request)
{
   foreach (var uploadedFile in base.Request.Files)
   {
      ... do something ...
   }
   return new MyDTOResponse();
}

一切都很好,我很高兴!

但是现在,我想从另一个服务中调用相同的服务方法,显然这样做的方法是:

public object Post(MyOtherDTO request)
{
  var myService = base.ResolveService<MyService>();
  // now I call some new method I wrote to bypass the file upload part, since
  // myService.Post() doesn't know about the file upload part
  var myResponse = myService.NewMethodThatLetsMePassAStreamToTheOtherService(streamData);
  ... do other stuff...
  return new MyOtherDTOResponse();
}

虽然我不是不开心,但它确实在两个服务之间创建了一个硬依赖关系,所以我不像我通常使用ServiceStack一样激动

有没有更优雅的方式将它们组合在一起?我可能只是错过了一些非常非常明显的东西......

1 个答案:

答案 0 :(得分:3)

我不是100%清楚问题是什么,如果它是如何在服务之间共享逻辑的?然后,您可以从每个服务类中提取通用逻辑,并引用两个服务中的共享代码。

如果不需要依赖项,我将重构可重用扩展方法背后的共享代码。

如果需要依赖关系,我将在一个共享逻辑类后面重构它,这是两个服务中的依赖关系,请参阅sharing logic between MVC and ServiceStack answer中的IGreeter示例:

public class MyService1 : Service
{
    public ISharedDep SharedDep { get; set] 

    public object Any(Request1 request)
    {
        //...
    }
}

public class MyService2 : Service
{
    public ISharedDep SharedDep { get; set] 

    public object Any(Request2 request)
    {
        //...
    }
}

使用基类

的请求上下文的共享逻辑

如果许多服务使用的公共代码需要base.Request上下文而不是将其移动到公共服务基类:

public class MyServiceBase : Service
{
    public ISharedDep SharedDep { get; set] 

    public object SharedMethod(object request)
    {
        //...
    }
}

public class MyServices1 : MyServiceBase { ... }
public class MyServices2 : MyServiceBase { ... }

使用扩展方法

的请求上下文的共享逻辑

如果您不想使用基类,也可以在扩展方法后面重新计算:

public static void MyServiceExtensions
{
    public static object SharedMethod(this IServicBase service, object request)
    {
        var sharedDep = service.TryResolve<ISharedDep>();
        return sharedDep.SharedMethodWithRequestCtx(request, service.Request);
    }
}

执行请求DTO

的松散耦合

如果问题是关于松散耦合的方式调用服务而不引用实现本身,您可以使用ServiceController执行Request DTO:

public class MyService : Service
{
    public object Any(Request requestDto)
    {
        var altDto = new AltRequest { Id = requestDto.Id };
        var response = HostContext.ServiceController.Execute(altDto, base.Request);
        //...
    }
}
  

注意:此API在v4.0.32 +。

中以base.ExecuteRequest(requestDto)的形式提供

将文件上传到内存中的HTTP服务

如果问题是如何执行处理文件上传的服务,则有一个example in the embedded version of HttpBenchmarks显示如何使用自定义请求上下文来调用处理HTTP文件上载的服务,该自定义请求上下文使用本地文件系统文件:

using (var admin = Resolve<AdminServices>())
{
    //...
    var dir = new FileSystemVirtualPathProvider(this, Config.WebHostPhysicalPath);
    var files = dir.GetAllMatchingFiles("*.txt")
        .Concat(dir.GetAllMatchingFiles("*.zip"));

    admin.Request = new BasicRequest
    {
        Files = files.Map(x => new HttpFile {
            ContentLength = x.Length,
            ContentType = MimeTypes.GetMimeType(x.Name),
            FileName = x.Name,
            InputStream = x.OpenRead(),
        } as IHttpFile).ToArray()
    };

    if (admin.Request.Files.Length > 0)
    {
        admin.Post(new UploadTestResults
        {
            TestPlanId = 1,
            TestRunId = testRun.Id,
            CreateNewTestRuns = true,
        });
    }
}