Browse Source
Complete only the reserved unit of work on response start
pull/26017/head
maliming
7 hours ago
No known key found for this signature in database
GPG Key ID: A646B9CB645ECEA4
3 changed files with
35 additions and
3 deletions
-
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs
-
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkMiddleware_Tests.cs
-
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkTestController.cs
|
|
|
@ -39,12 +39,13 @@ public class AbpUnitOfWorkMiddleware : AbpMiddlewareBase, ITransientDependency |
|
|
|
{ |
|
|
|
// Commit the ambient unit of work before the response starts, so data written
|
|
|
|
// during the request is committed before the response is flushed to the client.
|
|
|
|
// Only when this reserved unit of work is the current one: if an explicit nested
|
|
|
|
// unit of work is in progress, it is the current one and must be left to its owner.
|
|
|
|
context.Response.OnStarting(async () => |
|
|
|
{ |
|
|
|
var currentUow = _unitOfWorkManager.Current; |
|
|
|
if (currentUow != null && !currentUow.IsCompleted) |
|
|
|
if (_unitOfWorkManager.Current == uow) |
|
|
|
{ |
|
|
|
await currentUow.CompleteAsync(_cancellationTokenProvider.Token); |
|
|
|
await uow.CompleteAsync(_cancellationTokenProvider.Token); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
@ -68,4 +68,11 @@ public class UnitOfWorkMiddleware_Tests : AspNetCoreMvcTestBase |
|
|
|
var body = await GetResponseAsStringAsync("/api/unitofwork-test/RawDatabaseProviderAfterResponseFlush"); |
|
|
|
body.ShouldBe("first:threw-AbpException"); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async Task Response_Flush_Inside_Nested_Uow_Should_Not_Complete_The_Nested_Uow() |
|
|
|
{ |
|
|
|
var body = await GetResponseAsStringAsync("/api/unitofwork-test/NestedUowDuringResponseFlush"); |
|
|
|
body.ShouldBe("first:nested-completed-by-owner"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -151,4 +151,28 @@ public class UnitOfWorkTestController : AbpController |
|
|
|
|
|
|
|
await Response.WriteAsync(outcome); |
|
|
|
} |
|
|
|
|
|
|
|
[HttpGet] |
|
|
|
[Route("NestedUowDuringResponseFlush")] |
|
|
|
public async Task NestedUowDuringResponseFlush() |
|
|
|
{ |
|
|
|
using (var nested = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) |
|
|
|
{ |
|
|
|
await Response.WriteAsync("first"); |
|
|
|
await Response.Body.FlushAsync(); |
|
|
|
|
|
|
|
string outcome; |
|
|
|
try |
|
|
|
{ |
|
|
|
await nested.CompleteAsync(); |
|
|
|
outcome = ":nested-completed-by-owner"; |
|
|
|
} |
|
|
|
catch (AbpException) |
|
|
|
{ |
|
|
|
outcome = ":nested-already-completed"; |
|
|
|
} |
|
|
|
|
|
|
|
await Response.WriteAsync(outcome); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|