Skip to content
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

Minimal API F# RouteValue is Null #38906

Open
rfvgyhn opened this issue Dec 9, 2021 · 4 comments
Open

Minimal API F# RouteValue is Null #38906

rfvgyhn opened this issue Dec 9, 2021 · 4 comments
Assignees
Labels
area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc
Milestone

Comments

@rfvgyhn
Copy link

rfvgyhn commented Dec 9, 2021

Mapping a route with a route value in F# fails to bind the value when using a named function instead of a anonymous function. I'm not sure if this is an ASP.NET or F# issue (or maybe just a consequence of how F# works with the delegate param).

dotnet new web -lang F#

open System
open Microsoft.AspNetCore.Builder
open Microsoft.Extensions.Hosting


[<EntryPoint>]
let main args =
    let builder = WebApplication.CreateBuilder(args)
    let app = builder.Build()
    
    let funcB v = v
    let funcC = fun v -> v 

    app.MapGet("/a/{v}", Func<string, _> (fun v -> v)) |> ignore
    app.MapGet("/b/{v}", Func<string, _> funcB) |> ignore
    app.MapGet("/c/{v}", Func<string, _> funcC) |> ignore

    app.Run()

    0 // Exit code

dotnet run

GET /a/test

test
GET /b/test

System.ArgumentNullException: Value cannot be null. (Parameter 'text')
   at Microsoft.AspNetCore.Http.HttpResponseWritingExtensions.WriteAsync(HttpResponse response, String text, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.RequestDelegateFactory.ExecuteWriteStringResponseAsync(HttpContext httpContext, String text)
   at lambda_method2(Closure , Object , HttpContext )
   at Microsoft.AspNetCore.Http.RequestDelegateFactory.<>c__DisplayClass36_0.<Create>b__0(HttpContext httpContext)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
GET /c/test

System.ArgumentNullException: Value cannot be null. (Parameter 'text')
   at Microsoft.AspNetCore.Http.HttpResponseWritingExtensions.WriteAsync(HttpResponse response, String text, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Http.RequestDelegateFactory.ExecuteWriteStringResponseAsync(HttpContext httpContext, String text)
   at lambda_method3(Closure , Object , HttpContext )
   at Microsoft.AspNetCore.Http.RequestDelegateFactory.<>c__DisplayClass36_0.<Create>b__0(HttpContext httpContext)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
$ dotnet --info
.NET SDK (reflecting any global.json):
 Version:   6.0.100
 Commit:    9e8b04bbff

Runtime Environment:
 OS Name:     arch
 OS Version:
 OS Platform: Linux
 RID:         arch-x64
 Base Path:   /usr/share/dotnet/sdk/6.0.100/

Host (useful for support):
  Version: 6.0.0
  Commit:  4822e3c3aa

.NET SDKs installed:
  6.0.100 [/usr/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 6.0.0 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 6.0.0 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
@davidfowl
Copy link
Member

This is because the name of the parameter is lost through in the F# function conversions (as you've pointed out).

cc @dsyme

@Pilchie Pilchie added the area-web-frameworks *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels label Dec 9, 2021
@rafikiassumani-msft rafikiassumani-msft added this to the Backlog milestone Jan 11, 2022
@ghost
Copy link

ghost commented Jan 11, 2022

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@captainsafia captainsafia added area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc and removed area-web-frameworks *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels labels Jun 20, 2023
@mchylek
Copy link

mchylek commented Aug 29, 2023

As a workaround you can also use wrapper with AsParametersAttribute

public static class Endpoint
{
    public static Delegate Of<TParam, TResult>(FSharpFunc<TParam, TResult> requestDelegate)
    {
        return (HttpContext context, [AsParametersAttribute] TParam parameters) => requestDelegate.Invoke(parameters);
    }
}

And then from F#

app.MapGet("/{name}", Endpoint.Of (fun (req : {| Name : string |}) -> $"Hello {req.Name}!"))

I've made simplistic library for this https://github.com/mchylek/Endpoints.FSharp.Interop

@lucasteles
Copy link

Also
#46551 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-minimal Includes minimal APIs, endpoint filters, parameter binding, request delegate generator etc
Projects
None yet
Development

No branches or pull requests

8 participants