Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Amigo 243 posts 568 karma points
    Sep 27, 2016 @ 19:15
    Amigo
    0

    Calling async method from controller

    Hi, Im struggling trying to call an async method from my Umbraco controller. Can anyone give an example what to do to get it working?

  • Alex Skrypnyk 6175 posts 24186 karma points MVP 8x admin c-trib
    Sep 27, 2016 @ 20:57
    Alex Skrypnyk
    0

    Hi Amigo,

    What type of controller are you using?

    We have this example it our project:

    public class PageController : RenderMvcController
    {
        private ContentService _contentService;
        public PageController()
        {
            _contentService = new ContentService();
        }
        public ActionResult Index()
        {
            var page = (Page)Umbraco.AssignedContentItem;
            var Model = new PageModel(Page)
            {
                Configuration = _contentService.Client.GetContentAsync().Result
            };
    
            return View("~/Views/Page.cshtml", Model);
        }
    }
    

    I know it's not real async code, but this is solution for us.

    Hope it will help.

    Thanks,

    Alex

  • Amigo 243 posts 568 karma points
    Sep 27, 2016 @ 21:41
    Amigo
    0

    hmm i geuess its because im using Umbraco.Web.Mvc.SurfaceController. its not working then...

  • Alex Skrypnyk 6175 posts 24186 karma points MVP 8x admin c-trib
    Sep 28, 2016 @ 09:35
    Alex Skrypnyk
    0

    Hi Amigo,

    Can you share your code?

  • Amigo 243 posts 568 karma points
    Sep 28, 2016 @ 16:57
    Amigo
    0

    Hi, Alex, sure Its something like this:`

    public class NewsletterSignupSurfaceController : Umbraco.Web.Mvc.SurfaceController
    

    {

    ....
    
    [HttpPost]
    public ActionResult HandleNewsletterSubmitMailhimp(NewsletterFormViewModel model)
    {
        System.Threading.Thread.Sleep(1000);
    
        string lsReturnValue = "";
    
        var currentNode = Umbraco.TypedContent(model.CurrentNodeID);
        var currentPage = Umbraco.TypedContent(model.ActualPageID);
    
        IPublishedContent homeNode = currentPage.AncestorOrSelf(1);
        var settingsFolder = Umbraco.TypedContent(homeNode.GetProperty("websiteConfigurationNode").Value);
        var globalSettings = settingsFolder.Children.Where(x => x.DocumentTypeAlias == "USNGlobalSettings").First();
    
        if (!ModelState.IsValid)
        {
            return JavaScript(String.Format("$(NewsletterError{0}).show();$(NewsletterError{0}).html('<div class=\"info\"><p>{1}</p></div>');", model.CurrentNodeID, umbraco.library.GetDictionaryItem("USN Newsletter Form General Error")));
        }
        try
        {
            var t = Subscribe();
    
            lsReturnValue = string.Format("<div class=\"page_component alert alert-success alert-dismissible fade in\" role=\"alert\"><div class=\"info\">{0}</div></div>", currentNode.GetProperty("submissionMessage").Value.ToString() + "," + t);
            return Content(lsReturnValue);
        }
        catch (Exception ex)
        {
            return JavaScript(string.Format("$(NewsletterError{0}).show();$(NewsletterError{0}).html('<div class=\"info\"><p>{1}</p><p>{2}</p></div>');", model.CurrentNodeID, umbraco.library.GetDictionaryItem("USN Newsletter Form Signup Error"), ex.Message));
        }
    }
    
    public async Task<string> Subscribe()
    {
           ....
    
            return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
    
    }
    

    }

  • Richard van der Meel 13 posts 77 karma points
    Sep 29, 2016 @ 07:25
    Richard van der Meel
    1

    Hi Amigo,

    If you want to call an async method from a non-async location, you can not directly access the Result. That will occur in deadlocks and will not work properly.

    You should use something like:

    var result = Task.Run(async() => await _contentService.Client.GetTvContentAsync().ConfigureAwait(false)).Result;

    That should do the trick.

  • Alex Skrypnyk 6175 posts 24186 karma points MVP 8x admin c-trib
    Sep 29, 2016 @ 13:51
    Alex Skrypnyk
    0

    Thanks, Richard, this is the same what I wrote. Main idea is to use .Result, what isn't not async exactly.

    Thanks,

    Alex

  • Paul Seal 524 posts 2889 karma points MVP 7x c-trib
    Sep 29, 2016 @ 14:26
    Paul Seal
    1

    Here is how I handle async methods from a controller.

    Task<bool> deleteTask = client.DeleteAsync(SALESFORCE_OBJECT_NAME, model.id);
    
    deleteTask.Wait();
    
    bool success = deleteTask.Result;
    
  • Amigo 243 posts 568 karma points
    Sep 29, 2016 @ 21:34
    Amigo
    0

    Hi Guys,

    Hmmm its simply not working, must be because of inheriting Umbraco.Web.Mvc.SurfaceController i think. I will come back if i find out more on this problem, im not sure what to do next thoug...

  • Alex Skrypnyk 6175 posts 24186 karma points MVP 8x admin c-trib
    Sep 30, 2016 @ 09:05
    Alex Skrypnyk
    1

    Hi Amigo,

    Waiting for your response!

  • Joe Begly 19 posts 110 karma points
    Oct 11, 2019 @ 13:49
    Joe Begly
    0

    Hi everyone. I know this post is a couple years old, but why can't the ActionResult simply be made a Task

    public class EventsPageController : RenderMvcController
    {
        public ITessituraApiFactory TessituraApiFactory { get; set; }
        private readonly IUmbracoContextFactory _umbracoContext;
        public EventsPageController(IUmbracoContextFactory umbracoContext)
        {
            TessituraApiFactory = new TessituraApiFactory();
            _umbracoContext = umbracoContext;
        }
        public async Task<ActionResult> Index(ContentModel contentModel)
        {
            var service = new ProductionDetailService(TessituraApiFactory);
            var vm = new EventDetailViewModel(contentModel.Content);
            try
            {
                var eventsPage = contentModel.Content as EventsPage;
                vm.Event = eventsPage;
                vm.Performances = await service.GetProductionPerformancesViewModel(eventsPage.ProductionSeasonId);
            }
            catch (Exception ex)
            {
                vm.Error = "Error retrieving event information. Please try again later.";
            }
            return View(vm);
        }
    }
    

    In the above, I'm calling a pure asynchronous method from my service class (makes a web request to a REST API).

    I realize this is a RenderMvcController and not a Surface controller, but I've done similar things in a Surface controller, where the action result is an awaitable Task

    https://docs.microsoft.com/en-us/aspnet/mvc/overview/performance/using-asynchronous-methods-in-aspnet-mvc-4

    Stephen Cleary has great articles about this as well

    https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

    Anyway, curious to know what you all think about the solution!

Please Sign in or register to post replies

Write your reply to:

Draft