FromResult or IServiceScopeFactory in Blazor server-side - c#

So I've been injecting IServiceScopeFactory to my pages to use it's scope when getting my data through EF Core.
But yesterday I stumbled upon somebody using Task.FromResult when calling the database.
Is one preferred over the other and if so why?
Thank you in advance!
Ex Task.FromResult
//In code behind
[Inject]
IMyService myService { get; set; }
protected void GetSomeData()
{
var someData = await myServie.GetSomeData();
}
//From serviceClass
public async Task<List<SomeData>> GetSomeData(int id)
{
return await Task.FromResult(db.SomeTable.Where(x => x.Id == qualifierVersionId).AsEnumerable());
}
Ex
//In code behind
[Inject]
IServiceScopeFactory ScopeFactory { get; set; }
protected void GetSomeData()
{
using (var serviceScope = ScopeFactory.CreateScope())
{
var myService = serviceScope.ServiceProvider.GetService<IMyService>();
var someData = await myServie.GetSomeData();
}
}
//From serviceClass
public async Task<List<SomeData>> GetSomeData(int id)
{
return await db.SomeTable.Where(x => x.Id == id).ToListAsync();
}
Edit (because the questions of why I want to know which way to go)
I need to use one or the other because when using Server side Blazor the lifespan makes a Scoop behave like a Singleton. So if I for instance call return await db.SomeTable.Where(x => x.Id == id).ToListAsync(); without the IServiceScopeFactory it will live until you close the website. So this creates an error: 'A second operation started on this context before a previous operation completed.'.

You can't compare the two as they don't have anything in common.
Task.FromResult just creates a task that's completed successfully with the specified result. I believe one of the main use cases for using Task.FromResult is when you're implementing an async interface but your implementation is synchronous, as in the example above. This is not really a good idea on DB calls as they could take a long time.
I'm not sure why you're using the IServiceScopeFactory above. If it's so that the service you're requesting is scoped to the lifetime of the component you're requesting it in then there is a better way.
public class MyComponent : OwningComponentBase<IMyService>
{
protected void GetSomeData(int id)
{
var someData = await Service.GetSomeData(id);
}
}
public class MyService : IMyService
{
public async Task<List<SomeData>> GetSomeData(int id)
{
return await db.SomeTable.Where(x => x.Id == id).ToListAsync();
}
}
By using OwningComponentBase a service scope is created for you under the hood and the service is exposed by the base component via the Service property. I've written a blog post on it if you want to know more.

Related

Memory leak in Xamarin Forms app when using DI in a Task

