diff --git a/README.md b/README.md index 3034f7c4c..4ec45383b 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,12 @@ Version 2.0 - [ ] Generic Command & Event Activities - [ ] Workflow Host REST API - [ ] Workflow Host gRPC API +- [ ] Workflow Server - [ ] Distributed Hosting Support (support for multi-node environments) - [ ] Localization Support +- [ ] More activities +- [ ] Workflow Designer UI improvements +- [ ] Activity Editor UI improvements Version 3.0 diff --git a/src/activities/Elsa.Activities.Console/Elsa.Activities.Console.csproj b/src/activities/Elsa.Activities.Console/Elsa.Activities.Console.csproj index 481f8e48b..51fbf63f8 100644 --- a/src/activities/Elsa.Activities.Console/Elsa.Activities.Console.csproj +++ b/src/activities/Elsa.Activities.Console/Elsa.Activities.Console.csproj @@ -4,13 +4,19 @@ netstandard2.0 1.0.0 latest - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides the following Console activities: + + * ReadLine + * WriteLine + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core GitHub - elsa, workflows, orchard + elsa, workflows diff --git a/src/activities/Elsa.Activities.ControlFlow/Elsa.Activities.ControlFlow.csproj b/src/activities/Elsa.Activities.ControlFlow/Elsa.Activities.ControlFlow.csproj index acced5f61..c60769450 100644 --- a/src/activities/Elsa.Activities.ControlFlow/Elsa.Activities.ControlFlow.csproj +++ b/src/activities/Elsa.Activities.ControlFlow/Elsa.Activities.ControlFlow.csproj @@ -2,6 +2,25 @@ netstandard2.0 + 1.0.0 + latest + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides the following control flow activities: + + * ForEach + * Fork + * IfElse + * Join + * Switch + * While + + 2019 + https://github.com/elsa-workflows/elsa-core + https://github.com/elsa-workflows/elsa-core + GitHub + elsa, workflows diff --git a/src/activities/Elsa.Activities.Dropbox/Elsa.Activities.Dropbox.csproj b/src/activities/Elsa.Activities.Dropbox/Elsa.Activities.Dropbox.csproj index 008267d2e..8ac8489d0 100644 --- a/src/activities/Elsa.Activities.Dropbox/Elsa.Activities.Dropbox.csproj +++ b/src/activities/Elsa.Activities.Dropbox/Elsa.Activities.Dropbox.csproj @@ -4,13 +4,18 @@ netstandard2.0 1.0.0 latest - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides the following Dropbox activities: + + * SaveToDropbox + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core GitHub - elsa, workflows, orchard, dropbox + elsa, workflows, dropbox diff --git a/src/activities/Elsa.Activities.Email/Elsa.Activities.Email.csproj b/src/activities/Elsa.Activities.Email/Elsa.Activities.Email.csproj index 481f8e48b..9db0d7236 100644 --- a/src/activities/Elsa.Activities.Email/Elsa.Activities.Email.csproj +++ b/src/activities/Elsa.Activities.Email/Elsa.Activities.Email.csproj @@ -4,13 +4,18 @@ netstandard2.0 1.0.0 latest - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides the following Email activities: + + * SendEmail + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core GitHub - elsa, workflows, orchard + elsa, workflows, email, smtp diff --git a/src/activities/Elsa.Activities.Http/Activities/HttpRequestEvent.cs b/src/activities/Elsa.Activities.Http/Activities/ReceiveHttpRequest.cs similarity index 95% rename from src/activities/Elsa.Activities.Http/Activities/HttpRequestEvent.cs rename to src/activities/Elsa.Activities.Http/Activities/ReceiveHttpRequest.cs index 3de7b6cf7..369bc6591 100644 --- a/src/activities/Elsa.Activities.Http/Activities/HttpRequestEvent.cs +++ b/src/activities/Elsa.Activities.Http/Activities/ReceiveHttpRequest.cs @@ -1,135 +1,135 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Elsa.Activities.Http.Extensions; -using Elsa.Activities.Http.Models; -using Elsa.Activities.Http.Services; -using Elsa.Attributes; -using Elsa.Design; -using Elsa.Extensions; -using Elsa.Results; -using Elsa.Services; -using Elsa.Services.Models; -using Microsoft.AspNetCore.Http; -using Newtonsoft.Json.Linq; - -namespace Elsa.Activities.Http.Activities -{ - [ActivityDefinition( - Category = "HTTP", - DisplayName = "Receive HTTP Request", - Description = "Receive an incoming HTTP request.", - RuntimeDescription = "x => !!x.state.path ? `Handle ${ x.state.method } ${ x.state.path }.` : x.definition.description", - Outcomes = new[] { OutcomeNames.Done } - )] - public class HttpRequestEvent : Activity - { - public static Uri GetPath(JObject state) - { - return state.GetState(nameof(Path)); - } - - public static string GetMethod(JObject state) - { - return state.GetState(nameof(Method)); - } - - private readonly IHttpContextAccessor httpContextAccessor; - private readonly IEnumerable contentFormatters; - - public HttpRequestEvent( - IHttpContextAccessor httpContextAccessor, - IEnumerable contentFormatters) - { - this.httpContextAccessor = httpContextAccessor; - this.contentFormatters = contentFormatters; - } - - /// - /// The path that triggers this activity. - /// - [ActivityProperty(Hint = "The relative path that triggers this activity.")] - public Uri Path - { - get => GetState(); - set => SetState(value); - } - - /// - /// The HTTP method that triggers this activity. - /// - [ActivityProperty( - Type = ActivityPropertyTypes.Select, - Hint = "The HTTP method that triggers this activity." - )] - [SelectOptions("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD")] - public string Method - { - get => GetState(); - set => SetState(value); - } - - /// - /// A value indicating whether the HTTP request content body should be read and stored as part of the HTTP request model. - /// The stored format depends on the content-type header. - /// - [ActivityProperty( - Hint = - "A value indicating whether the HTTP request content body should be read and stored as part of the HTTP request model. The stored format depends on the content-type header." - )] - public bool ReadContent - { - get => GetState(); - set => SetState(value); - } - - protected override ActivityExecutionResult OnExecute(WorkflowExecutionContext workflowContext) - { - return Halt(true); - } - - protected override async Task OnResumeAsync( - WorkflowExecutionContext workflowContext, - CancellationToken cancellationToken) - { - var request = httpContextAccessor.HttpContext.Request; - var model = new HttpRequestModel - { - Path = new Uri(request.Path.ToString(), UriKind.Relative), - QueryString = request.Query.ToDictionary(x => x.Key, x => new StringValuesModel(x.Value)), - Headers = request.Headers.ToDictionary(x => x.Key, x => new StringValuesModel(x.Value)), - Method = request.Method - }; - - if (ReadContent) - { - if (request.HasFormContentType) - { - model.Form = (await request.ReadFormAsync(cancellationToken)).ToDictionary( - x => x.Key, - x => new StringValuesModel(x.Value) - ); - } - - var parser = SelectContentParser(request.ContentType); - var content = await request.ReadContentAsBytesAsync(cancellationToken); - model.Body = await parser.ParseAsync(content, request.ContentType); - } - - Output["Content"] = model; - workflowContext.CurrentScope.LastResult = model; - - return Done(); - } - - private IContentFormatter SelectContentParser(string contentType) - { - var formatters = contentFormatters.OrderByDescending(x => x.Priority).ToList(); - return formatters.FirstOrDefault( - x => x.SupportedContentTypes.Contains(contentType, StringComparer.OrdinalIgnoreCase) - ) ?? formatters.Last(); - } - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Elsa.Activities.Http.Extensions; +using Elsa.Activities.Http.Models; +using Elsa.Activities.Http.Services; +using Elsa.Attributes; +using Elsa.Design; +using Elsa.Extensions; +using Elsa.Results; +using Elsa.Services; +using Elsa.Services.Models; +using Microsoft.AspNetCore.Http; +using Newtonsoft.Json.Linq; + +namespace Elsa.Activities.Http.Activities +{ + [ActivityDefinition( + Category = "HTTP", + DisplayName = "Receive HTTP Request", + Description = "Receive an incoming HTTP request.", + RuntimeDescription = "x => !!x.state.path ? `Handle ${ x.state.method } ${ x.state.path }.` : x.definition.description", + Outcomes = new[] { OutcomeNames.Done } + )] + public class ReceiveHttpRequest : Activity + { + public static Uri GetPath(JObject state) + { + return state.GetState(nameof(Path)); + } + + public static string GetMethod(JObject state) + { + return state.GetState(nameof(Method)); + } + + private readonly IHttpContextAccessor httpContextAccessor; + private readonly IEnumerable contentFormatters; + + public ReceiveHttpRequest( + IHttpContextAccessor httpContextAccessor, + IEnumerable contentFormatters) + { + this.httpContextAccessor = httpContextAccessor; + this.contentFormatters = contentFormatters; + } + + /// + /// The path that triggers this activity. + /// + [ActivityProperty(Hint = "The relative path that triggers this activity.")] + public Uri Path + { + get => GetState(); + set => SetState(value); + } + + /// + /// The HTTP method that triggers this activity. + /// + [ActivityProperty( + Type = ActivityPropertyTypes.Select, + Hint = "The HTTP method that triggers this activity." + )] + [SelectOptions("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD")] + public string Method + { + get => GetState(); + set => SetState(value); + } + + /// + /// A value indicating whether the HTTP request content body should be read and stored as part of the HTTP request model. + /// The stored format depends on the content-type header. + /// + [ActivityProperty( + Hint = + "A value indicating whether the HTTP request content body should be read and stored as part of the HTTP request model. The stored format depends on the content-type header." + )] + public bool ReadContent + { + get => GetState(); + set => SetState(value); + } + + protected override ActivityExecutionResult OnExecute(WorkflowExecutionContext workflowContext) + { + return Halt(true); + } + + protected override async Task OnResumeAsync( + WorkflowExecutionContext workflowContext, + CancellationToken cancellationToken) + { + var request = httpContextAccessor.HttpContext.Request; + var model = new HttpRequestModel + { + Path = new Uri(request.Path.ToString(), UriKind.Relative), + QueryString = request.Query.ToDictionary(x => x.Key, x => new StringValuesModel(x.Value)), + Headers = request.Headers.ToDictionary(x => x.Key, x => new StringValuesModel(x.Value)), + Method = request.Method + }; + + if (ReadContent) + { + if (request.HasFormContentType) + { + model.Form = (await request.ReadFormAsync(cancellationToken)).ToDictionary( + x => x.Key, + x => new StringValuesModel(x.Value) + ); + } + + var parser = SelectContentParser(request.ContentType); + var content = await request.ReadContentAsBytesAsync(cancellationToken); + model.Body = await parser.ParseAsync(content, request.ContentType); + } + + Output["Content"] = model; + workflowContext.CurrentScope.LastResult = model; + + return Done(); + } + + private IContentFormatter SelectContentParser(string contentType) + { + var formatters = contentFormatters.OrderByDescending(x => x.Priority).ToList(); + return formatters.FirstOrDefault( + x => x.SupportedContentTypes.Contains(contentType, StringComparer.OrdinalIgnoreCase) + ) ?? formatters.Last(); + } + } } \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Http/Activities/HttpRequestAction.cs b/src/activities/Elsa.Activities.Http/Activities/SendHttpRequest.cs similarity index 93% rename from src/activities/Elsa.Activities.Http/Activities/HttpRequestAction.cs rename to src/activities/Elsa.Activities.Http/Activities/SendHttpRequest.cs index 965b40736..ee4176331 100644 --- a/src/activities/Elsa.Activities.Http/Activities/HttpRequestAction.cs +++ b/src/activities/Elsa.Activities.Http/Activities/SendHttpRequest.cs @@ -1,267 +1,270 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using Elsa.Activities.Http.Models; -using Elsa.Activities.Http.Services; -using Elsa.Attributes; -using Elsa.Design; -using Elsa.Expressions; -using Elsa.Extensions; -using Elsa.Results; -using Elsa.Services; -using Elsa.Services.Models; -using Microsoft.AspNetCore.Http; - -namespace Elsa.Activities.Http.Activities -{ - [ActivityDefinition( - Category = "HTTP", - DisplayName = "Send HTTP Request", - Description = "Send an HTTP request.", - RuntimeDescription = "x => !!x.state.url ? `Send HTTP ${ x.state.method } ${ x.state.url.expression }.` : x.definition.description", - Outcomes = "x => !!x.state.supportedStatusCodes ? x.state.supportedStatusCodes : []" - )] - public class HttpRequestAction : Activity - { - private readonly IWorkflowExpressionEvaluator expressionEvaluator; - private readonly HttpClient httpClient; - private readonly IEnumerable contentFormatters; - - public HttpRequestAction( - IWorkflowExpressionEvaluator expressionEvaluator, - IHttpClientFactory httpClientFactory, - IEnumerable contentFormatters) - { - this.expressionEvaluator = expressionEvaluator; - httpClient = httpClientFactory.CreateClient(nameof(HttpRequestAction)); - this.contentFormatters = contentFormatters; - } - - /// - /// The URL to invoke. - /// - [ActivityProperty(Hint = "The URL to send the HTTP request to.")] - public WorkflowExpression Url - { - get - { - var url = GetState>(); - - if (url != null && !string.IsNullOrWhiteSpace(url.Expression) && Uri.TryCreate( - url.Expression, - UriKind.RelativeOrAbsolute, - out var uri - )) - return new WorkflowExpression(url.Syntax, uri.ToString()); - - return new WorkflowExpression(LiteralEvaluator.SyntaxName, ""); - } - set => SetState(new WorkflowExpression(value.Syntax, value.Expression)); - } - - /// - /// The HTTP method to use. - /// - [ActivityProperty( - Type = ActivityPropertyTypes.Select, - Hint = "The HTTP method to use when making the request." - )] - [SelectOptions("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD")] - public string Method - { - get => GetState(() => "GET"); - set => SetState(value); - } - - /// - /// The body to send along with the request. - /// - [ActivityProperty(Hint = "The HTTP content to send along with the request.")] - [ExpressionOptions(Multiline = true)] - public WorkflowExpression Content - { - get => GetState(() => new WorkflowExpression(LiteralEvaluator.SyntaxName, "")); - set => SetState(value); - } - - /// - /// The Content Type header to send along with the request body. - /// - [ActivityProperty( - Type = ActivityPropertyTypes.Select, - Hint = "The content type to send with the request (if applicable)." - )] - [SelectOptions("text/plain", "text/html", "application/json", "application/xml")] - public WorkflowExpression ContentType - { - get => GetState(() => new WorkflowExpression(LiteralEvaluator.SyntaxName, "")); - set => SetState(value); - } - - [ActivityProperty( - Hint = "The Authorization header value to send." - )] - public WorkflowExpression Authorization - { - get => GetState>(); - set => SetState(value); - } - - /// - /// The headers to send along with the request. - /// - [ActivityProperty(Hint = "The headers to send along with the request. One 'header: value' pair per line.")] - public WorkflowExpression RequestHeaders - { - get => GetState(() => new WorkflowExpression(LiteralEvaluator.SyntaxName, "")); - set => SetState(value); - } - - [ActivityProperty(Hint = "Check to read the content of the response.")] - public bool ReadContent - { - get => GetState(() => true); - set => SetState(value); - } - - /// - /// A list of HTTP status codes this activity can handle. - /// - [ActivityProperty( - Type = ActivityPropertyTypes.List, - Hint = "A list of possible HTTP status codes to handle, comma-separated. Example: 200, 400, 404" - )] - public HashSet SupportedStatusCodes - { - get => GetState(() => new HashSet { 200 }); - set => SetState(value); - } - - - protected override async Task OnExecuteAsync(WorkflowExecutionContext workflowContext, - CancellationToken cancellationToken) - { - var request = await CreateRequestAsync(workflowContext, cancellationToken); - var response = await httpClient.SendAsync(request, cancellationToken); - var hasContent = response.Content != null; - var contentType = response.Content?.Headers.ContentType.MediaType; - - var responseModel = new HttpResponseModel - { - StatusCode = response.StatusCode, - Headers = new Dictionary( - response.Headers.ToDictionary(x => x.Key, x => x.Value.ToArray()) - ) - }; - - if (hasContent && ReadContent) - { - var formatter = SelectContentFormatter(contentType); - - responseModel.Content = await response.Content.ReadAsByteArrayAsync(); - responseModel.ParsedContent = await formatter.ParseAsync(responseModel.Content, contentType); - } - - workflowContext.SetLastResult(responseModel); - Output["Response"] = responseModel; - var statusEndpoint = ((int) response.StatusCode).ToString(); - - return Outcomes(new[] { OutcomeNames.Done, statusEndpoint }); - } - - private IContentFormatter SelectContentFormatter(string contentType) - { - var formatters = contentFormatters.OrderByDescending(x => x.Priority).ToList(); - return formatters.FirstOrDefault( - x => x.SupportedContentTypes.Contains(contentType, StringComparer.OrdinalIgnoreCase) - ) ?? formatters.Last(); - } - - private async Task CreateRequestAsync(WorkflowExecutionContext workflowContext, - CancellationToken cancellationToken) - { - var methodSupportsBody = GetMethodSupportsBody(Method); - var uri = await expressionEvaluator.EvaluateAsync(Url, workflowContext, cancellationToken); - var request = new HttpRequestMessage(new HttpMethod(Method), uri); - - var authorizationHeaderValue = await expressionEvaluator.EvaluateAsync( - Authorization, - workflowContext, - cancellationToken - ); - - var requestHeaders = await ParseRequestHeadersAsync(workflowContext, cancellationToken); - - if (methodSupportsBody) - { - var body = await expressionEvaluator.EvaluateAsync(Content, workflowContext, cancellationToken); - var contentType = await expressionEvaluator.EvaluateAsync( - ContentType, - workflowContext, - cancellationToken - ); - - if (!string.IsNullOrWhiteSpace(body)) - { - request.Content = new StringContent(body, Encoding.UTF8, contentType); - } - } - - if (!string.IsNullOrWhiteSpace(authorizationHeaderValue)) - { - request.Headers.Authorization = AuthenticationHeaderValue.Parse(authorizationHeaderValue); - } - - foreach (var header in requestHeaders) - { - request.Headers.Add(header.Key, header.Value.AsEnumerable()); - } - - return request; - } - - private async Task ParseRequestHeadersAsync(WorkflowExecutionContext workflowContext, - CancellationToken cancellationToken) - { - var headersText = await expressionEvaluator.EvaluateAsync( - RequestHeaders, - workflowContext, - cancellationToken - ); - var headers = new HeaderDictionary(); - - if (headersText != null) - { - var headersQuery = - from line in Regex.Split(headersText, "\\n", RegexOptions.Multiline) - let pair = line.Split(':', '=') - select new KeyValuePair(pair[0], pair[1]); - - foreach (var header in headersQuery) - { - var headerValueExpression = new WorkflowExpression(RequestHeaders.Syntax, header.Value); - var headerValue = await expressionEvaluator.EvaluateAsync( - headerValueExpression, - workflowContext, - cancellationToken - ); - headers.Add(header.Key, headerValue); - } - } - - return headers; - } - - private bool GetMethodSupportsBody(string method) - { - var methods = new[] { "POST", "PUT", "PATCH" }; - return methods.Contains(method, StringComparer.InvariantCultureIgnoreCase); - } - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Elsa.Activities.Http.Models; +using Elsa.Activities.Http.Services; +using Elsa.Attributes; +using Elsa.Design; +using Elsa.Expressions; +using Elsa.Extensions; +using Elsa.Results; +using Elsa.Services; +using Elsa.Services.Models; +using Microsoft.AspNetCore.Http; + +namespace Elsa.Activities.Http.Activities +{ + [ActivityDefinition( + Category = "HTTP", + DisplayName = "Send HTTP Request", + Description = "Send an HTTP request.", + RuntimeDescription = "x => !!x.state.url ? `Send HTTP ${ x.state.method } ${ x.state.url.expression }.` : x.definition.description", + Outcomes = "x => !!x.state.supportedStatusCodes ? x.state.supportedStatusCodes : []" + )] + public class SendHttpRequest : Activity + { + private readonly IWorkflowExpressionEvaluator expressionEvaluator; + private readonly HttpClient httpClient; + private readonly IEnumerable contentFormatters; + + public SendHttpRequest( + IWorkflowExpressionEvaluator expressionEvaluator, + IHttpClientFactory httpClientFactory, + IEnumerable contentFormatters) + { + this.expressionEvaluator = expressionEvaluator; + httpClient = httpClientFactory.CreateClient(nameof(SendHttpRequest)); + this.contentFormatters = contentFormatters; + } + + /// + /// The URL to invoke. + /// + [ActivityProperty(Hint = "The URL to send the HTTP request to.")] + public WorkflowExpression Url + { + get + { + var url = GetState>(); + + if (url != null && !string.IsNullOrWhiteSpace(url.Expression) && Uri.TryCreate( + url.Expression, + UriKind.RelativeOrAbsolute, + out var uri + )) + return new WorkflowExpression(url.Syntax, uri.ToString()); + + return new WorkflowExpression(LiteralEvaluator.SyntaxName, ""); + } + set => SetState(new WorkflowExpression(value.Syntax, value.Expression)); + } + + /// + /// The HTTP method to use. + /// + [ActivityProperty( + Type = ActivityPropertyTypes.Select, + Hint = "The HTTP method to use when making the request." + )] + [SelectOptions("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD")] + public string Method + { + get => GetState(() => "GET"); + set => SetState(value); + } + + /// + /// The body to send along with the request. + /// + [ActivityProperty(Hint = "The HTTP content to send along with the request.")] + [ExpressionOptions(Multiline = true)] + public WorkflowExpression Content + { + get => GetState(() => new WorkflowExpression(LiteralEvaluator.SyntaxName, "")); + set => SetState(value); + } + + /// + /// The Content Type header to send along with the request body. + /// + [ActivityProperty( + Type = ActivityPropertyTypes.Select, + Hint = "The content type to send with the request (if applicable)." + )] + [SelectOptions("text/plain", "text/html", "application/json", "application/xml")] + public WorkflowExpression ContentType + { + get => GetState(() => new WorkflowExpression(LiteralEvaluator.SyntaxName, "")); + set => SetState(value); + } + + [ActivityProperty( + Hint = "The Authorization header value to send." + )] + public WorkflowExpression Authorization + { + get => GetState>(); + set => SetState(value); + } + + /// + /// The headers to send along with the request. + /// + [ActivityProperty(Hint = "The headers to send along with the request. One 'header: value' pair per line.")] + public WorkflowExpression RequestHeaders + { + get => GetState(() => new WorkflowExpression(LiteralEvaluator.SyntaxName, "")); + set => SetState(value); + } + + [ActivityProperty(Hint = "Check to read the content of the response.")] + public bool ReadContent + { + get => GetState(() => true); + set => SetState(value); + } + + /// + /// A list of HTTP status codes this activity can handle. + /// + [ActivityProperty( + Type = ActivityPropertyTypes.List, + Hint = "A list of possible HTTP status codes to handle, comma-separated. Example: 200, 400, 404" + )] + public HashSet SupportedStatusCodes + { + get => GetState(() => new HashSet { 200 }); + set => SetState(value); + } + + + protected override async Task OnExecuteAsync( + WorkflowExecutionContext workflowContext, + CancellationToken cancellationToken) + { + var request = await CreateRequestAsync(workflowContext, cancellationToken); + var response = await httpClient.SendAsync(request, cancellationToken); + var hasContent = response.Content != null; + var contentType = response.Content?.Headers.ContentType.MediaType; + + var responseModel = new HttpResponseModel + { + StatusCode = response.StatusCode, + Headers = new Dictionary( + response.Headers.ToDictionary(x => x.Key, x => x.Value.ToArray()) + ) + }; + + if (hasContent && ReadContent) + { + var formatter = SelectContentFormatter(contentType); + + responseModel.Content = await response.Content.ReadAsByteArrayAsync(); + responseModel.ParsedContent = await formatter.ParseAsync(responseModel.Content, contentType); + } + + workflowContext.SetLastResult(responseModel); + Output["Response"] = responseModel; + var statusEndpoint = ((int)response.StatusCode).ToString(); + + return Outcomes(new[] { OutcomeNames.Done, statusEndpoint }); + } + + private IContentFormatter SelectContentFormatter(string contentType) + { + var formatters = contentFormatters.OrderByDescending(x => x.Priority).ToList(); + return formatters.FirstOrDefault( + x => x.SupportedContentTypes.Contains(contentType, StringComparer.OrdinalIgnoreCase) + ) ?? formatters.Last(); + } + + private async Task CreateRequestAsync( + WorkflowExecutionContext workflowContext, + CancellationToken cancellationToken) + { + var methodSupportsBody = GetMethodSupportsBody(Method); + var uri = await expressionEvaluator.EvaluateAsync(Url, workflowContext, cancellationToken); + var request = new HttpRequestMessage(new HttpMethod(Method), uri); + + var authorizationHeaderValue = await expressionEvaluator.EvaluateAsync( + Authorization, + workflowContext, + cancellationToken + ); + + var requestHeaders = await ParseRequestHeadersAsync(workflowContext, cancellationToken); + + if (methodSupportsBody) + { + var body = await expressionEvaluator.EvaluateAsync(Content, workflowContext, cancellationToken); + var contentType = await expressionEvaluator.EvaluateAsync( + ContentType, + workflowContext, + cancellationToken + ); + + if (!string.IsNullOrWhiteSpace(body)) + { + request.Content = new StringContent(body, Encoding.UTF8, contentType); + } + } + + if (!string.IsNullOrWhiteSpace(authorizationHeaderValue)) + { + request.Headers.Authorization = AuthenticationHeaderValue.Parse(authorizationHeaderValue); + } + + foreach (var header in requestHeaders) + { + request.Headers.Add(header.Key, header.Value.AsEnumerable()); + } + + return request; + } + + private async Task ParseRequestHeadersAsync( + WorkflowExecutionContext workflowContext, + CancellationToken cancellationToken) + { + var headersText = await expressionEvaluator.EvaluateAsync( + RequestHeaders, + workflowContext, + cancellationToken + ); + var headers = new HeaderDictionary(); + + if (headersText != null) + { + var headersQuery = + from line in Regex.Split(headersText, "\\n", RegexOptions.Multiline) + let pair = line.Split(':', '=') + select new KeyValuePair(pair[0], pair[1]); + + foreach (var header in headersQuery) + { + var headerValueExpression = new WorkflowExpression(RequestHeaders.Syntax, header.Value); + var headerValue = await expressionEvaluator.EvaluateAsync( + headerValueExpression, + workflowContext, + cancellationToken + ); + headers.Add(header.Key, headerValue); + } + } + + return headers; + } + + private bool GetMethodSupportsBody(string method) + { + var methods = new[] { "POST", "PUT", "PATCH" }; + return methods.Contains(method, StringComparer.InvariantCultureIgnoreCase); + } + } } \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Http/Activities/HttpResponseAction.cs b/src/activities/Elsa.Activities.Http/Activities/WriteHttpResponse.cs similarity index 89% rename from src/activities/Elsa.Activities.Http/Activities/HttpResponseAction.cs rename to src/activities/Elsa.Activities.Http/Activities/WriteHttpResponse.cs index 27344fedd..390c9e8ca 100644 --- a/src/activities/Elsa.Activities.Http/Activities/HttpResponseAction.cs +++ b/src/activities/Elsa.Activities.Http/Activities/WriteHttpResponse.cs @@ -1,153 +1,155 @@ -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using Elsa.Attributes; -using Elsa.Design; -using Elsa.Expressions; -using Elsa.Extensions; -using Elsa.Results; -using Elsa.Services; -using Elsa.Services.Models; -using Microsoft.AspNetCore.Http; - -namespace Elsa.Activities.Http.Activities -{ - [ActivityDefinition( - Category = "HTTP", - DisplayName = "Send HTTP Response", - Description = "Send an HTTP response.", - RuntimeDescription = "x => !!x.state.statusCode ? `Send an HTTP ${ x.state.statusCode } - ${ x.state.contentType } response` : x.definition.description", - Outcomes = new[] { OutcomeNames.Done } - )] - public class HttpResponseAction : Activity - { - private readonly IWorkflowExpressionEvaluator expressionEvaluator; - private readonly IHttpContextAccessor httpContextAccessor; - - public static IEnumerable GetStatusCodes() - { - return new[] - { - new SelectItem - { - Label = "2xx", - Options = new object[] { 200, 201, 202, 203, 204 } - }, - new SelectItem - { - Label = "3xx", - Options = new object[] { 301, 302, 304, 307, 308 } - }, - new SelectItem - { - Label = "4xx", - Options = new object[] { 400, 401, 402, 403, 404, 405, 409, 410, 412, 413, 415, 417, 418, 420, 428, 429 } - } - }; - } - - public HttpResponseAction(IWorkflowExpressionEvaluator expressionEvaluator, - IHttpContextAccessor httpContextAccessor) - { - this.expressionEvaluator = expressionEvaluator; - this.httpContextAccessor = httpContextAccessor; - } - - /// - /// The HTTP status code to return. - /// - [ActivityProperty( - Type = ActivityPropertyTypes.Select, - Hint = "The HTTP status code to write." - )] - [SelectOptions(nameof(GetStatusCodes), typeof(HttpResponseAction))] - public HttpStatusCode StatusCode - { - get => GetState(() => HttpStatusCode.OK); - set => SetState(value); - } - - /// - /// The content to send along with the response - /// - [ActivityProperty(Hint = "The HTTP content to write.")] - [ExpressionOptions(Multiline = true)] - public WorkflowExpression Content - { - get => GetState(() => new WorkflowExpression(LiteralEvaluator.SyntaxName, "")); - set => SetState(value); - } - - /// - /// The Content-Type header to send along with the response. - /// - [ActivityProperty( - Type = ActivityPropertyTypes.Select, - Hint = "The HTTP content type header to write." - )] - [SelectOptions("text/plain", "text/html", "application/json", "application/xml")] - public string ContentType - { - get => GetState(); - set => SetState(value); - } - - /// - /// The headers to send along with the response. One 'header: value' pair per line. - /// - [ActivityProperty(Hint = "The headers to send along with the response. One 'header: value' pair per line.")] - public WorkflowExpression ResponseHeaders - { - get => GetState(() => new WorkflowExpression(LiteralEvaluator.SyntaxName, "")); - set => SetState(value); - } - - protected override async Task OnExecuteAsync(WorkflowExecutionContext workflowContext, - CancellationToken cancellationToken) - { - var response = httpContextAccessor.HttpContext.Response; - - if (response.HasStarted) - return Fault("Response has already started"); - - response.StatusCode = (int) StatusCode; - response.ContentType = ContentType; - - var headersText = await expressionEvaluator.EvaluateAsync( - ResponseHeaders, - workflowContext, - cancellationToken - ); - - if (headersText != null) - { - var headersQuery = - from line in Regex.Split(headersText, "\\n", RegexOptions.Multiline) - let pair = line.Split(':', '=') - select new KeyValuePair(pair[0], pair[1]); - - foreach (var header in headersQuery) - { - var headerValueExpression = new WorkflowExpression(ResponseHeaders.Syntax, header.Value); - response.Headers[header.Key] = await expressionEvaluator.EvaluateAsync( - headerValueExpression, - workflowContext, - cancellationToken - ); - } - } - - var bodyText = await expressionEvaluator.EvaluateAsync(Content, workflowContext, cancellationToken); - - if (!string.IsNullOrWhiteSpace(bodyText)) - { - await response.WriteAsync(bodyText, cancellationToken); - } - - return Done(); - } - } +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Elsa.Attributes; +using Elsa.Design; +using Elsa.Expressions; +using Elsa.Extensions; +using Elsa.Results; +using Elsa.Services; +using Elsa.Services.Models; +using Microsoft.AspNetCore.Http; + +namespace Elsa.Activities.Http.Activities +{ + [ActivityDefinition( + Category = "HTTP", + DisplayName = "Write HTTP Response", + Description = "Write an HTTP response.", + RuntimeDescription = "x => !!x.state.statusCode ? `Send an HTTP ${ x.state.statusCode } - ${ x.state.contentType } response` : x.definition.description", + Outcomes = new[] { OutcomeNames.Done } + )] + public class WriteHttpResponse : Activity + { + private readonly IWorkflowExpressionEvaluator expressionEvaluator; + private readonly IHttpContextAccessor httpContextAccessor; + + public static IEnumerable GetStatusCodes() + { + return new[] + { + new SelectItem + { + Label = "2xx", + Options = new object[] { 200, 201, 202, 203, 204 } + }, + new SelectItem + { + Label = "3xx", + Options = new object[] { 301, 302, 304, 307, 308 } + }, + new SelectItem + { + Label = "4xx", + Options = new object[] { 400, 401, 402, 403, 404, 405, 409, 410, 412, 413, 415, 417, 418, 420, 428, 429 } + } + }; + } + + public WriteHttpResponse( + IWorkflowExpressionEvaluator expressionEvaluator, + IHttpContextAccessor httpContextAccessor) + { + this.expressionEvaluator = expressionEvaluator; + this.httpContextAccessor = httpContextAccessor; + } + + /// + /// The HTTP status code to return. + /// + [ActivityProperty( + Type = ActivityPropertyTypes.Select, + Hint = "The HTTP status code to write." + )] + [SelectOptions(nameof(GetStatusCodes), typeof(WriteHttpResponse))] + public HttpStatusCode StatusCode + { + get => GetState(() => HttpStatusCode.OK); + set => SetState(value); + } + + /// + /// The content to send along with the response + /// + [ActivityProperty(Hint = "The HTTP content to write.")] + [ExpressionOptions(Multiline = true)] + public WorkflowExpression Content + { + get => GetState(() => new WorkflowExpression(LiteralEvaluator.SyntaxName, "")); + set => SetState(value); + } + + /// + /// The Content-Type header to send along with the response. + /// + [ActivityProperty( + Type = ActivityPropertyTypes.Select, + Hint = "The HTTP content type header to write." + )] + [SelectOptions("text/plain", "text/html", "application/json", "application/xml")] + public string ContentType + { + get => GetState(); + set => SetState(value); + } + + /// + /// The headers to send along with the response. One 'header: value' pair per line. + /// + [ActivityProperty(Hint = "The headers to send along with the response. One 'header: value' pair per line.")] + public WorkflowExpression ResponseHeaders + { + get => GetState(() => new WorkflowExpression(LiteralEvaluator.SyntaxName, "")); + set => SetState(value); + } + + protected override async Task OnExecuteAsync( + WorkflowExecutionContext workflowContext, + CancellationToken cancellationToken) + { + var response = httpContextAccessor.HttpContext.Response; + + if (response.HasStarted) + return Fault("Response has already started"); + + response.StatusCode = (int)StatusCode; + response.ContentType = ContentType; + + var headersText = await expressionEvaluator.EvaluateAsync( + ResponseHeaders, + workflowContext, + cancellationToken + ); + + if (headersText != null) + { + var headersQuery = + from line in Regex.Split(headersText, "\\n", RegexOptions.Multiline) + let pair = line.Split(':', '=') + select new KeyValuePair(pair[0], pair[1]); + + foreach (var header in headersQuery) + { + var headerValueExpression = new WorkflowExpression(ResponseHeaders.Syntax, header.Value); + response.Headers[header.Key] = await expressionEvaluator.EvaluateAsync( + headerValueExpression, + workflowContext, + cancellationToken + ); + } + } + + var bodyText = await expressionEvaluator.EvaluateAsync(Content, workflowContext, cancellationToken); + + if (!string.IsNullOrWhiteSpace(bodyText)) + { + await response.WriteAsync(bodyText, cancellationToken); + } + + return Done(); + } + } } \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Http/Controllers/HttpWorkflowsController.cs b/src/activities/Elsa.Activities.Http/Controllers/HttpWorkflowsController.cs index a9812178f..6f534245f 100644 --- a/src/activities/Elsa.Activities.Http/Controllers/HttpWorkflowsController.cs +++ b/src/activities/Elsa.Activities.Http/Controllers/HttpWorkflowsController.cs @@ -19,14 +19,14 @@ namespace Elsa.Activities.Http.Controllers public HttpWorkflowsController( ITokenService tokenService, - IWorkflowInvoker workflowInvoker, + IWorkflowInvoker workflowInvoker, IWorkflowInstanceStore workflowInstanceStore) { this.tokenService = tokenService; this.workflowInvoker = workflowInvoker; this.workflowInstanceStore = workflowInstanceStore; } - + [Route("trigger/{token}")] [HttpGet, HttpPost] public async Task Trigger(string token, CancellationToken cancellationToken) @@ -37,8 +37,8 @@ namespace Elsa.Activities.Http.Controllers var workflowInstance = await workflowInstanceStore.GetByIdAsync(signal.WorkflowInstanceId, cancellationToken); if (workflowInstance == null) - return NotFound(); - + return NotFound(); + var input = new Variables { ["signal"] = signal.Name @@ -46,8 +46,8 @@ namespace Elsa.Activities.Http.Controllers await workflowInvoker.ResumeAsync(workflowInstance, input, cancellationToken: cancellationToken); - return HttpContext.Items.ContainsKey(WorkflowHttpResult.Instance) - ? (IActionResult) new EmptyResult() + return HttpContext.Items.ContainsKey(WorkflowHttpResult.Instance) + ? (IActionResult)new EmptyResult() : Accepted(); } } diff --git a/src/activities/Elsa.Activities.Http/Elsa.Activities.Http.csproj b/src/activities/Elsa.Activities.Http/Elsa.Activities.Http.csproj index dcc0ca91d..87fa2d920 100644 --- a/src/activities/Elsa.Activities.Http/Elsa.Activities.Http.csproj +++ b/src/activities/Elsa.Activities.Http/Elsa.Activities.Http.csproj @@ -4,13 +4,20 @@ netstandard2.0 1.0.0 latest - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides the following Console activities: + + * ReceiveHttpRequest + * SendHttpRequest + * WriteHttpResponse + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core GitHub - elsa, workflows, orchard + elsa, workflows, http @@ -28,4 +35,4 @@ - + \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Http/Extensions/ApplicationBuilderExtensions.cs b/src/activities/Elsa.Activities.Http/Extensions/ApplicationBuilderExtensions.cs index 722f00e59..a4db45ced 100644 --- a/src/activities/Elsa.Activities.Http/Extensions/ApplicationBuilderExtensions.cs +++ b/src/activities/Elsa.Activities.Http/Extensions/ApplicationBuilderExtensions.cs @@ -13,12 +13,12 @@ namespace Elsa.Activities.Http.Extensions .UseRequestHandler() .UseRequestHandler("/workflows/signal"); } - + public static IApplicationBuilder UseRequestHandler(this IApplicationBuilder app) where THandler : IRequestHandler { return app.UseMiddleware>(); } - + public static IApplicationBuilder UseRequestHandler(this IApplicationBuilder app, string path) where THandler : IRequestHandler { return app diff --git a/src/activities/Elsa.Activities.Http/Extensions/HttpActivitiesServiceCollectionExtensions.cs b/src/activities/Elsa.Activities.Http/Extensions/HttpActivitiesServiceCollectionExtensions.cs index f3fbc1532..09d55e2ce 100644 --- a/src/activities/Elsa.Activities.Http/Extensions/HttpActivitiesServiceCollectionExtensions.cs +++ b/src/activities/Elsa.Activities.Http/Extensions/HttpActivitiesServiceCollectionExtensions.cs @@ -24,12 +24,12 @@ namespace Elsa.Activities.Http.Extensions options?.Invoke(services.AddOptions()); services.TryAddSingleton(); - services.AddHttpClient(nameof(HttpRequestAction)); + services.AddHttpClient(nameof(SendHttpRequest)); services - .AddActivity() - .AddActivity() - .AddActivity(); + .AddActivity() + .AddActivity() + .AddActivity(); services .AddSingleton() diff --git a/src/activities/Elsa.Activities.Http/Extensions/StreamExtensions.cs b/src/activities/Elsa.Activities.Http/Extensions/StreamExtensions.cs index bc14175d3..bfd0bb323 100644 --- a/src/activities/Elsa.Activities.Http/Extensions/StreamExtensions.cs +++ b/src/activities/Elsa.Activities.Http/Extensions/StreamExtensions.cs @@ -10,7 +10,7 @@ namespace Elsa.Activities.Http.Extensions { using (var ms = new MemoryStream()) { - await input.CopyToAsync(ms, 16*1024, cancellationToken); + await input.CopyToAsync(ms, 16 * 1024, cancellationToken); return ms.ToArray(); } } diff --git a/src/activities/Elsa.Activities.Http/Handlers/HttpJavaScriptHandler.cs b/src/activities/Elsa.Activities.Http/Handlers/HttpJavaScriptHandler.cs index 35febcda3..05edb7631 100644 --- a/src/activities/Elsa.Activities.Http/Handlers/HttpJavaScriptHandler.cs +++ b/src/activities/Elsa.Activities.Http/Handlers/HttpJavaScriptHandler.cs @@ -25,25 +25,25 @@ namespace Elsa.Activities.Http.Handlers this.absoluteUrlProvider = absoluteUrlProvider; this.httpContextAccessor = httpContextAccessor; } - + public Task Handle(EvaluatingJavaScriptExpression notification, CancellationToken cancellationToken) { var engine = notification.Engine; var workflowExecutionContext = notification.WorkflowExecutionContext; - + engine.SetValue( "queryString", - (Func) (key => httpContextAccessor.HttpContext.Request.Query[key].ToString()) + (Func)(key => httpContextAccessor.HttpContext.Request.Query[key].ToString()) ); engine.SetValue( "absoluteUrl", - (Func) (url => absoluteUrlProvider.ToAbsoluteUrl(url).ToString()) + (Func)(url => absoluteUrlProvider.ToAbsoluteUrl(url).ToString()) ); engine.SetValue( "signalUrl", - (Func) (signal => GenerateUrl(signal, workflowExecutionContext)) + (Func)(signal => GenerateUrl(signal, workflowExecutionContext)) ); - + return Task.CompletedTask; } diff --git a/src/activities/Elsa.Activities.Http/Handlers/HttpLiquidHandler.cs b/src/activities/Elsa.Activities.Http/Handlers/HttpLiquidHandler.cs index d8c146dc4..0814bab63 100644 --- a/src/activities/Elsa.Activities.Http/Handlers/HttpLiquidHandler.cs +++ b/src/activities/Elsa.Activities.Http/Handlers/HttpLiquidHandler.cs @@ -14,7 +14,7 @@ namespace Elsa.Activities.Http.Handlers var context = notification.TemplateContext; context.MemberAccessStrategy.Register(); - + return Task.CompletedTask; } } diff --git a/src/activities/Elsa.Activities.Http/Middleware/RequestHandlerMiddleware.cs b/src/activities/Elsa.Activities.Http/Middleware/RequestHandlerMiddleware.cs index 396f31595..871c825ca 100644 --- a/src/activities/Elsa.Activities.Http/Middleware/RequestHandlerMiddleware.cs +++ b/src/activities/Elsa.Activities.Http/Middleware/RequestHandlerMiddleware.cs @@ -12,12 +12,12 @@ namespace Elsa.Activities.Http.Middleware { this.next = next; } - + public async Task InvokeAsync(HttpContext httpContext, THandler handler) { var result = await handler.HandleRequestAsync(); - if(result != null && !httpContext.Response.HasStarted) + if (result != null && !httpContext.Response.HasStarted) await result.ExecuteResultAsync(httpContext, next); } } diff --git a/src/activities/Elsa.Activities.Http/RequestHandlers/Handlers/SignalRequestHandler.cs b/src/activities/Elsa.Activities.Http/RequestHandlers/Handlers/SignalRequestHandler.cs index f9bd9ad3b..b564a79af 100644 --- a/src/activities/Elsa.Activities.Http/RequestHandlers/Handlers/SignalRequestHandler.cs +++ b/src/activities/Elsa.Activities.Http/RequestHandlers/Handlers/SignalRequestHandler.cs @@ -103,7 +103,7 @@ namespace Elsa.Activities.Http.RequestHandlers.Handlers workflowInstance.DefinitionId, VersionOptions.SpecificVersion(workflowInstance.Version), cancellationToken); - + var workflow = workflowFactory.CreateWorkflow(workflowDefinition, input, workflowInstance); var blockingSignalActivities = workflow.BlockingActivities.ToList(); await workflowInvoker.ResumeAsync(workflow, blockingSignalActivities, cancellationToken); diff --git a/src/activities/Elsa.Activities.Http/RequestHandlers/Handlers/TriggerRequestHandler.cs b/src/activities/Elsa.Activities.Http/RequestHandlers/Handlers/TriggerRequestHandler.cs index 2f904085b..d11baeb50 100644 --- a/src/activities/Elsa.Activities.Http/RequestHandlers/Handlers/TriggerRequestHandler.cs +++ b/src/activities/Elsa.Activities.Http/RequestHandlers/Handlers/TriggerRequestHandler.cs @@ -41,11 +41,11 @@ namespace Elsa.Activities.Http.RequestHandlers.Handlers // TODO: Optimize this by building up a hash of routes and workflows to execute. var requestPath = new Uri(httpContext.Request.Path.ToString(), UriKind.Relative); var method = httpContext.Request.Method; - var httpWorkflows = await registry.ListByStartActivityAsync(nameof(HttpRequestEvent), cancellationToken); + var httpWorkflows = await registry.ListByStartActivityAsync(nameof(ReceiveHttpRequest), cancellationToken); var workflowsToStart = Filter(httpWorkflows, requestPath, method).ToList(); - var haltedHttpWorkflows = await workflowInstanceStore.ListByBlockingActivityAsync( + var haltedHttpWorkflows = await workflowInstanceStore.ListByBlockingActivityAsync( cancellationToken: cancellationToken); - + var workflowsToResume = Filter(haltedHttpWorkflows, requestPath, method).ToList(); if (!workflowsToStart.Any() && !workflowsToResume.Any()) @@ -77,8 +77,8 @@ namespace Elsa.Activities.Http.RequestHandlers.Handlers private bool IsMatch(JObject state, Uri path, string method) { - var m = HttpRequestEvent.GetMethod(state); - var p = HttpRequestEvent.GetPath(state); + var m = ReceiveHttpRequest.GetMethod(state); + var p = ReceiveHttpRequest.GetPath(state); return (string.IsNullOrWhiteSpace(m) || m == method) && p == path; } diff --git a/src/activities/Elsa.Activities.Http/RequestHandlers/Results/AcceptedResult.cs b/src/activities/Elsa.Activities.Http/RequestHandlers/Results/AcceptedResult.cs index bd3214568..98b04fefe 100644 --- a/src/activities/Elsa.Activities.Http/RequestHandlers/Results/AcceptedResult.cs +++ b/src/activities/Elsa.Activities.Http/RequestHandlers/Results/AcceptedResult.cs @@ -9,7 +9,7 @@ namespace Elsa.Activities.Http.RequestHandlers.Results { public Task ExecuteResultAsync(HttpContext httpContext, RequestDelegate next) { - httpContext.Response.StatusCode = (int) HttpStatusCode.Accepted; + httpContext.Response.StatusCode = (int)HttpStatusCode.Accepted; return Task.CompletedTask; } } diff --git a/src/activities/Elsa.Activities.Http/RequestHandlers/Results/BadRequestResult.cs b/src/activities/Elsa.Activities.Http/RequestHandlers/Results/BadRequestResult.cs index 93d89e362..2f7f433a8 100644 --- a/src/activities/Elsa.Activities.Http/RequestHandlers/Results/BadRequestResult.cs +++ b/src/activities/Elsa.Activities.Http/RequestHandlers/Results/BadRequestResult.cs @@ -9,7 +9,7 @@ namespace Elsa.Activities.Http.RequestHandlers.Results { public Task ExecuteResultAsync(HttpContext httpContext, RequestDelegate next) { - httpContext.Response.StatusCode = (int) HttpStatusCode.BadRequest; + httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; return Task.CompletedTask; } } diff --git a/src/activities/Elsa.Activities.Http/RequestHandlers/Results/NotFoundResult.cs b/src/activities/Elsa.Activities.Http/RequestHandlers/Results/NotFoundResult.cs index 3340ff752..81d6a2a0c 100644 --- a/src/activities/Elsa.Activities.Http/RequestHandlers/Results/NotFoundResult.cs +++ b/src/activities/Elsa.Activities.Http/RequestHandlers/Results/NotFoundResult.cs @@ -9,7 +9,7 @@ namespace Elsa.Activities.Http.RequestHandlers.Results { public Task ExecuteResultAsync(HttpContext httpContext, RequestDelegate next) { - httpContext.Response.StatusCode = (int) HttpStatusCode.NotFound; + httpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; return Task.CompletedTask; } } diff --git a/src/activities/Elsa.Activities.Http/Services/DefaultAbsoluteUrlProvider.cs b/src/activities/Elsa.Activities.Http/Services/DefaultAbsoluteUrlProvider.cs index 94f75842a..37c43c05b 100644 --- a/src/activities/Elsa.Activities.Http/Services/DefaultAbsoluteUrlProvider.cs +++ b/src/activities/Elsa.Activities.Http/Services/DefaultAbsoluteUrlProvider.cs @@ -11,7 +11,8 @@ namespace Elsa.Activities.Http.Services private readonly IHttpContextAccessor httpContextAccessor; private readonly IOptions options; - public DefaultAbsoluteUrlProvider(IHttpContextAccessor httpContextAccessor, + public DefaultAbsoluteUrlProvider( + IHttpContextAccessor httpContextAccessor, IOptions options) { this.httpContextAccessor = httpContextAccessor; diff --git a/src/activities/Elsa.Activities.Http/Services/TokenService.cs b/src/activities/Elsa.Activities.Http/Services/TokenService.cs index 0d7e201b8..bf26f4351 100644 --- a/src/activities/Elsa.Activities.Http/Services/TokenService.cs +++ b/src/activities/Elsa.Activities.Http/Services/TokenService.cs @@ -11,7 +11,7 @@ namespace Elsa.Activities.Http.Services { dataProtector = dataProtectionProvider.CreateProtector("HTTP Workflow Tokens"); } - + public string CreateToken(T payload) { var json = JsonConvert.SerializeObject(payload); @@ -36,7 +36,6 @@ namespace Elsa.Activities.Http.Services } return false; - } } } \ No newline at end of file diff --git a/src/activities/Elsa.Activities.MassTransit/Elsa.Activities.MassTransit.csproj b/src/activities/Elsa.Activities.MassTransit/Elsa.Activities.MassTransit.csproj index 8665b7334..1cda350dc 100644 --- a/src/activities/Elsa.Activities.MassTransit/Elsa.Activities.MassTransit.csproj +++ b/src/activities/Elsa.Activities.MassTransit/Elsa.Activities.MassTransit.csproj @@ -4,13 +4,19 @@ netstandard2.0 1.0.0 latest - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides the following MassTransit activities: + + * ReceiveMassTransitMessage + * SendMassTransitMessage + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core GitHub - elsa, workflows, orchard + elsa, workflows diff --git a/src/activities/Elsa.Activities.Timers/Elsa.Activities.Timers.csproj b/src/activities/Elsa.Activities.Timers/Elsa.Activities.Timers.csproj index d1efe8ee6..77a47744a 100644 --- a/src/activities/Elsa.Activities.Timers/Elsa.Activities.Timers.csproj +++ b/src/activities/Elsa.Activities.Timers/Elsa.Activities.Timers.csproj @@ -4,13 +4,20 @@ netstandard2.0 1.0.0 latest - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides the following Timer activities: + + * CronEvent + * InstantEvent + * TimerEvent + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core GitHub - elsa, workflows, orchard + elsa, workflows, timers, background tasks diff --git a/src/activities/Elsa.Activities.UserTask/Elsa.Activities.UserTask.csproj b/src/activities/Elsa.Activities.UserTask/Elsa.Activities.UserTask.csproj index 481f8e48b..551e30c78 100644 --- a/src/activities/Elsa.Activities.UserTask/Elsa.Activities.UserTask.csproj +++ b/src/activities/Elsa.Activities.UserTask/Elsa.Activities.UserTask.csproj @@ -4,13 +4,18 @@ netstandard2.0 1.0.0 latest - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides the following User Task activities: + + * UserTask + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core GitHub - elsa, workflows, orchard + elsa, workflows diff --git a/src/activities/Elsa.Activities.Workflows/Activities/Trigger.cs b/src/activities/Elsa.Activities.Workflows/Activities/TriggerSignal.cs similarity index 94% rename from src/activities/Elsa.Activities.Workflows/Activities/Trigger.cs rename to src/activities/Elsa.Activities.Workflows/Activities/TriggerSignal.cs index 469fbd632..cb08491e2 100644 --- a/src/activities/Elsa.Activities.Workflows/Activities/Trigger.cs +++ b/src/activities/Elsa.Activities.Workflows/Activities/TriggerSignal.cs @@ -20,12 +20,12 @@ namespace Elsa.Activities.Workflows.Activities Description = "Trigger the specified signal.", Icon = "fas fa-broadcast-tower" )] - public class Trigger : Activity + public class TriggerSignal : Activity { private readonly IWorkflowExpressionEvaluator expressionEvaluator; private readonly IWorkflowInvoker workflowInvoker; - public Trigger(IWorkflowExpressionEvaluator expressionEvaluator, IWorkflowInvoker workflowInvoker) + public TriggerSignal(IWorkflowExpressionEvaluator expressionEvaluator, IWorkflowInvoker workflowInvoker) { this.expressionEvaluator = expressionEvaluator; this.workflowInvoker = workflowInvoker; diff --git a/src/activities/Elsa.Activities.Workflows/Elsa.Activities.Workflows.csproj b/src/activities/Elsa.Activities.Workflows/Elsa.Activities.Workflows.csproj index acced5f61..8fb6e1442 100644 --- a/src/activities/Elsa.Activities.Workflows/Elsa.Activities.Workflows.csproj +++ b/src/activities/Elsa.Activities.Workflows/Elsa.Activities.Workflows.csproj @@ -2,11 +2,30 @@ netstandard2.0 + 1.0.0 + latest + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides the following Workflow activities: + + * Correlate + * Finish + * Signaled + * Start + * TriggerSignal + * TriggerWorkflow + + 2019 + https://github.com/elsa-workflows/elsa-core + https://github.com/elsa-workflows/elsa-core + GitHub + elsa, workflows - - + + diff --git a/src/activities/Elsa.Activities.Workflows/Extensions/WorkflowActivityServiceCollectionExtensions.cs b/src/activities/Elsa.Activities.Workflows/Extensions/WorkflowActivityServiceCollectionExtensions.cs index 55c36a0cb..898cbd275 100644 --- a/src/activities/Elsa.Activities.Workflows/Extensions/WorkflowActivityServiceCollectionExtensions.cs +++ b/src/activities/Elsa.Activities.Workflows/Extensions/WorkflowActivityServiceCollectionExtensions.cs @@ -11,7 +11,7 @@ namespace Elsa.Activities.Workflows.Extensions .AddActivity() .AddActivity() .AddActivity() - .AddActivity() + .AddActivity() .AddActivity() .AddActivity(); } diff --git a/src/core/Elsa.Abstractions/Elsa.Abstractions.csproj b/src/core/Elsa.Abstractions/Elsa.Abstractions.csproj index b0e4937b7..c890e362a 100644 --- a/src/core/Elsa.Abstractions/Elsa.Abstractions.csproj +++ b/src/core/Elsa.Abstractions/Elsa.Abstractions.csproj @@ -5,8 +5,11 @@ Elsa latest 1.0.0 - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides abstractions and models that are used by Elsa.Core and other related packages. You don't need to reference this package separately if you reference any other Elsa package. + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core diff --git a/src/core/Elsa.Core/Elsa.Core.csproj b/src/core/Elsa.Core/Elsa.Core.csproj index 4779a0fbf..ee01e6d7b 100644 --- a/src/core/Elsa.Core/Elsa.Core.csproj +++ b/src/core/Elsa.Core/Elsa.Core.csproj @@ -5,8 +5,12 @@ 8 Elsa 1.0.0 - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package contains the heart and soul of what makes Elsa tick. It implements most of the abstractions defined in Elsa.Abstractions. + If you reference the Elsa package, which is recommended, you don;t have to explicitly reference this package. + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core diff --git a/src/core/Elsa/Elsa.csproj b/src/core/Elsa/Elsa.csproj index 0a5f30dc1..5b766ab99 100644 --- a/src/core/Elsa/Elsa.csproj +++ b/src/core/Elsa/Elsa.csproj @@ -4,8 +4,11 @@ netstandard2.0 latest 1.0.0 - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package references some of the most commonly used packages you are likely to use when working with Elsa. + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core diff --git a/src/dashboard/Elsa.Dashboard/Elsa.Dashboard.csproj b/src/dashboard/Elsa.Dashboard/Elsa.Dashboard.csproj index da6587839..bd0ac0716 100644 --- a/src/dashboard/Elsa.Dashboard/Elsa.Dashboard.csproj +++ b/src/dashboard/Elsa.Dashboard/Elsa.Dashboard.csproj @@ -6,8 +6,11 @@ 8 true 1.0.0 - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides the Elsa Dashboard in the form of an MVC Area that you can use in your own ASP.NET Core MVC application. + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core diff --git a/src/dashboard/Elsa.WorkflowDesigner/Elsa.WorkflowDesigner.csproj b/src/dashboard/Elsa.WorkflowDesigner/Elsa.WorkflowDesigner.csproj index 128f8a015..16b193cca 100644 --- a/src/dashboard/Elsa.WorkflowDesigner/Elsa.WorkflowDesigner.csproj +++ b/src/dashboard/Elsa.WorkflowDesigner/Elsa.WorkflowDesigner.csproj @@ -5,8 +5,11 @@ 8.0 enable 1.0.0 - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides a reusable WorkflowDesigner View Component. It is used by Elsa.Dashboard to display the workflow designer. + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core diff --git a/src/persistence/Elsa.Persistence.DocumentDb/Elsa.Persistence.DocumentDb.csproj b/src/persistence/Elsa.Persistence.DocumentDb/Elsa.Persistence.DocumentDb.csproj index 876921f1f..71b2ef670 100644 --- a/src/persistence/Elsa.Persistence.DocumentDb/Elsa.Persistence.DocumentDb.csproj +++ b/src/persistence/Elsa.Persistence.DocumentDb/Elsa.Persistence.DocumentDb.csproj @@ -1,18 +1,28 @@  - - netstandard2.0 - netcoreapp2.2 - latest - 1.0.0 - + + netstandard2.0 + 8.0 + enable + 1.0.0 + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides a CosmosDb persistence provider. + + 2019 + https://github.com/elsa-workflows/elsa-core + https://github.com/elsa-workflows/elsa-core + GitHub + elsa, workflows, cosmosdb + - - - + + + - - - + + + diff --git a/src/persistence/Elsa.Persistence.EntityFrameworkCore/Elsa.Persistence.EntityFrameworkCore.csproj b/src/persistence/Elsa.Persistence.EntityFrameworkCore/Elsa.Persistence.EntityFrameworkCore.csproj index a5999c0dd..a8b17a6c3 100644 --- a/src/persistence/Elsa.Persistence.EntityFrameworkCore/Elsa.Persistence.EntityFrameworkCore.csproj +++ b/src/persistence/Elsa.Persistence.EntityFrameworkCore/Elsa.Persistence.EntityFrameworkCore.csproj @@ -5,13 +5,16 @@ netcoreapp3.0 latest 1.0.0 - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides an Entity Framework Core persistence provider. + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core GitHub - elsa, workflows + elsa, workflows, entity framework core diff --git a/src/persistence/Elsa.Persistence.MongoDb/Elsa.Persistence.MongoDb.csproj b/src/persistence/Elsa.Persistence.MongoDb/Elsa.Persistence.MongoDb.csproj index 619892b70..20083a750 100644 --- a/src/persistence/Elsa.Persistence.MongoDb/Elsa.Persistence.MongoDb.csproj +++ b/src/persistence/Elsa.Persistence.MongoDb/Elsa.Persistence.MongoDb.csproj @@ -4,13 +4,16 @@ netstandard2.0 latest 1.0.0 - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides a MongoDB persistence provider. + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core GitHub - elsa, workflows + elsa, workflows, mongodb diff --git a/src/persistence/Elsa.Persistence.YesSql/Elsa.Persistence.YesSql.csproj b/src/persistence/Elsa.Persistence.YesSql/Elsa.Persistence.YesSql.csproj index 4207316a4..72e38466f 100644 --- a/src/persistence/Elsa.Persistence.YesSql/Elsa.Persistence.YesSql.csproj +++ b/src/persistence/Elsa.Persistence.YesSql/Elsa.Persistence.YesSql.csproj @@ -4,13 +4,16 @@ netstandard2.0 latest 1.0.0 - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides a YesSQL persistence provider. + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core GitHub - elsa, workflows + elsa, workflows, yessql diff --git a/src/samples/Sample06/HelloWorldWorkflow.cs b/src/samples/Sample06/HelloWorldWorkflow.cs index 1774be224..920dcdc78 100644 --- a/src/samples/Sample06/HelloWorldWorkflow.cs +++ b/src/samples/Sample06/HelloWorldWorkflow.cs @@ -12,10 +12,10 @@ namespace Sample06 public void Build(IWorkflowBuilder builder) { builder - .StartWith( + .StartWith( activity => activity.Path = new Uri("/hello-world", UriKind.Relative) ) - .Then( + .Then( activity => { activity.Content = new LiteralExpression("

Hello World!

Elsa says hi :)

"); diff --git a/src/samples/Sample07/DocumentApprovalWorkflow.cs b/src/samples/Sample07/DocumentApprovalWorkflow.cs index 3d00ca300..3ec97ef90 100644 --- a/src/samples/Sample07/DocumentApprovalWorkflow.cs +++ b/src/samples/Sample07/DocumentApprovalWorkflow.cs @@ -22,7 +22,7 @@ namespace Sample07 public void Build(IWorkflowBuilder builder) { builder - .StartWith( + .StartWith( x => { x.Method = HttpMethod.Post.Method; @@ -50,7 +50,7 @@ namespace Sample07 ); } ) - .Then( + .Then( x => { x.Content = new LiteralExpression( diff --git a/src/samples/Sample08/Workflows/CreateOrderWorkflow.cs b/src/samples/Sample08/Workflows/CreateOrderWorkflow.cs index 72f0a4317..db9a282a4 100644 --- a/src/samples/Sample08/Workflows/CreateOrderWorkflow.cs +++ b/src/samples/Sample08/Workflows/CreateOrderWorkflow.cs @@ -20,7 +20,7 @@ namespace Sample08.Workflows public void Build(IWorkflowBuilder builder) { builder - .StartWith( + .StartWith( activity => { activity.Method = HttpMethod.Post.Method; @@ -47,7 +47,7 @@ namespace Sample08.Workflows { fork .When("Write-Response") - .Then( + .Then( activity => { activity.Content = new LiteralExpression("

Order Received

Your order has been received. Waiting for shipment.

"); diff --git a/src/scripting/Elsa.Scripting.JavaScript/Elsa.Scripting.JavaScript.csproj b/src/scripting/Elsa.Scripting.JavaScript/Elsa.Scripting.JavaScript.csproj index 7fa86a9f5..0e67ea081 100644 --- a/src/scripting/Elsa.Scripting.JavaScript/Elsa.Scripting.JavaScript.csproj +++ b/src/scripting/Elsa.Scripting.JavaScript/Elsa.Scripting.JavaScript.csproj @@ -4,13 +4,16 @@ netstandard2.0 latest 1.0.0 - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides a JavaScript expression evaluator based on Jint. + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core GitHub - elsa, workflows + elsa, workflows, javascript, jint diff --git a/src/scripting/Elsa.Scripting.Liquid/Elsa.Scripting.Liquid.csproj b/src/scripting/Elsa.Scripting.Liquid/Elsa.Scripting.Liquid.csproj index 9d76047f9..a553b96e1 100644 --- a/src/scripting/Elsa.Scripting.Liquid/Elsa.Scripting.Liquid.csproj +++ b/src/scripting/Elsa.Scripting.Liquid/Elsa.Scripting.Liquid.csproj @@ -4,13 +4,16 @@ netstandard2.0 latest 1.0.0 - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides a Liquid expression evaluator based on Fluid. + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core GitHub - elsa, workflows + elsa, workflows, liquid, fluid diff --git a/src/utils/Elsa.AutoMapper.Extensions/Elsa.AutoMapper.Extensions.csproj b/src/utils/Elsa.AutoMapper.Extensions/Elsa.AutoMapper.Extensions.csproj index b5256fec1..8abbbc856 100644 --- a/src/utils/Elsa.AutoMapper.Extensions/Elsa.AutoMapper.Extensions.csproj +++ b/src/utils/Elsa.AutoMapper.Extensions/Elsa.AutoMapper.Extensions.csproj @@ -4,8 +4,11 @@ netstandard2.0 latest 1.0.0 - Sipke Schoorstra - Elsa is a set of workflowing libraries and tools to enable super-fast workflowing capabilities in any .NET Core application. + Elsa Contributors + + Elsa is a set of workflow libraries and tools that enable super-fast workflowing capabilities in any .NET Core application. + This package provides extension methods that simplify registration of AutoMapper and profiles. + 2019 https://github.com/elsa-workflows/elsa-core https://github.com/elsa-workflows/elsa-core