Skip to content

Supporting calling non-generic instance methods on generic types #9061

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
julienGrd opened this issue Apr 4, 2019 · 9 comments
Closed

Supporting calling non-generic instance methods on generic types #9061

julienGrd opened this issue Apr 4, 2019 · 9 comments
Assignees
Labels
area-blazor Includes: Blazor, Razor Components bug This issue describes a behavior which is not expected - a bug. component ecosystem Indicates an issue which also has impact on 3rd party component ecosystem Done This issue has been fixed

Comments

@julienGrd
Copy link

julienGrd commented Apr 4, 2019

Describe the bug

I have a generic component wich need some Js interaction. My component is an autocomplete wich listen on the keypress event to launch research. Whe i try invoke c# method from Js, I have this following Js error
"Error: System.InvalidOperationException: Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
"

To Reproduce

create a generic component, which contain an input type text

@typeparam TItem 
@inherits AutoCompleteViewModel<TItem>
<input type="text" id="@Id" class="form-control" value="@Value"> `

register js on render

 protected override async Task OnAfterRenderAsync()
        {
            this.JsRuntime.InvokeAsync<object>("listenAutoComplete", this.Id, new DotNetObjectRef(this));
            await base.OnAfterRenderAsync();
        }

[JSInvokable]
        public void SynchroniseValue(string value)
        {
            if(this.Value != value)
            {
                this.Value = value;
                this.LaunchResearch();
            }
        }
function listenAutoComplete(id, control) {
    $("#" + id).keyup(function () {
        var value = $(this).val();
        control.invokeMethodAsync('SynchroniseValue', value);
    });
}

Expected behavior

Have a way to call C# method without error

Additional context

My first idea was to use the key-* event of razor, but i was unable to have a satisfaying behavior with ths events (unable to retrieve the current value of my input, binding seem only fire when control lost focus), so i decided to switch on js.
If you have another solution, i take it ;-)

@Eilon Eilon added the area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates label Apr 4, 2019
@mkArtakMSFT mkArtakMSFT added the area-blazor Includes: Blazor, Razor Components label Apr 5, 2019
@mkArtakMSFT
Copy link
Member

Thanks for contacting us, @julienGrd.
You're facing this issue because we currently don't support JSInterop from a generic type.

@mkArtakMSFT mkArtakMSFT added the enhancement This issue represents an ask for new feature or an enhancement to an existing one label Apr 5, 2019
@mkArtakMSFT mkArtakMSFT added this to the 3.0.0-preview6 milestone Apr 5, 2019
@mrpmorris
Copy link

@mkArtakMSFT This PR on the old repo would have fixed it. If I can get approval then I will reimplement it on this repo instead - but I don't want to do that if there is no chance of it being merged in...

dotnet/jsinterop#6

@SteveSandersonMS
Copy link
Member

@mrpmorris I'd recommend holding off on reimplementing the PR. The reason is that, if we're only supporting calling methods on generic types if it's an instance method and the method itself has no generic args [1], then my gut sense is that it should be an extremely small change, on the order of a few lines of code. The previous PR involved some extensive refactoring which I would hope we can avoid.

[1] I do agree this is probably the right restriction, since you probably don't want to let client-side code pass arbitrary type args. There would be security implications if it can force the server to load types (and execute static constructors, etc.) that you never expected it to load.

@mrpmorris
Copy link

mrpmorris commented Apr 23, 2019

@SteveSandersonMS Hi Steve.
The code was mostly refactored (500 lines). I extracted out your code for holding lookups so we could have one for static methods and one for instance methods. The lookup method was different because static must have unique names per DLL, but for instance we couldn't do this because we need to allow duplicate names in the DLL that are unique based on hierarchy.

Most of the code is actually test classes (probably 2/3 or 3/4 of the remaining 500 lines).

@mkArtakMSFT mkArtakMSFT removed area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates labels May 9, 2019
@SQL-MisterMagoo
Copy link
Contributor

FYI - for a workaround, I have found that using a child component to handle the JS Interop works, then I just wired up some Action parameters so the child can notify the Generic parent when something happens.

@mkArtakMSFT mkArtakMSFT modified the milestones: 3.0.0-preview7, Backlog May 24, 2019
@littlejohnjt
Copy link

littlejohnjt commented Jul 18, 2019

I am having a similar issue but not necessarily to a component. I want to basically process JS promises back in C# by passing an instance method to JS to call when a promise succeeds (kind of a promise handler) which would populate a TaskCompletionSource object and return it to C#.

@danroth27 danroth27 modified the milestones: Backlog, 3.1.0 Aug 22, 2019
@mkArtakMSFT mkArtakMSFT modified the milestones: 3.1.0, 3.1.0-preview1 Aug 27, 2019
@danroth27 danroth27 added the component ecosystem Indicates an issue which also has impact on 3rd party component ecosystem label Aug 27, 2019
@Bob-HL
Copy link

Bob-HL commented Aug 30, 2019

JS invokeMethod to .NET GenericClass.Method() cause TargetException: Object does not match target type, even the parameter is not generic/T.

@danroth27 danroth27 changed the title [Razor Component] - "Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true." when Invoke C# method from Js on generic component Supporting calling non-generic instance methods on generic types Sep 7, 2019
@danroth27 danroth27 mentioned this issue Sep 7, 2019
10 tasks
@SteveSandersonMS
Copy link
Member

@pranavkm You're already doing/done this, right? Do you want to self-assign and perhaps close as done?

@pranavkm pranavkm self-assigned this Sep 19, 2019
@pranavkm
Copy link
Contributor

Merged as part of dotnet/extensions#2342. I'll keep this open to add a couple of E2E tests with Blazor.

@pranavkm pranavkm reopened this Sep 19, 2019
@danroth27 danroth27 added bug This issue describes a behavior which is not expected - a bug. and removed enhancement This issue represents an ask for new feature or an enhancement to an existing one labels Sep 25, 2019
pranavkm added a commit that referenced this issue Oct 1, 2019
pranavkm added a commit that referenced this issue Oct 2, 2019
@mkArtakMSFT mkArtakMSFT added Done This issue has been fixed and removed Working labels Oct 4, 2019
@ghost ghost locked as resolved and limited conversation to collaborators Dec 3, 2019
JunTaoLuo pushed a commit that referenced this issue Feb 12, 2020
…ns#2342)

* Add support for JSInvokable methods on generic types

Prior to this change, DotNetDispatcher cached the MethodInfo on the
generic type definition. Using this would have required MethodInfo.MakeGenericMethod before the method was invoked.
We could separately cache the result of this to avoid the reflection cost per invocation.

Alternatively we could cache static and non-static MethodInfo instances separately which is what this change attempts to do.
The big difference in the outcome is that this requires instance (non-static) JSInvokable methods to be only unique named within
the type hierarchy as opposed to across all static and instance JSInvokable methods in an assembly.

Fixes dotnet/extensions#1360
Fixes #9061
\n\nCommit migrated from dotnet/extensions@659b604
JunTaoLuo pushed a commit that referenced this issue Feb 13, 2020
…nsdotnet/extensionsdotnet/extensionsdotnet/extensions#2342)

* Add support for JSInvokable methods on generic types

Prior to this change, DotNetDispatcher cached the MethodInfo on the
generic type definition. Using this would have required MethodInfo.MakeGenericMethod before the method was invoked.
We could separately cache the result of this to avoid the reflection cost per invocation.

Alternatively we could cache static and non-static MethodInfo instances separately which is what this change attempts to do.
The big difference in the outcome is that this requires instance (non-static) JSInvokable methods to be only unique named within
the type hierarchy as opposed to across all static and instance JSInvokable methods in an assembly.

Fixes dotnet/extensions#1360
Fixes #9061
\n\nCommit migrated from https://github.com/dotnet/extensions/commit/dotnet/extensions@dotnet/extensions@dotnet/extensions@659b604fb2e595d48a931a7ed831f6c38f035382
\n\nCommit migrated from https://github.com/dotnet/extensions/commit/dotnet/extensions@dotnet/extensions@aaf9159b65e6fd911ffc63514bc3b179d4122d08
\n\nCommit migrated from https://github.com/dotnet/extensions/commit/dotnet/extensions@4f70b0248ef2ba6547cbe93bdea8169c2b826898
\n\nCommit migrated from dotnet/extensions@92c60ff
JunTaoLuo pushed a commit that referenced this issue Feb 15, 2020
…ns#2342)

* Add support for JSInvokable methods on generic types

Prior to this change, DotNetDispatcher cached the MethodInfo on the
generic type definition. Using this would have required MethodInfo.MakeGenericMethod before the method was invoked.
We could separately cache the result of this to avoid the reflection cost per invocation.

Alternatively we could cache static and non-static MethodInfo instances separately which is what this change attempts to do.
The big difference in the outcome is that this requires instance (non-static) JSInvokable methods to be only unique named within
the type hierarchy as opposed to across all static and instance JSInvokable methods in an assembly.

Fixes dotnet/extensions#1360
Fixes #9061
\n\nCommit migrated from dotnet/extensions@659b604
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components bug This issue describes a behavior which is not expected - a bug. component ecosystem Indicates an issue which also has impact on 3rd party component ecosystem Done This issue has been fixed
Projects
None yet
Development

No branches or pull requests

10 participants