diff --git a/src/activities/Elsa.Activities.Http/Activities/HttpEndpoint/HttpEndpoint.cs b/src/activities/Elsa.Activities.Http/Activities/HttpEndpoint/HttpEndpoint.cs index ca17fd961..41d46eb9d 100644 --- a/src/activities/Elsa.Activities.Http/Activities/HttpEndpoint/HttpEndpoint.cs +++ b/src/activities/Elsa.Activities.Http/Activities/HttpEndpoint/HttpEndpoint.cs @@ -70,8 +70,8 @@ namespace Elsa.Activities.Http 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)), + QueryString = request.Query.ToDictionary(x => x.Key, x => x.Value.ToString()), + Headers = request.Headers.ToDictionary(x => x.Key, x => x.Value.ToString()), Method = request.Method }; diff --git a/src/activities/Elsa.Activities.Http/Activities/SendHttpRequest/SendHttpRequest.cs b/src/activities/Elsa.Activities.Http/Activities/SendHttpRequest/SendHttpRequest.cs index e7054c7a5..79e4497fb 100644 --- a/src/activities/Elsa.Activities.Http/Activities/SendHttpRequest/SendHttpRequest.cs +++ b/src/activities/Elsa.Activities.Http/Activities/SendHttpRequest/SendHttpRequest.cs @@ -13,6 +13,7 @@ using Elsa.Design; using Elsa.Services; using Elsa.Services.Models; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; using HttpRequestHeaders = Elsa.Activities.Http.Models.HttpRequestHeaders; // ReSharper disable once CheckNamespace @@ -139,7 +140,7 @@ namespace Elsa.Activities.Http var url = Url; var request = new HttpRequestMessage(new HttpMethod(Method), url); var authorizationHeaderValue = Authorization; - var requestHeaders = new HeaderDictionary(RequestHeaders); + var requestHeaders = new HeaderDictionary(RequestHeaders.ToDictionary(x => x.Key, x => new StringValues(x.Value.Split(',')))); if (methodSupportsBody) { diff --git a/src/activities/Elsa.Activities.Http/Models/HttpRequestHeaders.cs b/src/activities/Elsa.Activities.Http/Models/HttpRequestHeaders.cs index 291776571..e2f9f7104 100644 --- a/src/activities/Elsa.Activities.Http/Models/HttpRequestHeaders.cs +++ b/src/activities/Elsa.Activities.Http/Models/HttpRequestHeaders.cs @@ -3,7 +3,7 @@ using Microsoft.Extensions.Primitives; namespace Elsa.Activities.Http.Models { - public class HttpRequestHeaders : Dictionary + public class HttpRequestHeaders : Dictionary { public string ContentType => this["content-type"]; } diff --git a/src/activities/Elsa.Activities.Http/Models/HttpRequestModel.cs b/src/activities/Elsa.Activities.Http/Models/HttpRequestModel.cs index 21596360b..6cad7c5d4 100644 --- a/src/activities/Elsa.Activities.Http/Models/HttpRequestModel.cs +++ b/src/activities/Elsa.Activities.Http/Models/HttpRequestModel.cs @@ -7,8 +7,8 @@ namespace Elsa.Activities.Http.Models { public Uri Path { get; set; } = default!; public string Method { get; set; } = default!; - public IDictionary QueryString { get; set; } = default!; - public IDictionary Headers { get; set; } = default!; + public IDictionary QueryString { get; set; } = default!; + public IDictionary Headers { get; set; } = default!; public object? Body { get; set; } public T GetBody() => (T)Body!; } diff --git a/src/activities/Elsa.Activities.Http/Models/HttpResponseHeaders.cs b/src/activities/Elsa.Activities.Http/Models/HttpResponseHeaders.cs index abd11e385..ef2b1450e 100644 --- a/src/activities/Elsa.Activities.Http/Models/HttpResponseHeaders.cs +++ b/src/activities/Elsa.Activities.Http/Models/HttpResponseHeaders.cs @@ -3,7 +3,7 @@ using Microsoft.Extensions.Primitives; namespace Elsa.Activities.Http.Models { - public class HttpResponseHeaders : Dictionary + public class HttpResponseHeaders : Dictionary { } } \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Http/Models/HttpResponseModel.cs b/src/activities/Elsa.Activities.Http/Models/HttpResponseModel.cs index 294042c2f..823545a77 100644 --- a/src/activities/Elsa.Activities.Http/Models/HttpResponseModel.cs +++ b/src/activities/Elsa.Activities.Http/Models/HttpResponseModel.cs @@ -6,7 +6,7 @@ namespace Elsa.Activities.Http.Models public class HttpResponseModel { public HttpStatusCode StatusCode { get; set; } - public Dictionary Headers { get; set; } = new Dictionary(); + public Dictionary Headers { get; set; } = new(); public object? Content { get; set; } } } \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Http/Models/StringValuesModel.cs b/src/activities/Elsa.Activities.Http/Models/StringValuesModel.cs deleted file mode 100644 index 73b37ea88..000000000 --- a/src/activities/Elsa.Activities.Http/Models/StringValuesModel.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.Extensions.Primitives; - -namespace Elsa.Activities.Http.Models -{ - /// - /// Represents a collection of zero or more string values. It is used for values such as - /// HTTP header/query string values. These are often thought-of as key/value pairs but might - /// have more than one value. - /// - public class StringValuesModel : IConvertible - { - /// - /// Gets either the first value of or a reference - /// if the values are null or empty. - /// - /// The first value - public string? Value => Values?.FirstOrDefault(); - - /// - /// Gets a collection of the string values for the current instance. - /// - /// The values - public string[] Values { get; set; } - - /// - /// Initializes an instance of with an empty collection of values. - /// - public StringValuesModel() => Values = new string[0]; - - /// - /// Initializes an instance of from a . - /// - /// A model of zero or more string values. - public StringValuesModel(StringValues value) => Values = value.ToArray(); - - /// - /// Gets a string representation of the current instance. Either null (for no, or an empty-collection of ), - /// a single string (for a collection of one ) or a comma-separated string of many values. - /// - /// The string representation of the . - public override string? ToString() => (Values?.Any() == true) ? string.Join(",", Values) : null; - - #region IConvertible implementation - - TypeCode IConvertible.GetTypeCode() => TypeCode.Object; - bool IConvertible.ToBoolean(IFormatProvider? provider) => Convert.ToBoolean(ToString(), provider); - byte IConvertible.ToByte(IFormatProvider? provider) => Convert.ToByte(ToString(), provider); - char IConvertible.ToChar(IFormatProvider? provider) => Convert.ToChar(ToString()!, provider); - DateTime IConvertible.ToDateTime(IFormatProvider? provider) => Convert.ToDateTime(ToString(), provider); - decimal IConvertible.ToDecimal(IFormatProvider? provider) => Convert.ToDecimal(ToString(), provider); - double IConvertible.ToDouble(IFormatProvider? provider) => Convert.ToDouble(ToString(), provider); - short IConvertible.ToInt16(IFormatProvider? provider) => Convert.ToInt16(ToString(), provider); - int IConvertible.ToInt32(IFormatProvider? provider) => Convert.ToInt32(ToString(), provider); - long IConvertible.ToInt64(IFormatProvider? provider) => Convert.ToInt64(ToString(), provider); - sbyte IConvertible.ToSByte(IFormatProvider? provider) => Convert.ToSByte(ToString()!, provider); - float IConvertible.ToSingle(IFormatProvider? provider) => Convert.ToSingle(ToString(), provider); - string IConvertible.ToString(IFormatProvider? provider) => ToString()!; - object IConvertible.ToType(Type conversionType, IFormatProvider? provider) => Convert.ChangeType(ToString()!, conversionType, provider); - ushort IConvertible.ToUInt16(IFormatProvider? provider) => Convert.ToUInt16(ToString(), provider); - uint IConvertible.ToUInt32(IFormatProvider? provider) => Convert.ToUInt32(ToString(), provider); - ulong IConvertible.ToUInt64(IFormatProvider? provider) => Convert.ToUInt64(ToString(), provider); - - #endregion - } -} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Http/Parsers/FormHttpRequestBodyParser.cs b/src/activities/Elsa.Activities.Http/Parsers/FormHttpRequestBodyParser.cs index 2a119c389..a06a117fe 100644 --- a/src/activities/Elsa.Activities.Http/Parsers/FormHttpRequestBodyParser.cs +++ b/src/activities/Elsa.Activities.Http/Parsers/FormHttpRequestBodyParser.cs @@ -12,14 +12,15 @@ namespace Elsa.Activities.Http.Parsers { public int Priority => 0; public string?[] SupportedContentTypes => new[] { "application/x-www-form-urlencoded" }; - + public async Task ParseAsync(HttpRequest request, Type? targetType = default, CancellationToken cancellationToken = default) { var form = await request.ReadFormAsync(cancellationToken); + return form.ToDictionary( - x => x.Key, - x => new StringValuesModel(x.Value) - ); + x => x.Key, + x => x.Value.ToString()) + ; } } } \ No newline at end of file diff --git a/src/samples/server/Elsa.Samples.Server.Host/Workflows/FaultyWorkflow.cs b/src/samples/server/Elsa.Samples.Server.Host/Workflows/FaultyWorkflow.cs index 597567047..22b3c9b08 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/Workflows/FaultyWorkflow.cs +++ b/src/samples/server/Elsa.Samples.Server.Host/Workflows/FaultyWorkflow.cs @@ -31,7 +31,7 @@ namespace Elsa.Samples.Server.Host.Workflows private void MaybeThrow(ActivityExecutionContext context) { var model = context.GetInput()!; - var fault = model.QueryString.GetItem("fault")?.Value == "true"; + var fault = model.QueryString.GetItem("fault") == "true"; if (fault) throw new Exception("This is quite a serious fault!"); diff --git a/src/samples/server/Elsa.Samples.Server.Host/Workflows/NamingWorkflow.cs b/src/samples/server/Elsa.Samples.Server.Host/Workflows/NamingWorkflow.cs index 7212dc7bc..822530302 100644 --- a/src/samples/server/Elsa.Samples.Server.Host/Workflows/NamingWorkflow.cs +++ b/src/samples/server/Elsa.Samples.Server.Host/Workflows/NamingWorkflow.cs @@ -19,7 +19,7 @@ namespace Elsa.Samples.Server.Host.Workflows .Correlate(() => Guid.NewGuid().ToString("N")) .WriteHttpResponse(x => x.WithStatusCode(HttpStatusCode.OK).WithContent(context => $"Tell me your name please. Use correlation ID {context.WorkflowExecutionContext.CorrelationId}").WithContentType("text/plain")) .HttpEndpoint(x => x.WithPath("/signup").WithMethod(HttpMethod.Post.ToString()).WithReadContent()) - .SetVariable("Name", context => (string) context.GetInput().Body) + .SetVariable("Name", context => (string) context.GetInput()!.Body!) .SetName(context => context.GetVariable("Name")) .WriteHttpResponse(x => x diff --git a/test/unit/Elsa.UnitTests/Activities/Http/StringValuesModelTests.cs b/test/unit/Elsa.UnitTests/Activities/Http/StringValuesModelTests.cs deleted file mode 100644 index 09575532b..000000000 --- a/test/unit/Elsa.UnitTests/Activities/Http/StringValuesModelTests.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using Elsa.Activities.Http.Models; -using Microsoft.Extensions.Primitives; -using Xunit; - -namespace Elsa.Activities.Http -{ - public class StringValuesModelTests - { - [Theory(DisplayName = "It should be possible to use Convert.ChangeType to convert an instance to string. This is primarily to support usage via Jint."), AutoMoqData] - public void ItShouldBePossibleToConvertAStringValuesModelToString(string[] values) - { - var sut = new StringValuesModel(new StringValues(values)); - var result = Convert.ChangeType(sut, typeof(string)); - Assert.Equal(sut.ToString(), result); - } - - [Fact(DisplayName = "It should be possible to use Convert.ToInt32 to convert an instance to a number if the value is a valid string representation of a number. This is primarily to support usage via Jint.")] - public void ItShouldBePossibleToConvertAStringValuesModelToInt32IfValid() - { - var sut = new StringValuesModel(new StringValues("3")); - var result = Convert.ChangeType(sut, typeof(int)); - Assert.Equal(3, result); - } - - [Theory(DisplayName = "The Value property should return the first value if there is more than one."), AutoMoqData] - public void ValueShouldReturnFirstItemIfThereAreMoreThanOne(string firstValue, string secondValue) - { - var sut = new StringValuesModel(new StringValues(new [] { firstValue, secondValue })); - Assert.Equal(firstValue, sut.Value); - } - - [Theory(DisplayName = "The Value property should always return the first value if there is only one."), AutoMoqData] - public void ValueShouldReturnFirstItemIfThereIsOne(string firstValue) - { - var sut = new StringValuesModel(new StringValues(new [] { firstValue })); - Assert.Equal(firstValue, sut.Value); - } - - [Fact(DisplayName = "The Value property should return null if there are no values.")] - public void ValueShouldReturnNullIfThereAreNone() - { - var sut = new StringValuesModel(new StringValues(new string[0])); - Assert.Null(sut.Value); - } - - [Theory(DisplayName = "The Values property should return a length-one collection if there is a single value."), AutoMoqData] - public void ValuesShouldReturnLengthOneCollectionIfThereIsOneValue(string firstValue) - { - var sut = new StringValuesModel(new StringValues(new [] { firstValue })); - Assert.Equal(new [] {firstValue}, sut.Values); - } - - [Theory(DisplayName = "The Values property should return a length-two collection if there are two values."), AutoMoqData] - public void ValuesShouldReturnLengthTwoCollectionIfThereAreTwoValues(string firstValue, string secondValue) - { - var sut = new StringValuesModel(new StringValues(new [] { firstValue, secondValue })); - Assert.Equal(new [] {firstValue, secondValue}, sut.Values); - } - - [Fact(DisplayName = "The Values property should return an empty collection if there are no values.")] - public void ValuesShouldReturnEmptyCollectionIfThereAreNone() - { - var sut = new StringValuesModel(new StringValues(new string[0])); - Assert.Empty(sut.Values); - } - - [Fact(DisplayName = "The ToString method should return null if there are no values")] - public void ToStringShouldReturnNullIfNotValues() - { - var sut = new StringValuesModel(new StringValues(new string[0])); - Assert.Null(sut.ToString()); - } - - [Theory(DisplayName = "The ToString method should return the first value if there is only one"), AutoMoqData] - public void ToStringShouldReturnFirstValueIfThereIsOnlyOne(string firstValue) - { - var sut = new StringValuesModel(new StringValues(new [] { firstValue })); - Assert.Equal(firstValue, sut.ToString()); - } - - [Theory(DisplayName = "The ToString method should return comma-separated values if there are more than one"), AutoMoqData] - public void ToStringShouldReturnCommaSeparatedValuesIfThereIsMoreThanOne(string firstValue, string secondValue) - { - var sut = new StringValuesModel(new StringValues(new [] { firstValue, secondValue })); - Assert.Equal($"{firstValue},{secondValue}", sut.ToString()); - } - - [Fact(DisplayName = "The parameterless constructor should initialize Values to an empty collection")] - public void ParameterlessCtorShouldInitializeWithEmptyCollection() - { - var sut = new StringValuesModel(); - Assert.Empty(sut.Values); - } - } -} \ No newline at end of file