I am creating a Xamarin Forms application, and I am using the Xamarin Profiler to show that I have a memory leak. I have tracked the memory leak down to where it is happening, but I can't understand WHY it is happening.
I have a class (we will call it MyClass for now). And that class is using a Timer to call a service once every second. That service makes a REST call to retrieve a bunch of information, and then serializes the results back into an object....
MyClass:
public class MyClass : ContentPage
{
private readonly IMyService myService;
public MyClass() : base()
{
}
protected override async void OnAppearing()
{
StartTimer();
}
private void StartTimer()
{
Task.Run(async() =>
{
while(true)
{
myService = ((App)App.Current)
.serviceProvider
.GetRequiredService<IMyService>();
//--- everytime I call myService.GetSystemStatus(), my allocated memory continues to rise
MyResponse response = await myService.GetSystemStatus();
Device.BeginInvokeOnMainThread(() =>
{
// update the UI here...
});
await Task.Delay(1000);
}
});
}
}
MyService (Singleton):
public class MyService : IMyService
{
private readonly IMyHttpClientFactory httpClientFactory;
public MyService(IMyHttpClientFactory httpClientFactory)
{
this.httpClientFactory = httpClientFactory;
}
public async Task<MyResponse> GetSystemStatus()
{
return await httpClientFactory.Create().GetAsync<MyResponse>(
"http://example.com/api/status"
);
}
}
MyHttpClientFactory (Singleton):
public class MyHttpClientFactory : IMyHttpClientFactory
{
private readonly IServiceProvider _serviceProvider;
public MyHttpClientFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public MyHttpClient Create()
{
return _serviceProvider.GetRequiredService<MyHttpClient>();
}
}
MyHttpClient:
public class MyHttpClient : IDisposable
{
private HttpClient _httpClient;
public MyHttpClient ()
{
_httpClient = new HttpClient();
_httpClient.Timeout = TimeSpan.FromSeconds(10);
}
public async Task<T> GetAsync<T>(string url) where T : new()
{
string s = await GetStringAsync(url);
return JsonConvert.DeserializeObject<T>(s);
}
public async Task<string> GetStringAsync(string url)
{
using (var response = await _httpClient.GetAsync(url))
{
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
}
My services are defined as follows:
public partial class App : Application
public ServiceProvider serviceProvider;
public App()
{
IServiceCollection services = new ServiceCollection();
ConfigureServices(services);
serviceProvider = services.BuildServiceProvider();
InitializeComponent();
}
private void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<MyHttpClient>("MyHttpClient", x =>
{
x.Timeout = TimeSpan.FromSeconds(5);
});
services.AddSingleton<IMyHttpClientFactory, MyHttpClientFactory>();
services.AddSingleton<IMyService, MyService>();
}
}
Best I can tell, the memory is going up because I am referencing the DI MyService inside a separate thread. But I am not sure if this is the reason or if there is something else that would be causing the leak?
Any advice would be greatly appreciated!!!
Thanks!
From what I understand from your code and your comments, it looks like you're looping by calling StartTimer() inside the Device.StartTimer() method.
According to the documentation, Device.StartTimer() is recurring and will occur every X seconds, depending of your interval parameter.
By removing the call to StartTimer() (the one between t.Dispose() and return false of MyClass.StartTimer, your code should work as expected and you will not create a new timer every x seconds
What could be the cause of the leak:
Your MyHttpClient class implements the IDisposable interface, yet the code to use an instance of this class is not leveraging the disposable nature of the object.
Even though the internal HttpClient instance is wrapped in a using statement, the MyHttpClient instance will not be disposed of as you would expect.
// from MyHttpClient class
public async Task<MyResponse> GetSystemStatus()
{
// no using statement here
return await httpClientFactory.Create().GetAsync<MyResponse>(
"http://example.com/api/status"
);
}
// should be:
public async Task<MyResponse> GetSystemStatus()
{
using (var client = await httpClientFactory.Create())
{
return await client.GetAsync<MyResponse>("http://example.com/api/status");
}
}
Another thing to try is to change the location of the resolution of the MyService instance to inside the Task since this is where it is used. This will allow the task to own the resource, and allow it to be collected when the task is complete.
private void StartTimer()
{
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
Task t = Task.Run(async() =>
{
// resolve the service here
myService = ((App)App.Current)
.serviceProvider
.GetRequiredService<IMyService>();
MyResponse response = await myService.GetSystemStatus();
Device.BeginInvokeOnMainThread(() =>
{
// update the UI here...
});
});
t.Wait();
t.Dispose();
StartTimer();
return false;
});
}
A couple of additional observations of your code:
In your HttpClientFactory's Create() method, you are resolving an instance of your client from the DI container.
Your MyHttpClient class has a default constructor which means the resolution is not needed since there are no additional dependencies requiring DI support.
Your code could simply return a new MyHttpClient() instance from the Create() method without the need for DI.
Your MyHttpClient also implements the IMyHttpClient interface, but your factory returns the concrete type. This means you need to either remove the interface as unnecessary or change the return type to be the interface type since the interface is redundant unless it is used.
Thank you all for your answers....
I finally figured out the source of the memory leak.
The problem was that I was referencing "MyService" like this:
myService = ((App)App.Current)
.serviceProvider
.GetRequiredService<IMyService>();
The problem was that the serviceProvider object was a public property on my App. So each time I referenced the provider inside my loop, it was creating the leak.
To get around this, I added an abstract method to each of my pages that implemented MyClass to return the service correctly using DI. This has corrected my memory leak issue....
Thanks all for the help!
I don't think that your timer logic is the cause of the leak.
But in case it is useful to you, here is a clean way to do work periodically, yet if work takes a long time, avoid events "piling up".
Given await/async, no Timer is needed.
(There is an alternative solution that starts/stops a single System.Timers.Timer, but I won't go into that here.)
Replace StartTimer() declaration with the following:
/// <summary> Runs until keepRunning() returns false.
/// Delays by "msecDelay" AFTER finishing the previous loop's non-UI work. </summary>
private void StartTaskLoopWhileKeepRunning(Func<bool> keepRunning, int msecDelay = 250)
{
Task.Run(async () =>
{
while (keepRunning())
{
// Do non-UI work here.
// ... possibly slow work ...
Device.BeginInvokeOnMainThread(() =>
{
// NOTE: This work will run in parallel with the next delay.
// ... Do UI work here. ...
});
// Non-UI thread sleeps for msec.
await Task.Delay(msecDelay);
}
});
}

.NET DI with runtime implementation resolvers

I have a bit of a weird case involving DI, specifically in resolving implementation at runtime from within the same service. I'm aware that I could inject a service provider, but that would seemingly violate the dependency inversion principle.
Also, apologies if this ends up being more of a architectural/design question; I've recently switched from .NET Framework development and still getting acquainted with the limitations of DI. Note that I've simplified & changed the business context for obvious reasons, so keep in mind that the hierarchy/structure is the important part... For this question, I've decided to go with the classic example of an online retailer.
Project Overview/Example:
core library (.NET Class Library)
- IRetailerService: public service consumed by client apps
└ IOrderService: facade/aggregate services injected into ^
├ IInventoryManager: internal components injected into facade/aggregate services as well as other components
├ IProductRespository
└ IPriceEstimator
Aggregate/Façade Services
public class RetailerService : IRetailerService
{
private readonly IOrderService _orderService;
public OrderService( IOrderService orderService, ... ) { //... set injected components }
async Task IRetailerService.Execute( Guid id )
{
await _orderService.Get( id );
}
async Task IRetailerService.Execute( Guid id, User user )
{
await _orderService.Get( id, user );
}
}
internal class OrderService : IOrderService
{
public OrderService( IInventoryManager inventoryManager, IProductRespository productRepo, ... ) { }
async Task<object> IOrderService.Get( Guid id )
{
//... do stuff with the injected components
await _inventoryManager.Execute( ...args );
await _productRepo.Execute( ...args );
}
async Task<object> IOrderService.Get( Guid id, User user ) { }
}
The Problem:
Lets say I want to log IOrderService.Get( Guid id, User user ), but only when this override with the User is provided - this includes logging inside the injected components (InventoryManager, IProductRepository, etc.) as well.
The only solutions I can see at the moment are to either:
Add an additional layer to this hierarchy & use named registration with scope lifetimes to determine if a null vs logging implementation is passed down.
Inject the service provider into the public facing service IRetailerService, and somehow pass down the correct implementation.
I think my ideal solution would be some type of decorator/middleware to control this... I've only given the core library code; but there is also a WebApi project within the solution that references this library. Any ideas/guidance would be greatly appreciated.
I would recommend using a factory to create the order service, and any downstream dependencies that need the logger. Here is a fully worked example:
void Main()
{
var serviceProvider = new ServiceCollection()
.AddScoped<IRetailerService, RetailerService>()
.AddScoped<IInventoryManager, InventoryManager>()
.AddScoped<IOrderServiceFactory, OrderServiceFactory>()
.BuildServiceProvider();
var retailerService = serviceProvider.GetRequiredService<IRetailerService>();
Console.WriteLine("Running without user");
retailerService.Execute(Guid.NewGuid());
Console.WriteLine("Running with user");
retailerService.Execute(Guid.NewGuid(), new User());
}
public enum OrderMode
{
WithUser,
WithoutUser
}
public interface IOrderServiceFactory
{
IOrderService Get(OrderMode mode);
}
public class OrderServiceFactory : IOrderServiceFactory
{
private readonly IServiceProvider _provider;
public OrderServiceFactory(IServiceProvider provider)
{
_provider = provider;
}
public IOrderService Get(OrderMode mode)
{
// Create the right sort of order service - resolve dependencies either by new-ing them up (if they need the
// logger) or by asking the service provider (if they don't need the logger).
return mode switch
{
OrderMode.WithUser => new OrderService(new UserLogger(), _provider.GetRequiredService<IInventoryManager>()),
OrderMode.WithoutUser => new OrderService(new NullLogger(), _provider.GetRequiredService<IInventoryManager>())
};
}
}
public interface IRetailerService
{
Task Execute(Guid id);
Task Execute(Guid id, User user);
}
public interface IOrderService
{
Task Get(Guid id);
Task Get(Guid id, User user);
}
public class User { }
public class RetailerService : IRetailerService
{
private readonly IOrderServiceFactory _orderServiceFactory;
public RetailerService(
IOrderServiceFactory orderServiceFactory)
{
_orderServiceFactory = orderServiceFactory;
}
async Task IRetailerService.Execute(Guid id)
{
var orderService = _orderServiceFactory.Get(OrderMode.WithoutUser);
await orderService.Get(id);
}
async Task IRetailerService.Execute(Guid id, User user)
{
var orderService = _orderServiceFactory.Get(OrderMode.WithUser);
await orderService.Get(id, user);
}
}
public interface ISpecialLogger
{
public void Log(string message);
}
public class UserLogger : ISpecialLogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
}
public class NullLogger : ISpecialLogger
{
public void Log(string message)
{
// Do nothing.
}
}
public interface IInventoryManager { }
public class InventoryManager : IInventoryManager { }
internal class OrderService : IOrderService
{
private readonly ISpecialLogger _logger;
public OrderService(ISpecialLogger logger, IInventoryManager inventoryManager)
{
_logger = logger;
}
public async Task Get(Guid id)
{
_logger.Log("This is the 'id-only' method");
}
public async Task Get(Guid id, User user)
{
_logger.Log("This is the 'id-and-user' method");
}
}
Using this, you get the following output:
Running without user
Running with user
This is the 'id-and-user' method
The factory lets you have complete control of how the downstream components are generated, so you can get as complicated as you want.
You can resolve your dependencies in the IOrderService.Get method at runtime so that each method has its own dependencies. Nevertheless this doesn't fully resolve your problem. Nested dependencies IInventoryManager inventoryManager, IProductRespository productRepo, ... should be able to enable logging as well.
So instead you may use:
internal class OrderService : IOrderService
{
public OrderService( IServiceProvider serviceProvider) { }
async Task<object> IOrderService.Get( Guid id )
{
var inventoryManager = (IInventoryManager)serviceProvider.GetService(typeof(IInventoryManager));
inventoryManager.Logging = false;
var productRepo = (IProductRespository)serviceProvider.GetService(typeof(IProductRespository));
productRepo.Logging = false;
//... do stuff with the injected components
await inventoryManager.Execute( ...args );
await productRepo.Execute( ...args );
}
async Task<object> IOrderService.Get( Guid id, User user ) {
var inventoryManager = (IInventoryManager)serviceProvider.GetService(typeof(IInventoryManager));
inventoryManager.Logging = false;
var productRepo = (IProductRespository)serviceProvider.GetService(typeof(IProductRespository));
productRepo.Logging = true;
//... do stuff with the injected components
await inventoryManager.Execute( ...args );
await productRepo.Execute( ...args );
}
}
You may also provide a Factory / Builder with a parameter to enable logging.
But in any case because you want a different behavior in nested classes starting from a same root class, this may be complicated.
Another option is to provide 2 implementations of IOrderService, one that include logging, and the other not. But I'm not sure this may help you because you had probably good reasons to provide an overload to the method and not split them into separate services. And this doesn't resolve the issue for nested injections.
Last option may be to use a singleton LoggingOptions class.
Each dependency has a dependency on this class and because this is a singleton, each time you enter your overload you set it to true and so all classes are informed of your intent to log. Nevertheless this highly depends of your architecture. If both methods may be called nearly on the same time, this may break the nested dependencies logging behavior or interrupt the logging at any time.
Take a look at this question this may help. By considering this question, you may provide a Factory for each of your dependency (including nested ones) that would set logging behavior on each call to the overload method.

How to get all users async, with AspNetCore.Identity and MongoDb?

This question asks about how to retrieve all users from AspNetCore Identity, in an async method:
ASP.NET Identity 2 UserManager get all users async
The non-sync method is simple:
[HttpGet]
public ActionResult<IEnumerable<UserDto>> GetAsync()
{
var users = userManager.Users
.ToList()
.Select(user => user.AsDto());
return Ok(users);
}
The obvious solution is this:
[HttpGet]
public async Task<ActionResult<IEnumerable<UserDto>>> GetAsync()
{
var users = await userManager.Users
.ToListAsync()
.Select(user => user.AsDto());
return Ok(users);
}
But this doesn't work because userManager.Users is an IQueryable<>, and that doesn't define a .ToListAsync().
The recommended answer in the question above is:
public async Task<List<User>> GetUsersAsync()
{
using (var context = new YourContext())
{
return await UserManager.Users.ToListAsync();
}
}
But that is tied to Entity Framework, and if you're using AspNetCore.Identity.MongoDbCore, you won't have any dbcontexts, and the above simply doesn't work.
One comment on the answer points out that the .ToListAsync() extension method is defined in System.Data.Entity - but if you're using MongoDb you won't be including that.
How, actually, do you access all users from UserManager<> in an async method?
Basiccally, AspNetCore.Identity.MongoDbCore was just implementation wrapping around core concept of AspNetCore.Identity. And things gone just a bit difference from Sql implementation, cause they doesn't make use of unit of work concept (I know, SaveChange implement would wrap operation in transaction, but for everymethod call, the query execute immediately got this pretty similar to mongo in someway).
Then, If we need any furthur extension of those basic task, why don't just write our own implementation on top of default MongoDbCore implementation like good old days ?
// Starting with UserStore
public class ApplicationUserStore : MongoUserStore<How many generic would depend on use cases>, IApplicationUserStore
{
protected IMongoCollection<TUser> ApplicationUsersCollection;
public ApplicationUserStore(ApplicationDbContext context, IdentityErrorDescriber describer = null) : base(context, describer)
{
ApplicationUsersCollection = Context.GetCollection<TUser>();
}
public async Task<ICollection<ApplicationUser>> GetAllUserAsync() => // We have access to UsersCollection, implement as normal mongodb operation;
}
// Then, UserManager
public class ApplicationUserManager : UserManager<How many generic would depend on use cases>
{
private readonly IApplicationUserStore _applicationUserStore;
// Constructtor that could resolve our ApplicationUserStore.
public ApplicationUserManager(IApplicationUserStore applicationUserStore,...)
{
_applicationUserStore = applicationUserStore;
}
public async Task<ICollection<ApplicationUser>> GetAllUserAsync() => _applicationUserStore.GetAllUserAsync();
// Registering things
services.AddScoped<IApplicationUserStore, ApplicationUserStore>();
services.AddScoped<ApplicationUserManager>();
}
This was just describe the idea, implementation should be vary.

Why is HttpContext.Session status changing to disposed?

I'm trying to store token I get from external api on session.
code snippet concerning this;
[HttpPost]
public async void Post()
{
if (HttpContext.Session.GetValue<User>("Token") == null)
{
HttpContext.Session.SetValue("Token", "test");
var res = await _loginBusiness.GetToken();
HttpContext.Session.SetValue("Token", res);
}
}
HttpContext.Session.SetValue("Token", "test");
in this part, it doesn't occur any error but second the same code line give an error after GetToken().
related error
System.ObjectDisposedException: 'IFeatureCollection has been disposed.
Object name: 'Collection'.'
Also GetToken():
public async Task<User> GetToken()
{
String url = "login/login";
var client = httpClientFactory.CreateClient("VoiceScope");
var postRes = await client.PostAsync<User>(new UserLogin(), url);
return postRes;
}
The problem is that you are using async void. These promises can't be observed and their semantics end up a lot different from a normal Task. Your disposal is happening early because the infrastructure just assumes your Post method has completed (it has no way to tell otherwise).
Change the signature of Post to be:
public async Task Post()
Please note that async void should be limited to event handlers.
I am not sure about using HttpContext. You have IHttpContextAccessor in asp.net core.
I think for store token you can use this
public class UserContext
{
public UserContext(IHttpContextAccessor context)
{
Token = GetAccessToken(context);
}
private static string GetAccessToken(IHttpContextAccessor contextAccessor)
{
var identity = (ClaimsIdentity)contextAccessor?.HttpContext?.User?.Identity;
return identity?.Claims.FirstOrDefault(x => x.Type == "token")?.Value;
}
public string Token { get; }
}
And then, add this staff in your DI like scope object and use it in controllers via ServiceProvider.

Can I clone DbContext from existing one?

I'm working on .NET Core Web API and I have one endpoint where I want to run three operations in parallel. All three of them use the same database, so I need three copies of DbContext. I created a simple Factory class, which I later inject into my "Data" class.
Is it possible (if it's, is a good practice), to inject DbContext into my factory class (using built in .NET Core IoC) and when someone calls "CreateMyDbContext" method, just deep clone the one which was injected at the beginning?
EDIT:
Here is the example with the DbContext Pool:
public class FooData : IFooData
{
private readonly Func<DisposableScopedContextWrapper> _func;
public FooData(Func<DisposableScopedContextWrapper> func)
{
_func = func;
}
public async Task<List<Apple>> GetApples()
{
using (var wrapper = _func())
{
var apples = await wrapper.Context.Apples.FromSqlRaw("SELECT.... complicated query").ToListAsync();
return apples;
}
}
public async Task<List<Orange>> GetOranges()
{
using (var wrapper = _func())
{
var oranges = await wrapper.Context.Oranges.FromSqlRaw("SELECT.... complicated query").ToListAsync();
return oranges;
}
}
}
public class FooService
{
private readonly IFooData _fooData;
public FooData(IFooData fooData)
{
_fooData = fooData;
}
public async Task<List<Fruit>> GetFruits()
{
var appleTask = _fooData.GetApples();
var orangeTask = _fooData.GetOranges();
(var result1, var result2) = await (appleTask, orangeTask).WhenAll();
// ...
}
}
I definitely would not recommend any deepcloning for multiple reasons, one of them being that you will need to figure out a lot of EF internals to make it right, and internals can change (and you will need to spend some time on it).
Second option would be just creating your context manually, which I would recommend against also cause modern infrastructure uses DbContext pooling.
So what you can to register Func<DbContext> (or create your own factory) like this:
services.AddSingleton<Func<DbContext>>(provider => () =>
{
var scope = provider.CreateScope();
return scope.ServiceProvider.GetRequiredService<DbContext>();
});
the issue here is that scope here would not be disposed and you can't (if you have default scope for your DbContext) dispose the scope inside the Func cause your context will be disposed also. So you can try creating some disposable wrapper so you can manually dispose everything like this:
public class DisposableScopedContextWrapper : IDisposable
{
private readonly IServiceScope _scope;
public DbContext Context { get; }
public DisposableScopedContextWrapper(IServiceScope scope)
{
_scope = scope;
Context = _scope.ServiceProvider.GetService<DbContext>();
}
public void Dispose()
{
_scope.Dispose();
}
}
services.AddSingleton<Func<DisposableScopedContextWrapper>>(provider =>() =>
{
var scope = provider.CreateScope();
return new DisposableScopedContextWrapper(scope);
});
Inject in your classes Func<DisposableScopedContextWrapper> func and use it
using (var wrapper = func())
{
wrapper.Context...
}

Categories