< Summary

Information
Class: Elsa.Workflows.Api.Endpoints.Bookmarks.Resume.Request
Assembly: Elsa.Workflows.Api
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Api/Endpoints/Bookmarks/Resume/Endpoint.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 1
Coverable lines: 1
Total lines: 109
Line coverage: 0%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_Input()100%210%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Api/Endpoints/Bookmarks/Resume/Endpoint.cs

#LineLine coverage
 1using Elsa.Abstractions;
 2using Elsa.SasTokens.Contracts;
 3using Elsa.Workflows.Runtime;
 4using FastEndpoints;
 5using JetBrains.Annotations;
 6using Microsoft.AspNetCore.Http;
 7
 8namespace Elsa.Workflows.Api.Endpoints.Bookmarks.Resume;
 9
 10/// <summary>
 11/// Resumes a bookmarked workflow instance with the bookmark ID specified in the provided SAS token.
 12/// </summary>
 13[PublicAPI]
 14internal class Resume(ITokenService tokenService, IWorkflowResumer workflowResumer, IBookmarkQueue bookmarkQueue, IPaylo
 15{
 16    /// <inheritdoc />
 17    public override void Configure()
 18    {
 19        Routes("/bookmarks/resume");
 20        Verbs(Http.GET, Http.POST);
 21        AllowAnonymous();
 22    }
 23
 24    /// <inheritdoc />
 25    public override async Task HandleAsync(Request request, CancellationToken cancellationToken)
 26    {
 27        var token = Query<string>("t")!;
 28        var asynchronous = Query<bool>("async", false);
 29
 30        if (!tokenService.TryDecryptToken<BookmarkTokenPayload>(token, out var payload))
 31            AddError("Invalid token.");
 32
 33        var input = HttpContext.Request.Method == HttpMethods.Post ? request.Input : GetInputFromQueryString();
 34
 35        if (ValidationFailed)
 36        {
 37            await Send.ErrorsAsync(cancellation: cancellationToken);
 38            return;
 39        }
 40
 41        // Some clients, like Blazor, may prematurely cancel their request upon navigation away from the page.
 42        // In this case, we don't want to cancel the workflow execution.
 43        // We need to better understand the conditions that cause this.
 44        var workflowCancellationToken = CancellationToken.None;
 45        await ResumeBookmarkedWorkflowAsync(payload, input, asynchronous, workflowCancellationToken);
 46
 47        if (!HttpContext.Response.HasStarted)
 48            await Send.OkAsync(cancellationToken);
 49    }
 50
 51    private IDictionary<string, object>? GetInputFromQueryString()
 52    {
 53        var inputJson = Query<string?>("in", false);
 54        if (string.IsNullOrWhiteSpace(inputJson))
 55            return null;
 56
 57        try
 58        {
 59            return serializer.Deserialize<IDictionary<string, object>>(inputJson);
 60        }
 61        catch
 62        {
 63            AddError("Invalid input format. Expected a valid JSON string.");
 64            return null;
 65        }
 66    }
 67
 68    private async Task ResumeBookmarkedWorkflowAsync(BookmarkTokenPayload tokenPayload, IDictionary<string, object>? inp
 69    {
 70        var bookmarkId = tokenPayload.BookmarkId;
 71        var workflowInstanceId = tokenPayload.WorkflowInstanceId;
 72
 73        if (asynchronous)
 74        {
 75            var item = new NewBookmarkQueueItem
 76            {
 77                BookmarkId = bookmarkId,
 78                WorkflowInstanceId = workflowInstanceId,
 79                Options = new()
 80                {
 81                    Input = input
 82                }
 83            };
 84
 85            await bookmarkQueue.EnqueueAsync(item, cancellationToken);
 86            return;
 87        }
 88
 89        var resumeRequest = new ResumeBookmarkRequest
 90        {
 91            BookmarkId = bookmarkId,
 92            WorkflowInstanceId = workflowInstanceId,
 93            Input = input
 94        };
 95
 96        await workflowResumer.ResumeAsync(resumeRequest, cancellationToken);
 97    }
 98}
 99
 100/// <summary>
 101/// The request model for the Resume endpoint.
 102/// </summary>
 103internal class Request
 104{
 105    /// <summary>
 106    /// The input to provide to the workflow when resuming.
 107    /// </summary>
 0108    public IDictionary<string, object>? Input { get; set; }
 109}

Methods/Properties

get_Input()