Skip to content

Commit eba424e

Browse files
committed
Filter and middleware changes
- renamed and moved to subfolders - more methods to override and customize behavior - summary for methods updated
1 parent 3cf80f2 commit eba424e

File tree

2 files changed

+86
-40
lines changed

2 files changed

+86
-40
lines changed

Extensions/Xtensive.Orm.Web/SessionToActionProviderFilter.cs renamed to Extensions/Xtensive.Orm.Web/Filters/SessionActionFilter.cs

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
namespace Xtensive.Orm.Web.Filters
1212
{
1313
/// <summary>
14-
/// Filter that
14+
/// DataObjects.Net Session providing action filter.
1515
/// </summary>
16-
public class SessionToActionProviderFilter : IActionFilter, IAsyncActionFilter
16+
public class SessionActionFilter : IActionFilter, IAsyncActionFilter
1717
{
1818
private SessionAccessor sessionAccessor;
1919
private IDisposable contextBindResource;
@@ -38,62 +38,65 @@ public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionE
3838
}
3939

4040
/// <summary>
41-
/// Opens session.
41+
/// Opens <see cref="Session"/>.
4242
/// </summary>
43-
/// <param name="domain">Domain instance</param>
44-
/// <param name="context">Action executing context</param>
43+
/// <param name="domain"><see cref="Domain"/> instance.</param>
44+
/// <param name="context">Action executing context.</param>
4545
/// <returns>Instance of <see cref="Session"/>.</returns>
4646
protected virtual Session OpenSession(Domain domain, ActionExecutingContext context) => domain.OpenSession();
4747

4848
/// <summary>
49-
/// Opens session asynchronously.
49+
/// Opens <see cref="Session"/> asynchronously.
5050
/// </summary>
51-
/// <param name="domain">Domain instance</param>
52-
/// <param name="context">Action executing context</param>
51+
/// <param name="domain">A <see cref="Domain"/> instance.</param>
52+
/// <param name="context">The <see cref="ActionExecutingContext"/>.</param>
5353
/// <returns>Instance of <see cref="Session"/>.</returns>
5454
protected virtual Task<Session> OpenSessionAsync(Domain domain, ActionExecutingContext context) => domain.OpenSessionAsync();
5555

5656
/// <summary>
57-
/// Opens transaction scope.
57+
/// Opens <see cref="TransactionScope"/>.
5858
/// </summary>
59-
/// <param name="session">Domain instance.</param>
60-
/// <param name="context">Action executing context.</param>
59+
/// <param name="session">The <see cref="Session"/> to open transaction scope.</param>
60+
/// <param name="context">The <see cref="ActionExecutingContext"/>.</param>
6161
/// <returns>Instance of <see cref="TransactionScope"/>.</returns>
6262
protected virtual TransactionScope OpenTransaction(Session session, ActionExecutingContext context) =>
6363
session.OpenTransaction();
6464

6565
/// <summary>
66-
/// Opens transaction scope asynchronously.
66+
/// Opens <see cref="TransactionScope"/> asynchronously.
6767
/// </summary>
68-
/// <param name="session">Domain instance.</param>
69-
/// <param name="context">Action executing context.</param>
68+
/// <param name="session">The <see cref="Session"/> to open transaction scope.</param>
69+
/// <param name="context">The <see cref="ActionExecutingContext"/>.</param>
7070
/// <returns>Instance of <see cref="TransactionScope"/>.</returns>
7171
protected virtual async Task<TransactionScope> OpenTransactionAsync(Session session, ActionExecutingContext context) =>
7272
await session.OpenTransactionAsync();
7373

7474
/// <summary>
75-
/// Executes before <see cref="TransactionScope"/> dispose.
75+
/// Executes before <paramref name="transactionScope"/> disposing.
7676
/// </summary>
7777
/// <param name="transactionScope">The transaction scope which is about to be disposed.</param>
78-
/// <param name="session">The session transaction scope belongs to.</param>
78+
/// <param name="session">The <see cref="Session"/> transaction scope belongs to.</param>
7979
/// <param name="context">The <see cref="ActionExecutedContext"/>.</param>
8080
protected virtual void OnTransactionScopeDisposing(TransactionScope transactionScope, Session session, ActionExecutedContext context)
8181
{
82+
if (context.Exception == null || CompleteTransactionOnException(context.Exception, context)) {
83+
transactionScope.Complete();
84+
}
8285
}
8386

8487
/// <summary>
85-
/// Executes after <see cref="TransactionScope"/> is dispose.
88+
/// Executes after <see cref="TransactionScope"/> is disposed.
8689
/// </summary>
87-
/// <param name="session">The session the disposed transaction scope belonged to.</param>
90+
/// <param name="session">The <see cref="Session"/> the disposed transaction scope belonged to.</param>
8891
/// <param name="context">The <see cref="ActionExecutedContext"/>.</param>
8992
protected virtual void OnTransactionScopeDisposed(Session session, ActionExecutedContext context)
9093
{
9194
}
9295

9396
/// <summary>
94-
/// Executes before <see cref="Session"/> dispose.
97+
/// Executes before <paramref name="session"/> disposing.
9598
/// </summary>
96-
/// <param name="session">The session which is about to be disposed.</param>
99+
/// <param name="session">The <see cref="Session"/> which is about to be disposed.</param>
97100
/// <param name="context">The <see cref="ActionExecutedContext"/>.</param>
98101
protected virtual void OnSessionDisposing(Session session, ActionExecutedContext context)
99102
{
@@ -107,18 +110,29 @@ protected virtual void OnSessionDisposed(ActionExecutedContext context)
107110
{
108111
}
109112

113+
114+
/// <summary>
115+
/// Allows to define what exceptions will not leat to transaction rollback.
116+
/// </summary>
117+
/// <param name="exception">The exception thrown by action.</param>
118+
/// <param name="context">The <see cref="ActionExecutedContext"/>.</param>
119+
/// <returns><see langword="true"/> for complete transaction scope, otherwise, <see langword="false"/>.</returns>
120+
protected virtual bool CompleteTransactionOnException(Exception exception, ActionExecutedContext context) => false;
121+
110122
//internal void Persist(PersistReason reason) => Persist(reason, false).GetAwaiter().GetResult();
111123
private async ValueTask ExecuteBeforeAction(ActionExecutingContext context, bool isAsync)
112124
{
113125
var actionParameters = context.ActionDescriptor.Parameters;
114126

127+
skipResourcesRelease = true;
128+
115129
//this search can probably be improved by caching action names with needed parameters
116130
foreach (var p in actionParameters) {
117131
if (p.ParameterType == WellKnownTypes.SessionAccessorType) {
118132
// trying to get registered accessor as service
119133
var accessor = GetSessionAccesorFromServices(context.HttpContext);
120134
if (accessor != null) {
121-
// this is registered as service and probably filled with middlewere
135+
// this is registered as service and probably filled with middleware
122136
skipResourcesRelease = true;
123137
sessionAccessor = accessor;
124138
if (accessor.ContextIsBound) {
@@ -199,12 +213,10 @@ private async ValueTask<IDisposable> CreateSessionAndBindContext(SessionAccessor
199213
private static Domain GetDomainFromServices(HttpContext context)
200214
{
201215
var domain = (Domain) context.RequestServices.GetService(WellKnownTypes.DomainType);
202-
return domain == null
203-
? throw new InvalidOperationException("Domain is not found among registered services.")
204-
: domain;
216+
return domain ?? throw new InvalidOperationException("Domain is not found among registered services.");
205217
}
206218

207219
private static SessionAccessor GetSessionAccesorFromServices(HttpContext context) =>
208220
(SessionAccessor) context.RequestServices.GetService(WellKnownTypes.SessionAccessorType);
209221
}
210-
}
222+
}

Extensions/Xtensive.Orm.Web/OpenSessionMiddlewere.cs renamed to Extensions/Xtensive.Orm.Web/Middleware/OpenSessionMiddleware.cs

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77
using System.Threading.Tasks;
88
using System.Runtime.ExceptionServices;
99

10-
namespace Xtensive.Orm.Web
10+
namespace Xtensive.Orm.Web.Middleware
1111
{
12-
1312
/// <summary>
1413
/// DataObjects.Net Session providing middleware.
1514
/// </summary>
16-
public class OpenSessionMiddlewere
15+
public class OpenSessionMiddleware
1716
{
1817
private readonly RequestDelegate next;
1918

@@ -50,8 +49,13 @@ public async Task Invoke(HttpContext context)
5049
}
5150
finally {
5251
RemoveResourcesFromContext(context);
52+
await OnTransactionDisposingAsync(transaction, session, context);
5353
await transaction.DisposeAsync();
54+
await OnTransactionDisposedAsync(session, context);
55+
56+
await OnSessionDisposingAsync(session, context);
5457
await session.DisposeAsync();
58+
await OnSessionDisposedAsync(context);
5559
}
5660
}
5761
}
@@ -61,22 +65,54 @@ public async Task Invoke(HttpContext context)
6165
}
6266

6367
/// <summary>
64-
/// Opens session asynchronously.
68+
/// Opens <see cref="Session"/> asynchronously.
6569
/// </summary>
66-
/// <param name="domain">Domain instance</param>
67-
/// <param name="context">Action executing context</param>
70+
/// <param name="domain">A <see cref="Domain"/> instance.</param>
71+
/// <param name="context">The <see cref="HttpContext"/>.</param>
6872
/// <returns>Instance of <see cref="Session"/>.</returns>
6973
protected virtual Task<Session> OpenSessionAsync(Domain domain, HttpContext context) => domain.OpenSessionAsync();
7074

7175
/// <summary>
72-
/// Opens transaction scope asynchronously.
76+
/// Opens <see cref="TransactionScope"/> asynchronously.
7377
/// </summary>
74-
/// <param name="session">Domain instance.</param>
75-
/// <param name="context">Action executing context.</param>
78+
/// <param name="session">A <see cref="Session"/> instance to open transaction for.</param>
79+
/// <param name="context">The <see cref="HttpContext"/>.</param>
7680
/// <returns>Instance of <see cref="TransactionScope"/>.</returns>
7781
protected virtual async Task<TransactionScope> OpenTransactionAsync(Session session, HttpContext context) =>
7882
await session.OpenTransactionAsync();
7983

84+
/// <summary>
85+
/// Executes before <paramref name="transactionScope"/> disposing.
86+
/// </summary>
87+
/// <param name="transactionScope">The <see cref="TransactionScope"/> to be disposed.</param>
88+
/// <param name="session">The <see cref="Session"/> the <paramref name="transactionScope"/> belongs to.</param>
89+
/// <param name="context">The <see cref="HttpContext"/>.</param>
90+
/// <returns>Task performing this operation.</returns>
91+
protected virtual ValueTask OnTransactionDisposingAsync(TransactionScope transactionScope, Session session, HttpContext context) => default;
92+
93+
/// <summary>
94+
/// Executes after <see cref="TransactionScope"/> disposed.
95+
/// </summary>
96+
/// <param name="session">The <see cref="Session"/> disposed scoped belonged too.</param>
97+
/// <param name="context">The <see cref="HttpContext"/>.</param>
98+
/// <returns>Task performing this operation.</returns>
99+
protected virtual ValueTask OnTransactionDisposedAsync(Session session, HttpContext context) => default;
100+
101+
/// <summary>
102+
/// Executes before <paramref name="session"/> disposing.
103+
/// </summary>
104+
/// <param name="session">The <see cref="Session"/> to be disposed.</param>
105+
/// <param name="context">The <see cref="HttpContext"/>.</param>
106+
/// <returns>Task performing this operation.</returns>
107+
protected virtual ValueTask OnSessionDisposingAsync(Session session, HttpContext context) => default;
108+
109+
/// <summary>
110+
/// Executes after <see cref="Session"/> disposed.
111+
/// </summary>
112+
/// <param name="context">The <see cref="HttpContext"/>.</param>
113+
/// <returns>Task performing this operation.</returns>
114+
protected virtual ValueTask OnSessionDisposedAsync(HttpContext context) => default;
115+
80116
/// <summary>
81117
/// Determines whether transaction should be completed even though exception appeared.
82118
/// </summary>
@@ -108,18 +144,16 @@ private static void RemoveResourcesFromContext(HttpContext context)
108144
private static Domain GetDomainFromServices(HttpContext context)
109145
{
110146
var domain = (Domain) context.RequestServices.GetService(WellKnownTypes.DomainType);
111-
return domain == null
112-
? throw new InvalidOperationException("Domain is not found among registered services.")
113-
: domain;
147+
return domain ?? throw new InvalidOperationException("Domain is not found among registered services.");
114148
}
115149

116150
/// <summary>
117-
/// Creates an instance of <see cref="OpenSessionMiddlewere"/>
151+
/// Creates an instance of <see cref="OpenSessionMiddleware"/>
118152
/// </summary>
119153
/// <param name="next"></param>
120-
public OpenSessionMiddlewere(RequestDelegate next)
154+
public OpenSessionMiddleware(RequestDelegate next)
121155
{
122156
this.next = next;
123157
}
124158
}
125-
}
159+
}

0 commit comments

Comments
 (0)