Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MVC5: Asynchronous child actions Not supported #61

Closed
sanilpaul opened this issue Sep 15, 2017 · 5 comments
Closed

MVC5: Asynchronous child actions Not supported #61

sanilpaul opened this issue Sep 15, 2017 · 5 comments

Comments

@sanilpaul
Copy link

sanilpaul commented Sep 15, 2017

what is the recommended way to execute asynchronous actions (database access) through child actions in MVC5? I understand its very subjective to what i do in the child action. In my case, its only async queries to sql server using EF6.

Is wrapping in a task.run has any side effects in this case or is there any better way microsoft recommends other than changing to Synchronous?

@Html.Action("SampleChildAction)

public PartialViewResult SampleChildAction()
{
    Task.Run(async () => { await asyncMethod(); }).Result; 
    return PartialView("_SampleChildActionView");
}

I couldn't locate anything guidance from microsoft. I would appreciate any help.
https://justsimplycode.com/2016/09/04/child-action-in-mvc-5-does-not-support-async/
dotnet/aspnetcore#343

@Eilon
Copy link
Member

Eilon commented Oct 13, 2017

Unfortunately I'm not aware of any good/clean way to do this. It's a limitation of how Child Actions are implemented in MVC, which I don't think there's a good way to work around.

@Eilon Eilon closed this as completed Oct 13, 2017
@alohaninja
Copy link

alohaninja commented Dec 4, 2018

PartialViewResult is single-threaded so you can't benefit from async - in fact it blocks the app from executing entirely. Here are some options we use to work around it - keep in mind it still executes your child actions synchronously...

Using SynchronizationContext

private T InvokeAsyncMethod<T>(Func<Task<T>> func)
{
    var syncContext = SynchronizationContext.Current;
    SynchronizationContext.SetSynchronizationContext(null);

    var result = func.GetResult();

    SynchronizationContext.SetSynchronizationContext(syncContext);

    return result;
}

Using Task Library

private T InvokeAsyncMethod<T>(Func<Task<T>> func)
{
    return Task.Factory.StartNew(func)
        .Unwrap()
        .GetAwaiter()
        .GetResult();
}

To use this approach - just call your async method inline...

var user = InvokeAsyncMethod(() => user.getAsync(userId));

PartialViews have been superseded by ViewComponents in ASP.NET Core .

@benmccallum
Copy link

Dude, best timing for an answer here. Had this issue just yesterday. Thanks @alohaninja !

@benmccallum
Copy link

benmccallum commented Dec 5, 2018

I think there's a typo in the first approach. Should it be var result = func().GetAwaiter().GetResult()?

@alohaninja
Copy link

I think there's a typo in the first approach. Should it be var result = func().GetAwaiter().GetResult()?

Corrected - nice catch! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants