locked
Calling REST API from WF CodeActivity RRS feed

  • Question

  • Hi,

    I have a need to make a call to REST API from within the workflow.  I am planning to write a custom code activity.  I am just wondering if it is possible to make a call to REST API from WF CodeActivity?.

    Thanks


    Ravi

    Wednesday, May 10, 2017 3:36 PM

All replies

  • Hi Ravi,

    - try the following:

    #region Namespaces
    using RKiss.ClassExtensions;
    using System;
    using System.Activities;
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Net.Http;
    using System.Threading.Tasks;
    #endregion
    
    namespace RKiss.ActivityLibrary
    {
        public enum HttpMethods
        {
            POST, GET, PUT, DELETE
        }
      
        public sealed class SendHttpRequest : AsyncCodeActivity<HttpResponseMessage>
        {
            [Category("Input")]
            [RequiredArgument]
            [DefaultValue(null)]
            public InArgument<string> AddressUri { get; set; }
    
            [Category("Input")]
            [RequiredArgument]
            [DefaultValue(null)]
            public InArgument<HttpContent> Content { get; set; }
    
            [Category("Input")]
            [DefaultValue(null)]
            public InArgument<NameValueCollection> Headers { get; set; }
    
            [Category("Input")]
            public HttpMethods Method { get; set; }
    
            public TimeSpan Timeout { get; set; }
            public bool EnsureSuccessStatusCode { get; set; }
         
            public SendHttpRequest()
            {
                this.Timeout = TimeSpan.FromSeconds(100);
                this.EnsureSuccessStatusCode = true;
            }
            protected override void CacheMetadata(CodeActivityMetadata metadata)
            {
                RuntimeArgument contentArgument = new RuntimeArgument("Content", typeof(HttpContent), ArgumentDirection.In, true);
                metadata.Bind(this.Content, contentArgument);
    
                RuntimeArgument addressArgument = new RuntimeArgument("AddressUri", typeof(string), ArgumentDirection.In, true);
                metadata.Bind(this.AddressUri, addressArgument);
    
                RuntimeArgument headersArgument = new RuntimeArgument("Headers", typeof(NameValueCollection), ArgumentDirection.In, false);
                metadata.Bind(this.Headers, headersArgument);
    
                metadata.SetArgumentsCollection(
                    new Collection<RuntimeArgument>
                    {
      		    addressArgument,
                        contentArgument,
                        headersArgument
                    });
            }
    
            protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
            {
                try
                {
                    HttpClient client = new HttpClient() { Timeout = this.Timeout };
                    client.BaseAddress = new Uri(this.AddressUri.Get(context));
    
                    var request = new HttpRequestMessage(new HttpMethod(this.Method.ToString()), this.AddressUri.Get(context));
                    request.Content = this.Content.Get(context);
    
                    if (this.Headers != null && this.Headers.Get(context) != null)
                    {
                        var headers = this.Headers.Get(context);
                        foreach (string key in headers.Keys)
                        {
                            request.Headers.Add(key, headers[key]);                       
                        }
                    }
                    return client.SendAsync(request, HttpCompletionOption.ResponseContentRead).ToAPM<HttpResponseMessage>(callback, state);               
                }
                catch(Exception ex)
                {
                    ex.Data.Add("Location", this.DisplayName);
                    ex.Data.Add("Uri", this.AddressUri.Get(context));
                    ex.Data.Add("Method", this.Method.ToString());
                    throw ex;
                }
            }
    
            protected override HttpResponseMessage EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
            {
                try
                {             
                    var hrm = ((Task<HttpResponseMessage>)result).Result;
                    if (this.EnsureSuccessStatusCode)
                        hrm.EnsureSuccessStatusCode();
                    else if(hrm.IsSuccessStatusCode == false)
                    {
                        // tbd
                    }
                    return hrm;
                }
                catch (AggregateException ae)
                {
                    ae.Data.Add("Location", this.DisplayName);
                    ae.Data.Add("Uri", this.AddressUri.Get(context));
                    ae.Data.Add("Method", this.Method.ToString());
                    throw ae.InnerException;
                }
                catch (Exception ex)
                {
                    ex.Data.Add("Location", this.DisplayName);
                    ex.Data.Add("Uri", this.AddressUri.Get(context));
                    ex.Data.Add("Method", this.Method.ToString());
                    throw;
                }
            }   
        }
    }

    using System;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Xml.Linq;
    
    namespace RKiss.ClassExtensions
    {
        #region Async pattern
        // thanks to http://blogs.msdn.com/b/pfxteam/archive/2011/06/27/using-tasks-to-implement-the-apm-pattern.aspx
        public static class TaskExtensions
        {
            public static Task<TResult> ToAPM<TResult>(this Task<TResult> task, AsyncCallback callback, object state)
            {
                if (task.AsyncState == state)
                {
                    if (callback != null)
                    {
                        task.ContinueWith(delegate { callback(task); },
                            CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default);
                    }
                    return task;
                }
    
                var tcs = new TaskCompletionSource<TResult>(state);
                task.ContinueWith(delegate
                {
                    if (task.IsFaulted)
                        tcs.TrySetException(task.Exception.InnerExceptions);
                    else if (task.IsCanceled)
                        tcs.TrySetCanceled();
                    else
                        tcs.TrySetResult(task.Result);
    
                    if (callback != null)
                        callback(tcs.Task);
    
                }, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default);
                return tcs.Task;
            }
        }
        #endregion
    }

    Thanks

    Roman



    • Edited by Roman Kiss Friday, May 19, 2017 9:29 AM
    Friday, May 19, 2017 9:29 AM