Skip to content

Commit bc9968f

Browse files
committed
Add configurable max length to input
1 parent 0002cdd commit bc9968f

File tree

11 files changed

+146
-13
lines changed

11 files changed

+146
-13
lines changed

playground/Stress/Stress.AppHost/InteractionCommands.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ public static IResourceBuilder<T> AddInteractionCommands<T>(this IResourceBuilde
127127
var numberOfPeopleInput = new InteractionInput { InputType = InputType.Number, Label = "Number of people", Placeholder = "Enter number of people", Value = "2", Required = true };
128128
var inputs = new List<InteractionInput>
129129
{
130-
new InteractionInput { InputType = InputType.Text, Label = "Name", Placeholder = "Enter name", Required = true },
131-
new InteractionInput { InputType = InputType.SecretText, Label = "Password", Placeholder = "Enter password", Required = true },
130+
new InteractionInput { InputType = InputType.Text, Label = "Name", Placeholder = "Enter name", Required = true, MaxLength = 50 },
131+
new InteractionInput { InputType = InputType.SecretText, Label = "Password", Placeholder = "Enter password", Required = true, MaxLength = 20 },
132132
dinnerInput,
133133
numberOfPeopleInput,
134134
new InteractionInput { InputType = InputType.Boolean, Label = "Remember me", Placeholder = "What does this do?", Required = true },

src/Aspire.Dashboard/Aspire.Dashboard.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,8 @@
270270
<Compile Include="$(SharedDir)ConsoleLogs\LogEntry.cs" Link="Utils\ConsoleLogs\LogEntry.cs" />
271271
<Compile Include="$(SharedDir)ConsoleLogs\LogPauseViewModel.cs" Link="Utils\ConsoleLogs\LogPauseViewModel.cs" />
272272
<Compile Include="$(SharedDir)ConsoleLogs\TimestampParser.cs" Link="Utils\ConsoleLogs\TimestampParser.cs" />
273-
<Compile Include="..\Shared\KnownUrls.cs" Link="Utils\KnownUrls.cs" />
273+
<Compile Include="$(SharedDir)KnownUrls.cs" Link="Utils\KnownUrls.cs" />
274+
<Compile Include="$(SharedDir)InteractionHelpers.cs" Link="Utils\InteractionHelpers.cs" />
274275
</ItemGroup>
275276

276277
<ItemGroup>

src/Aspire.Dashboard/Components/Dialogs/InteractionsInputDialog.razor

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@
3333
<FluentStack Orientation="Orientation.Vertical" VerticalGap="12">
3434
@foreach (var vm in _inputDialogInputViewModels)
3535
{
36-
@*
37-
* AutoComplete value of one-time-code on password input prevents the browser asking to save the value.
38-
* Immediate value of true on text inputs ensures the value is set to the server token with every key press in textbox.
39-
*@
4036
var localItem = vm;
4137
var descriptionId = !string.IsNullOrEmpty(localItem.Input.Description)
4238
? $"{_elementRefs[localItem]?.Id}-description"
@@ -45,18 +41,25 @@
4541
@switch (vm.Input.InputType)
4642
{
4743
case InputType.Text:
44+
@*
45+
* Immediate value of true on text input ensures the value is set to the server token with every key press in textbox.
46+
*@
4847
<FluentTextField @ref="@_elementRefs[localItem]"
4948
@bind-Value="localItem.Value"
5049
Label="@localItem.Input.Label"
5150
Placeholder="@localItem.Input.Placeholder"
5251
Required="localItem.Input.Required"
5352
Immediate="true"
5453
aria-describedby="@descriptionId"
55-
Maxlength="@MaxTextLength" />
54+
Maxlength="@GetMaxLength(localItem)" />
5655
@GetDescriptionContent(localItem.Input, descriptionId)
5756
<ValidationMessage For="@(() => localItem.Value)" />
5857
break;
5958
case InputType.SecretText:
59+
@*
60+
* AutoComplete value of one-time-code on password input prevents the browser asking to save the value.
61+
* Immediate value of true on text input ensures the value is set to the server token with every key press in textbox.
62+
*@
6063
<FluentTextField @ref="@_elementRefs[localItem]"
6164
@bind-Value="localItem.Value"
6265
Label="@localItem.Input.Label"
@@ -66,7 +69,7 @@
6669
AutoComplete="one-time-code"
6770
Immediate="true"
6871
aria-describedby="@descriptionId"
69-
Maxlength="@MaxTextLength" />
72+
Maxlength="@GetMaxLength(localItem)" />
7073
@GetDescriptionContent(localItem.Input, descriptionId)
7174
<ValidationMessage For="@(() => localItem.Value)" />
7275
break;

src/Aspire.Dashboard/Components/Dialogs/InteractionsInputDialog.razor.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,14 @@ private async Task CancelAsync()
171171
{
172172
await Dialog.CancelAsync();
173173
}
174+
175+
private static int GetMaxLength(InputViewModel inputModel)
176+
{
177+
if (inputModel.Input.MaxLength == 0)
178+
{
179+
return MaxTextLength;
180+
}
181+
182+
return inputModel.Input.MaxLength;
183+
}
174184
}

src/Aspire.Hosting/Aspire.Hosting.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
<Compile Include="$(SharedDir)PortAllocator.cs" Link="Publishing\PortAllocator.cs" />
4343
<Compile Include="$(SharedDir)OverloadResolutionPriorityAttribute.cs" Link="Utils\OverloadResolutionPriorityAttribute.cs" />
4444
<Compile Include="$(SharedDir)PackageUpdateHelpers.cs" Link="Utils\PackageUpdateHelpers.cs" />
45+
<Compile Include="$(SharedDir)InteractionHelpers.cs" Link="Utils\InteractionHelpers.cs" />
4546
</ItemGroup>
4647

4748
<ItemGroup>

src/Aspire.Hosting/Dashboard/DashboardService.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ async Task WatchInteractionsInternal(CancellationToken cancellationToken)
143143
{
144144
dto.Options.Add(input.Options.ToDictionary());
145145
}
146+
if (input.MaxLength != null)
147+
{
148+
dto.MaxLength = input.MaxLength.Value;
149+
}
146150
dto.ValidationErrors.AddRange(input.ValidationErrors);
147151
return dto;
148152
}).ToList();

src/Aspire.Hosting/Dashboard/proto/dashboard_service.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ message InteractionInput {
376376
repeated string validation_errors = 7;
377377
string description = 8;
378378
bool enable_description_markdown = 9;
379+
int32 max_length = 10;
379380
}
380381
enum MessageIntent {
381382
MESSAGE_INTENT_NONE = 0;

src/Aspire.Hosting/IInteractionService.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,6 @@ public interface IInteractionService
103103
[Experimental(InteractionService.DiagnosticId, UrlFormat = "https://aka.ms/aspire/diagnostics/{0}")]
104104
public sealed class InteractionInput
105105
{
106-
internal const int MaxTextLength = 8000;
107-
108106
/// <summary>
109107
/// Gets or sets the label for the input.
110108
/// </summary>
@@ -146,6 +144,23 @@ public sealed class InteractionInput
146144
/// </summary>
147145
public string? Placeholder { get; set; }
148146

147+
/// <summary>
148+
/// gets or sets the maximum length for text inputs.
149+
/// </summary>
150+
public int? MaxLength
151+
{
152+
get => field;
153+
set
154+
{
155+
if (value is { } v)
156+
{
157+
ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(v, 0);
158+
}
159+
160+
field = value;
161+
}
162+
}
163+
149164
internal List<string> ValidationErrors { get; } = [];
150165
}
151166

src/Aspire.Hosting/InteractionService.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,11 @@ private async Task<bool> RunValidationAsync(Interaction interactionState, Intera
264264
{
265265
case InputType.Text:
266266
case InputType.SecretText:
267-
if (value.Length > InteractionInput.MaxTextLength)
267+
var maxLength = InteractionHelpers.GetMaxLength(input.MaxLength);
268+
269+
if (value.Length > maxLength)
268270
{
269-
context.AddValidationError(input, $"Value length exceeds {InteractionInput.MaxTextLength} characters.");
271+
context.AddValidationError(input, $"Value length exceeds {maxLength} characters.");
270272
}
271273
break;
272274
case InputType.Choice:

src/Shared/InteractionHelpers.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Buffers;
5+
using System.Diagnostics;
6+
using System.Security.Cryptography;
7+
using System.Text;
8+
9+
namespace Aspire;
10+
11+
internal static class InteractionHelpers
12+
{
13+
// Chosen to balance between being long enough for most normal use but provides a default limit
14+
// to prevent possible abuse of interactions API.
15+
public const int DefaultMaxLength = 8000;
16+
17+
public static int GetMaxLength(int? configuredInputLength)
18+
{
19+
// An unconfigured max length uses the default.
20+
if (configuredInputLength is null || configuredInputLength == 0)
21+
{
22+
return DefaultMaxLength;
23+
}
24+
25+
return configuredInputLength.Value;
26+
}
27+
}

0 commit comments

Comments
 (0)