Reputation: 1279
I'm tired of having to do this in my views any time I need to populate a <select>
element:
//ListObjectsFromDbAsync returns a List<T>
var data = await _manager.ListObjectsFromDbAsync();
var items = data
.Select(d=>new SelectListItem { /* conversion to SelectListItem here */})
.ToArray();
The problem is, ListObjectsFromDbAsync()
obviously requires to be await
ed in order to work with the list items.
So I devised this extension method:
public static class Extensions
{
public static Task<SelectListItem[]> AsSelect<T>(this Task<List<T>> src, Func<T, string> text, Func<T, string> value, Func<T, bool> selected = null)
{
if (src == null)
{
throw new NullReferenceException();
}
if (text == null)
{
throw new ArgumentNullException(nameof(text));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
var result = src.ContinueWith(s =>
{
var count = s.Result.Count;
var output = new SelectListItem[count];
for (int i = 0; i < count; i++)
{
var e = s.Result[i];
var d = new SelectListItem
{
Text = text(e),
Value = value(e),
Selected = selected != null && selected(e)
};
output[i] = d;
}
return output;
});
return result;
}
}
and now I can do this:
var items = await _manager
.ListObjectsFromDbAsync()
.AsSelect(a => a.Name, a => a.Id.ToString());
which, in my opinion, is simpler and cleaner.
Synthetic tests show that it works, but what I'm concerned about is using Task objects in an ASP.NET Core MVC application (I've heard it's not a really good idea; also I think what I did is a classical fake async method and I don't know what bad side effects this would have). Is there any downside or condition I should be worried about?
Upvotes: 0
Views: 699
Reputation: 456857
what I'm concerned about is using Task objects in an ASP.NET Core MVC application (I've heard it's not a really good idea; also I think what I did is a classical fake async method and I don't know what bad side effects this would have).
This is not a fake async method; there's no Task.Factory.StartNew
or Task.Run
anywhere. So this should be fine for ASP.NET.
Is there any downside or condition I should be worried about?
Yes. ContinueWith
is problematic; it's a low-level method with dangerous default behavior. Instead of using ContinueWith
, just use await
inside your extension method; that will make the code both more correct and clearer:
public static class Extensions
{
public static async Task<SelectListItem[]> AsSelectAsync<T>(this Task<List<T>> src, Func<T, string> text, Func<T, string> value, Func<T, bool> selected = null)
{
... // null checks
var data = await src;
return data.Select(d => new SelectListItem
{
Text = text(e),
Value = value(e),
Selected = selected != null && selected(e)
}).ToArray();
}
}
Upvotes: 3