Implement XML content writer

This commit is contained in:
Sipke Schoorstra 2023-01-24 22:39:31 +01:00
parent 061daa206d
commit 2697f512e9
9 changed files with 89 additions and 12 deletions

View file

@ -1,13 +1,12 @@
using System.Net;
using System.Net.Http.Headers;
using Elsa.Extensions;
using Elsa.Http.ContentWriters;
using Elsa.Http.Models;
using Elsa.Http.Providers;
using Elsa.Workflows.Core.Attributes;
using Elsa.Workflows.Core.Models;
using Elsa.Workflows.Management.Models;
using Microsoft.AspNetCore.Http;
using HttpRequestHeaders = Elsa.Http.Models.HttpRequestHeaders;
using HttpResponseHeaders = Elsa.Http.Models.HttpResponseHeaders;
namespace Elsa.Http;
@ -34,7 +33,7 @@ public class WriteHttpResponse : CodeActivity
/// </summary>
[Input(
Description = "The content type to use when returning the response.",
Options = new[] { "", "text/plain", "text/html", "application/json", "application/xml", "application/x-www-form-urlencoded" },
OptionsProvider = typeof(WriteHttpResponseContentTypeOptionsProvider),
UIHint = InputUIHints.Dropdown
)]
public Input<string?> ContentType { get; set; } = default!;

View file

@ -6,11 +6,11 @@ using System.Text;
namespace Elsa.Http.ContentWriters;
/// <summary>
/// Creates a <see cref="StringContent"/> object for application/json.
/// Creates a <see cref="HttpContent"/> object for application/json.
/// </summary>
public class JsonContentFactory : IHttpContentFactory
{
private readonly List<string> _supportedContentTypes = new() { MediaTypeNames.Application.Json };
private readonly List<string> _supportedContentTypes = new() { MediaTypeNames.Application.Json, "text/json" };
/// <inheritdoc />
public bool SupportsContentType(string contentType) => _supportedContentTypes.Contains(contentType);

View file

@ -4,14 +4,13 @@ using System.Text;
namespace Elsa.Http.ContentWriters;
/// <summary>
/// Creates a <see cref="StringContent"/> object for application/json, application/xml, text/json and text/xml content types.
/// Creates a <see cref="StringContent"/> object for text/plain, text/richtext and text/html content types.
/// </summary>
public class TextContentFactory : IHttpContentFactory
{
private readonly List<string> _supportedContentTypes = new()
{
MediaTypeNames.Text.Plain,
MediaTypeNames.Text.Xml,
MediaTypeNames.Text.RichText,
MediaTypeNames.Text.Html,
};

View file

@ -0,0 +1,31 @@
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Text;
using System.Xml.Serialization;
namespace Elsa.Http.ContentWriters;
/// <summary>
/// Creates a <see cref="HttpContent"/> object for application/json.
/// </summary>
public class XmlContentFactory : IHttpContentFactory
{
private readonly List<string> _supportedContentTypes = new() { MediaTypeNames.Application.Xml, MediaTypeNames.Text.Xml };
/// <inheritdoc />
public bool SupportsContentType(string contentType) => _supportedContentTypes.Contains(contentType);
/// <inheritdoc />
public HttpContent CreateHttpContent(object content, string contentType)
{
var text = content as string ?? Serialize(content);
return new StringContent(text, Encoding.UTF8, contentType);
}
private string Serialize(object value)
{
using var writer = new StringWriter();
new XmlSerializer(value.GetType()).Serialize(writer, value);
return writer.ToString();
}
}

View file

@ -8,7 +8,9 @@ using Elsa.Http.Handlers;
using Elsa.Http.Implementations;
using Elsa.Http.Options;
using Elsa.Http.Parsers;
using Elsa.Http.Providers;
using Elsa.Http.Services;
using Elsa.Workflows.Management.Implementations;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
@ -78,15 +80,19 @@ public class HttpFeature : FeatureBase
.AddNotificationHandlersFrom<UpdateRouteTable>()
.AddHttpContextAccessor()
// Add content parsers.
// Content parsers.
.AddSingleton<IHttpContentParser, StringHttpContentParser>()
.AddSingleton<IHttpContentParser, JsonHttpContentParser>()
.AddSingleton<IHttpContentParser, XmlHttpContentParser>()
// Add HTTP content factories.
// HTTP content factories.
.AddSingleton<IHttpContentFactory, TextContentFactory>()
.AddSingleton<IHttpContentFactory, JsonContentFactory>()
.AddSingleton<IHttpContentFactory, XmlContentFactory>()
.AddSingleton<IHttpContentFactory, FormUrlEncodedHttpContentFactory>()
// Activity property options providers
.AddSingleton<IActivityPropertyOptionsProvider, WriteHttpResponseContentTypeOptionsProvider>()
;
}
}

View file

@ -2,6 +2,9 @@ using Microsoft.AspNetCore.Http;
namespace Elsa.Http.Options;
/// <summary>
/// Provides various options related to the HTTP activities.
/// </summary>
public class HttpActivityOptions
{
/// <summary>
@ -13,4 +16,19 @@ public class HttpActivityOptions
/// The base URL of the server. This should be set to the same value at which the Elsa Server is publicly available. It will be used when generating absolute URLs need to be generated by activities such as SendEmail.
/// </summary>
public Uri BaseUrl { get; set; } = default!;
/// <summary>
/// A configurable set of available content types available from the <see cref="WriteHttpResponse"/> activity.
/// </summary>
public ISet<string> AvailableContentTypes { get; set; } = new HashSet<string>
{
"application/json",
"application/xml",
"application/x-www-form-urlencoded",
"application/octet-stream",
"text/plain",
"text/html",
"text/json",
"text/xml",
};
}

View file

@ -0,0 +1,18 @@
using System.Reflection;
using Elsa.Http.Options;
using Elsa.Workflows.Management.Implementations;
using Microsoft.Extensions.Options;
namespace Elsa.Http.Providers;
internal class WriteHttpResponseContentTypeOptionsProvider : IActivityPropertyOptionsProvider
{
private readonly HttpActivityOptions _options;
public WriteHttpResponseContentTypeOptionsProvider(IOptions<HttpActivityOptions> options)
{
_options = options.Value;
}
public object GetOptions(PropertyInfo property) => new[] { "" }.Concat(_options.AvailableContentTypes);
}

View file

@ -6,7 +6,7 @@ namespace Elsa.JavaScript.Activities;
internal class RunJavaScriptOptionsProvider : IActivityPropertyOptionsProvider
{
public object? GetOptions(PropertyInfo property)
public object GetOptions(PropertyInfo property)
{
return new CodeEditorOptions
{

View file

@ -2,7 +2,13 @@ using System.Reflection;
namespace Elsa.Workflows.Management.Implementations;
/// <summary>
/// Provides options about a given activity property.
/// </summary>
public interface IActivityPropertyOptionsProvider
{
object? GetOptions(PropertyInfo property);
/// <summary>
/// Returns options for the specified property.
/// </summary>
object GetOptions(PropertyInfo property);
}