[英]Calling one ServiceStack 4 service from another with a file upload thrown in for fun
I have a working service in 4.0.31 that looks like this: 我在4.0.31中有一个工作服务,看起来像这样:
public object Post(MyDTO request)
{
foreach (var uploadedFile in base.Request.Files)
{
... do something ...
}
return new MyDTOResponse();
}
Everything works great, and I'm happy! 一切都很好,我很高兴!
But now, I want to call the same service method from within another service, the way to do this apparently is: 但是现在,我想从另一个服务中调用相同的服务方法,显然,这样做的方法是:
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();
}
While I'm not unhappy with this, it does create a hard dependency between the two services, so I'm not thrilled like I usually am with ServiceStack! 虽然我对此并不满意 ,但它确实在两个服务之间创建了硬依赖性,因此,我并不像通常使用ServiceStack那样激动 !
Is there a more elegant way of putting this together? 有没有更优雅的方式将它们组合在一起? I'm probably just missing something really, really obvious...
我可能只是想念一些非常非常明显的东西...
I'm not 100% clear on what the issue is, if it's how to share logic between services? 我不清楚问题是什么,如果要在服务之间共享逻辑的话? then you could pull common logic out of each service class and reference the shared code in both Services.
那么您可以从每个服务类中提取通用逻辑,并在两个服务中引用共享代码。
If no dependencies are required I'll refactor the shared code behind re-usable extension methods . 如果不需要依赖,我将在可重用的扩展方法后面重构共享代码。
If dependencies are required I will refactor it behind a shared logic class that's a dependency in both Services, see the IGreeter
example in the sharing logic between MVC and ServiceStack answer : 如果需要依赖关系,我将在两个服务都依赖的共享逻辑类后面重构它,请参阅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)
{
//...
}
}
If it's common code used by many Services that requires the base.Request
context than you could move it to a common Service base class: 如果是许多需要
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 { ... }
If you prefer not to use a base class, this can be re-factored behind an extension method as well: 如果您不想使用基类,则也可以在扩展方法后面对其进行重构:
public static void MyServiceExtensions
{
public static object SharedMethod(this IServicBase service, object request)
{
var sharedDep = service.TryResolve<ISharedDep>();
return sharedDep.SharedMethodWithRequestCtx(request, service.Request);
}
}
If the issue is about a loose-coupled way to call Services without a reference to the implementation itself you can execute the Request DTO with the ServiceController: 如果问题是关于调用服务的松散耦合方式而不涉及实现本身,则可以使用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);
//...
}
}
Note: this API is available as
base.ExecuteRequest(requestDto)
in v4.0.32+.注意:此API在v4.0.32 +中可以作为
base.ExecuteRequest(requestDto)
使用。
If the issue is instead how to execute a Service that handles file uploads, there's an example in the embedded version of HttpBenchmarks showing how to call a Service that processes HTTP File uploads with a custom Request Context that uses local FileSystem files instead: 如果问题是如何执行处理文件上传的服务, 则嵌入式版本的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.