File tree Expand file tree Collapse file tree 7 files changed +105
-6
lines changed
Umbraco.Core/DependencyInjection
Umbraco.Web.Common/DependencyInjection
tests/Umbraco.Tests.Integration/Umbraco.Core Expand file tree Collapse file tree 7 files changed +105
-6
lines changed Original file line number Diff line number Diff line change
1
+ using System ;
2
+
3
+ namespace Umbraco . Cms . Core . DependencyInjection
4
+ {
5
+ /// <summary>
6
+ /// Provides access to a request scoped service provider when available for cases where
7
+ /// IHttpContextAccessor is not available. e.g. No reference to AspNetCore.Http in core.
8
+ /// </summary>
9
+ public interface IScopedServiceProvider
10
+ {
11
+ /// <summary>
12
+ /// Gets a request scoped service provider when available.
13
+ /// </summary>
14
+ /// <remarks>
15
+ /// Can be null.
16
+ /// </remarks>
17
+ IServiceProvider ServiceProvider { get ; }
18
+ }
19
+ }
Original file line number Diff line number Diff line change @@ -166,7 +166,9 @@ public static IUmbracoBuilder AddCoreInitialServices(this IUmbracoBuilder builde
166
166
builder . Services . AddScoped < ITagQuery , TagQuery > ( ) ;
167
167
168
168
builder . Services . AddSingleton < IUmbracoTreeSearcherFields , UmbracoTreeSearcherFields > ( ) ;
169
- builder . Services . AddSingleton < IPublishedContentQueryAccessor , PublishedContentQueryAccessor > ( ) ;
169
+ builder . Services . AddSingleton < IPublishedContentQueryAccessor , PublishedContentQueryAccessor > ( sp =>
170
+ new PublishedContentQueryAccessor ( sp . GetRequiredService < IScopedServiceProvider > ( ) )
171
+ ) ;
170
172
builder . Services . AddScoped < IPublishedContentQuery > ( factory =>
171
173
{
172
174
var umbCtx = factory . GetRequiredService < IUmbracoContextAccessor > ( ) ;
Original file line number Diff line number Diff line change 1
- using Umbraco . Cms . Infrastructure ;
2
-
3
1
namespace Umbraco . Cms . Core
4
2
{
3
+ /// <remarks>
4
+ /// Not intended for use in background threads where you should make use of <see cref="Umbraco.Cms.Core.Web.IUmbracoContextFactory.EnsureUmbracoContext"/>
5
+ /// and instead resolve IPublishedContentQuery from a <see cref="Microsoft.Extensions.DependencyInjection.IServiceScope"/>
6
+ /// e.g. using <see cref="Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.CreateScope"/>
7
+ /// <example>
8
+ /// <code>
9
+ /// // Background thread example
10
+ /// using UmbracoContextReference _ = _umbracoContextFactory.EnsureUmbracoContext();
11
+ /// using IServiceScope serviceScope = _serviceProvider.CreateScope();
12
+ /// IPublishedContentQuery query = serviceScope.ServiceProvider.GetRequiredService<IPublishedContentQuery>();
13
+ /// </code>
14
+ /// </example>
15
+ /// </remarks>
5
16
public interface IPublishedContentQueryAccessor
6
17
{
7
18
bool TryGetValue ( out IPublishedContentQuery publishedContentQuery ) ;
Original file line number Diff line number Diff line change 1
1
using System ;
2
2
using Microsoft . Extensions . DependencyInjection ;
3
+ using Umbraco . Cms . Core . DependencyInjection ;
3
4
4
5
namespace Umbraco . Cms . Core
5
6
{
6
7
public class PublishedContentQueryAccessor : IPublishedContentQueryAccessor
7
8
{
8
- private readonly IServiceProvider _serviceProvider ;
9
+ private readonly IScopedServiceProvider _scopedServiceProvider ;
9
10
10
- public PublishedContentQueryAccessor ( IServiceProvider serviceProvider ) => _serviceProvider = serviceProvider ;
11
+ [ Obsolete ( "Please use alternative constructor" ) ]
12
+ public PublishedContentQueryAccessor ( IServiceProvider serviceProvider ) => _scopedServiceProvider = serviceProvider . GetRequiredService < IScopedServiceProvider > ( ) ;
13
+
14
+ public PublishedContentQueryAccessor ( IScopedServiceProvider scopedServiceProvider ) => _scopedServiceProvider = scopedServiceProvider ;
11
15
12
16
public bool TryGetValue ( out IPublishedContentQuery publishedContentQuery )
13
17
{
14
- publishedContentQuery = _serviceProvider . GetRequiredService < IPublishedContentQuery > ( ) ;
18
+ publishedContentQuery = _scopedServiceProvider . ServiceProvider ? . GetService < IPublishedContentQuery > ( ) ;
15
19
16
20
return publishedContentQuery is not null ;
17
21
}
Original file line number Diff line number Diff line change
1
+ using System ;
2
+ using Microsoft . AspNetCore . Http ;
3
+ using Umbraco . Cms . Core . DependencyInjection ;
4
+
5
+ namespace Umbraco . Cms . Web . Common . DependencyInjection
6
+ {
7
+ /// <inheritdoc />
8
+ internal class ScopedServiceProvider : IScopedServiceProvider
9
+ {
10
+ private readonly IHttpContextAccessor _accessor ;
11
+
12
+ public ScopedServiceProvider ( IHttpContextAccessor accessor ) => _accessor = accessor ;
13
+
14
+ /// <inheritdoc />
15
+ public IServiceProvider ServiceProvider => _accessor . HttpContext ? . RequestServices ;
16
+ }
17
+ }
Original file line number Diff line number Diff line change @@ -349,6 +349,7 @@ public static IUmbracoBuilder AddWebComponents(this IUmbracoBuilder builder)
349
349
builder . Services . AddSingleton < ContentModelBinder > ( ) ;
350
350
351
351
builder . Services . AddSingleton < IUmbracoHelperAccessor , UmbracoHelperAccessor > ( ) ;
352
+ builder . Services . AddSingleton < IScopedServiceProvider , ScopedServiceProvider > ( ) ;
352
353
builder . Services . AddScoped < UmbracoHelper > ( ) ;
353
354
builder . Services . AddScoped < IBackOfficeSecurity , BackOfficeSecurity > ( ) ;
354
355
Original file line number Diff line number Diff line change
1
+ using System ;
2
+ using System . Net ;
3
+ using System . Net . Http ;
4
+ using System . Threading . Tasks ;
5
+ using Microsoft . AspNetCore . Mvc ;
6
+ using NUnit . Framework ;
7
+ using Umbraco . Cms . Core ;
8
+ using Umbraco . Cms . Tests . Integration . TestServerTest ;
9
+
10
+ namespace Umbraco . Cms . Tests . Integration . Umbraco . Core
11
+ {
12
+ [ TestFixture ]
13
+ public class PublishedContentQueryAccessorTests : UmbracoTestServerTestBase
14
+ {
15
+ [ Test ]
16
+ public async Task PublishedContentQueryAccessor_WithRequestScope_WillProvideQuery ( )
17
+ {
18
+ HttpResponseMessage result = await Client . GetAsync ( "/demo-published-content-query-accessor" ) ;
19
+ Assert . AreEqual ( HttpStatusCode . OK , result . StatusCode ) ;
20
+ }
21
+ }
22
+
23
+ public class PublishedContentQueryAccessorTestController : Controller
24
+ {
25
+ private readonly IPublishedContentQueryAccessor _accessor ;
26
+
27
+ public PublishedContentQueryAccessorTestController ( IPublishedContentQueryAccessor accessor )
28
+ {
29
+ _accessor = accessor ;
30
+ }
31
+
32
+ [ HttpGet ( "demo-published-content-query-accessor" ) ]
33
+ public IActionResult Test ( )
34
+ {
35
+ var success = _accessor . TryGetValue ( out IPublishedContentQuery query ) ;
36
+
37
+ if ( ! success || query == null )
38
+ {
39
+ throw new ApplicationException ( "It doesn't work" ) ;
40
+ }
41
+
42
+ return Ok ( ) ;
43
+ }
44
+ }
45
+ }
You can’t perform that action at this time.
0 commit comments