Skip to content

error CS1503: Argument 2: cannot convert from 'method group' to 'EventCallback' #12226

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gurunathancs1991 opened this issue Jul 16, 2019 · 6 comments
Labels
area-blazor Includes: Blazor, Razor Components component ecosystem Indicates an issue which also has impact on 3rd party component ecosystem ✔️ Resolution: By Design Resolved because the behavior in this issue is the intended design.

Comments

@gurunathancs1991
Copy link

gurunathancs1991 commented Jul 16, 2019

Description:

When using EventCallBack<T>, I countered an issue about error CS1503: Argument 2: cannot convert from 'method group' to 'EventCallback'

I have checked other github blogs which related to this, mostly reported that, this has been fixed in preview 7 version. Right now, i have tested with preview 7 build but could not get resolve it.

Here the link which i checked earlier.
#10077
#8385
#10730
#10077

Whether any syntax changes required to resolve in preview 7 version?

Screenshot:
image

Please find my component structure:

Rendering Page [Index razor page]


      @page "/"
      @using GenericEvent.Shared.Models;
      @inject IJSRuntime jsruntime;

    <MyGenComponent Data="@MyData">
        <Events>
        <NonGenericEvents EventTwo="@Event2"></NonGenericEvents>
        <GenericEvents EventOne="@EventOne"></GenericEvents>
         </Events>

    </MyGenComponent>

    @functions {
        public List<string> MyData = new List<string>() { "a", "b", "c", "d" };

        public void Event2(EventArguments args)
       {

       }

       public async Task EventOne(EventArgsData<string> data)
       {
        //dummy call
        await jsruntime.InvokeAsync<string>("call");
       }
      }

MyGenComponent.razor


    @using GenericEvent.Shared.Models;

    @typeparam T;

    <div>
        <ul>
            @ChildContent
        </ul>
    </div>


    @functions {
    [Parameter]
    protected RenderFragment ChildContent { get; set; }

    [Parameter]
    public IEnumerable<T> Data { get; set; }
    }


Events.razor


      @using Microsoft.AspNetCore.Components;

      @inherits ComponentBase



     <CascadingValue Value="@this">
        @ChildContent
    </CascadingValue>

     @functions{

    [Parameter]
    protected RenderFragment ChildContent { get; set; }

    public GenericEvents<object> GenEvents { get; set; }

    public NonGenericEvents NonGenEvents { get; set; }



     }

GenericEvents.razor


      @using Microsoft.AspNetCore.Components;
      @using GenericEvent.Shared.Models;


       @typeparam TValue


      <CascadingValue Value="@this">

     </CascadingValue>


     @functions{
   
     [Parameter]
    public EventCallback<EventArgsData<TValue>> EventOne { get; set; }

    }



NonGenericEvents.razor

   @using Microsoft.AspNetCore.Components;
    @using GenericEvent.Shared.Models;




   <CascadingValue Value="@this">

   </CascadingValue>


   @functions{

     [Parameter]
     public EventCallback<EventArguments> EventTwo { get; set; }


     }

To Reproduce

Clone this Github repository and run the application

https://github.com/gurunathancs1991/BlazorGenericEvents

We are also expecting the solution for this thread too

#12116

Additional context


C:\Users\GurunathanA>dotnet --info
.NET Core SDK (reflecting any global.json):
 Version:   3.0.100-preview7-012814
 Commit:    efad165932

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.17763
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\3.0.100-preview7-012814\

Host (useful for support):
  Version: 3.0.0-preview7-27912-14
  Commit:  4da6ee6450

.NET Core SDKs installed:
  1.1.13 [C:\Program Files\dotnet\sdk]
  1.1.14 [C:\Program Files\dotnet\sdk]
  2.1.202 [C:\Program Files\dotnet\sdk]
  2.1.502 [C:\Program Files\dotnet\sdk]
  2.1.602 [C:\Program Files\dotnet\sdk]
  2.1.700 [C:\Program Files\dotnet\sdk]
  2.2.202 [C:\Program Files\dotnet\sdk]
  2.2.300 [C:\Program Files\dotnet\sdk]
  3.0.100-preview7-012814 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.0.0-preview4-19216-03 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.0.0-preview7.19363.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 1.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.0.0-preview4-27615-11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.0.0-preview7-27912-14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.0.0-preview7-27912-14 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download
@SQL-MisterMagoo
Copy link
Contributor

A workaround (maybe even the correct way):

<GenericEvents TValue="string" EventOne="@EventOne"></GenericEvents>

@mkArtakMSFT mkArtakMSFT added area-blazor Includes: Blazor, Razor Components investigate labels Jul 16, 2019
@mkArtakMSFT mkArtakMSFT added this to the 3.1.0 milestone Jul 16, 2019
@EdCharbeneau
Copy link

I agree that this still seems like an issue as creating verbose markup when handling events (without databinding).

Take the InputSelect for example. ValueChanged either requires T to be defined or a lambda expression within ValueChanged. Compounding the problem is ValueExpression which is also required, this is leading to some very clumsy looking markup @(()=>. This isn't going to be the DX people expect when coming from jQuery, WebForms or even React.

<p>Current value: @form.MyProperty</p>

<EditForm Model="form">
    <InputSelect ValueChanged="@DoThing" 
                 T="string"
                 ValueExpression="@(()=> form.MyProperty)">
        <option value="0">0</option>
        <option value="100">100</option>
        <option value="200">200</option>
        <option value="300">300</option>
    </InputSelect>
</EditForm>

@code {
    MyForm form = new MyForm();

    void DoThing(string s)
    {
        form.MyProperty = s;
    }

    public class MyForm
    {
        public string MyProperty { get; set; }
    }
}
   <InputSelect ValueChanged="@((string s) => DoThing(s))"
                 ValueExpression="@(()=> form.MyProperty)">
        <option value="0">0</option>
        <option value="100">100</option>
        <option value="200">200</option>
        <option value="300">300</option>
    </InputSelect>

@pranavkm
Copy link
Contributor

pranavkm commented Aug 6, 2019

From what I can tell, the problem is that the compiler does not use the the generic type parameter for type inference in method calls. Here's a fairly trivial example:

public void Foo()
{
    Tester<int>(2, TestAction);
    // This fails complaining about type inference
    Tester<int>(2, CreateDelegate(TestAction));
}

public void TestAction(int x) { }

public void Tester<T>(T value, Action<T> input) { }

public static Action<T> CreateDelegate<T>(Action<T> action) => action;

We effectively get the same code when we code-gen a Razor file like this:

<InputSelect ValueChanged="ChangedInt" />

@code {
    public void ChangedInt(int value)
    {
    }
}
using Microsoft.AspNetCore.Components;

namespace razor1.Pages
{
    public class Index : Microsoft.AspNetCore.Components.ComponentBase
    {
        protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder)
        {
            __Blazor.razor1.Pages.Index.TypeInference.CreateInputSelect_0(builder, 0, 1, Microsoft.AspNetCore.Components.EventCallback.Factory.Create(this,
                           ChangedInt
            ));
        }

        public void ChangedInt(int value)
        {
        }
    }
}
namespace __Blazor.razor1.Pages.Index
{
    internal static class TypeInference
    {
        public static void CreateInputSelect_0<T>(global::Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder, int seq, int __seq0, global::Microsoft.AspNetCore.Components.EventCallback<T> __arg0)
        {
            builder.OpenComponent<global::Microsoft.AspNetCore.Components.Forms.InputSelect<T>>(seq);
            builder.AddAttribute(__seq0, "ValueChanged", __arg0);
            builder.CloseComponent();
        }
    }
}

The compiler fails the type inferrence, picks the wrong overload for EventCallback.Factory.Create and generates the method group conversion error reported here.

From playing around, one of the ways to solve this would be to modify the code in TypeInference to pass the Action<T> in and produce the EventCallback<T> in there. This works well, but we now have the pain of having to code-gen an overload per overload of EventCallback.Factory.Create<T>. Changing the code-gen is going to be fairly involved, so I'm sending it back to triage to consider for a later release.


Workarounds that have been pointed out by others in the thread that work:

  1. Specify the type parameter
<InputSelect T="int" ValueChanged="ChangedInt" />

(I filed an issue to do a pass over blazor input elements to consider renaming T to TValue or something slightly better)

  1. Use a delegate or perform an explicit cast
<InputSelect ValueChanged="(int x) => ChangedInt(x)" />

<InputSelect ValueChanged="(Action<int>)ChangedInt" />

@pranavkm pranavkm removed this from the 3.0.0-preview9 milestone Aug 6, 2019
@pranavkm pranavkm removed their assignment Aug 6, 2019
@mkArtakMSFT
Copy link
Member

Thanks for contacting us, @gurunathancs1991.
As @pranavkm has pointed out, you will have to go with one of the provided workarounds here.
Type inference will always have limitations and it's unfortunate that this is one of them.

@mkArtakMSFT mkArtakMSFT added the ✔️ Resolution: By Design Resolved because the behavior in this issue is the intended design. label Aug 7, 2019
@danroth27 danroth27 added the component ecosystem Indicates an issue which also has impact on 3rd party component ecosystem label Aug 27, 2019
@srg1204
Copy link

srg1204 commented Sep 7, 2019

EdCharbeneau commented on 23 Jul wrote: but this solution is not working with
ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 9.19424.4

Current value: @form.MyProperty

0 100 200 300

@code {
MyForm form = new MyForm();

void DoThing(string s)
{
    form.MyProperty = s;
}

public class MyForm
{
    public string MyProperty { get; set; }
}

}

0
100
200
300

@srg1204
Copy link

srg1204 commented Sep 7, 2019

Sorry my mistake:
EdCharbeneau was OK: the solution works very well

@ghost ghost locked as resolved and limited conversation to collaborators Dec 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components component ecosystem Indicates an issue which also has impact on 3rd party component ecosystem ✔️ Resolution: By Design Resolved because the behavior in this issue is the intended design.
Projects
None yet
Development

No branches or pull requests

7 participants