簡體   English   中英

從另一個服務中調用一個ServiceStack 4服務,並拋出文件上傳的樂趣

[英]Calling one ServiceStack 4 service from another with a file upload thrown in for fun

我在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那樣激動

有沒有更優雅的方式將它們組合在一起? 我可能只是想念一些非常非常明顯的東西...

我不清楚問題是什么,如果要在服務之間共享邏輯的話? 那么您可以從每個服務類中提取通用邏輯,並在兩個服務中引用共享代碼。

如果不需要依賴,我將在可重用的擴展方法后面重構共享代碼。

如果需要依賴關系,我將在兩個服務都依賴的共享邏輯類后面重構它,請參閱MVC和ServiceStack之間共享邏輯中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上下文的服務使用的通用代碼,則可以將其移至通用Service基類:

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服務

如果問題是如何執行處理文件上傳的服務, 則嵌入式版本的HttpBenchmarks中有一個示例,該示例顯示如何調用使用自定義請求上下文(使用本地FileSystem文件)來處理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,
        });
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM