1

I have something like this in mij Index.razor file:

<div class="trials">
    @DoSomething("First try")
    @(async () => await DoSomething("Second try"))
    @DoSomething("Third try").Result
</div>

<div class="purpose">
    <h4>@DoSomething("Use the result like a title")</h4>
    <textarea placeholder="@DoSomething("Use the result like a placeholder")" />
    <button type="button" class="btn">@DoSomething("Show the result on a button")</button>
</div>


@code {
    private async Task<string> DoSomething(string text)
    {
        return await client.DoSomething(text);
    }
}

I want to show the string result of the DoSomething() on headers, buttons, placeholders etc. But I cannot get it to work. I have tried different solutions.

First try:

@DoSomething("First try")

Returns System.Threading.Tasks.Task`1[System.String] instead of the result I expect.

Second try:

@(async () => await DoSomething("Second try"))

It says this is not valid because: Cannot convert lambda expression to type 'object' because it is not a delegate type

Third try:

@DoSomething("Third try").Result

Does not come back, the application will freeze.

It is possible to store the result in a variable or property, but this is not a solution for me because I will use it like everywhere, on buttons, placeholders and stuff.

How do I show the result of DoSomething() on a header/button/placeholder/etc?

Kim Went
  • 19
  • 7
  • DoSomething has only one input parameter, a string, and the output is also a string. The value of the input parameter varies. – Kim Went Jun 11 '20 at 04:44
  • What matters is if the number of input parameters varies. – H H Jun 11 '20 at 20:00

2 Answers2

1

The 'cleanest' I can think of is a Component for the job:

// AsyncHelper.razor    
@result
@code {
    [Parameter]
    public Func<string, Task<string>> Formatter { get; set; }

    [Parameter]
    public string Text { get; set; }

    private string result;

    protected override async Task OnParametersSetAsync()
    {
        result = await Source(Text);
    }    
}

and then use it like

<h4><AsyncHelper Formatter="DoSomething" Text ="Use the result like a title" /></h4>
H H
  • 263,252
  • 30
  • 330
  • 514
  • Great! This is a nice solution for headers, button texts, labels, but is it somehow possible to use it for a placeholder? Like this: – Kim Went Jun 15 '20 at 11:02
0

The correct way to do this is as follows

<div class="trials">
   @Value1
   @Value2
   @Value3
</div>

@code
{
  protected override async Task OnInitializedAsync()
  {
    Value1 = "1";
    Value2 = await DoSomethingAsync().ConfigureAwait(false);
    Value3 = "3";
  }
}
Peter Morris
  • 20,174
  • 9
  • 81
  • 146
  • This is not a solution for me, because I do not want a zillion @Values for each DoSomethingAsync() I do.. – Kim Went Jun 09 '20 at 13:02
  • The `ConfigureAwait(false)` is unnecessary and can [lead to problems](https://stackoverflow.com/q/62289074/60761). – H H Jun 09 '20 at 18:47
  • @HenkHolterman It doesn't tell the task to continue on another thread, it says it doesn't care which thread it continues on. If it causes a hang then it needs to be reported as a bug. – Peter Morris Jun 09 '20 at 18:54
  • @KimWent Please provide more information, as your question doesn't seem to accurately represent your requirement. – Peter Morris Jun 09 '20 at 18:55
  • @PeterMorris - it will not cause a 'hang'. But it could lead to wrong-context errors. But I admit the root cause is not shown in the question I linked to. – H H Jun 09 '20 at 19:29
  • @PeterMorris I already said in my opening post: It is possible to store the result in a variable or property, but this is not a solution for me because I will use it like everywhere, on buttons, placeholders and stuff. – Kim Went Jun 11 '20 at 04:48