Copied to clipboard

Flag this post as spam?

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


  • Amigo 245 posts 600 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 6182 posts 24284 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 245 posts 600 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 6182 posts 24284 karma points MVP 8x admin c-trib
    Sep 28, 2016 @ 09:35
    Alex Skrypnyk
    0

    Hi Amigo,

    Can you share your code?

  • Amigo 245 posts 600 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 6182 posts 24284 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 2890 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 245 posts 600 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 6182 posts 24284 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!

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies