Copied to clipboard

Flag this post as spam?

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


  • Amigo 231 posts 506 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 5908 posts 22603 karma points MVP 4x 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 231 posts 506 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 5908 posts 22603 karma points MVP 4x admin c-trib
    Sep 28, 2016 @ 09:35
    Alex Skrypnyk
    0

    Hi Amigo,

    Can you share your code?

  • Amigo 231 posts 506 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 76 karma points
    Sep 29, 2016 @ 07:25
    Richard van der Meel
    0

    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 5908 posts 22603 karma points MVP 4x 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 428 posts 2354 karma points MVP 3x c-trib
    Sep 29, 2016 @ 14:26
    Paul Seal
    0

    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 231 posts 506 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 5908 posts 22603 karma points MVP 4x admin c-trib
    Sep 30, 2016 @ 09:05
    Alex Skrypnyk
    1

    Hi Amigo,

    Waiting for your response!

  • Joe Begly 7 posts 77 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