How to call extension method when there is a property with same name?

Viewed 131

I'm trying to use OwaspHeaders.Core nuget package, but I cannot figure out how to use their fluent style configuration builder in F#. The following is C# code from their documentation converted to F# (and simplified a little).

#r "nuget: OwaspHeaders.Core, 4.2.0"
open OwaspHeaders.Core.Extensions

let config =
    SecureHeadersMiddlewareBuilder
        .CreateBuilder()
        .UseHsts(1200, false)
        .Build()

The problem is that the object that CreateBuilder returns has also UseHsts property, which is what is resolved no matter what I try resulting in an error.

FS0003: This value is not a function and cannot be applied.

How can I call UseHsts extension method, instead of accessing the property with same name?

enter image description here

3 Answers

One way is to call the UseHsts method directly

let config =
    SecureHeadersMiddlewareBuilder
        .UseHsts(SecureHeadersMiddlewareBuilder.CreateBuilder(), 1200, false)
        .Build()

Following on @nilekirk's answer, you could create your own extension method with a distinct name, in order to preserve the fluent syntax:

#r "nuget: OwaspHeaders.Core, 4.2.0"
open OwaspHeaders.Core.Extensions
open OwaspHeaders.Core.Models

type SecureHeadersMiddlewareConfiguration with
    member config.MyUseHsts(maxAge, includeSubDomains) =
        SecureHeadersMiddlewareBuilder.UseHsts(config, maxAge, includeSubDomains)

let config =
    SecureHeadersMiddlewareBuilder
        .CreateBuilder()
        .MyUseHsts(1200, false)
        .Build()

If you want to maintain the same default arguments, I think you probably have to do something like this instead:

type SecureHeadersMiddlewareConfiguration with
    member config.MyUseHsts(?maxAge, ?includeSubDomains) =
        match maxAge, includeSubDomains with
            | Some maxAge', Some includeSubDomains' ->
                SecureHeadersMiddlewareBuilder.UseHsts(config, maxAge', includeSubDomains')
            | Some maxAge', None ->
                SecureHeadersMiddlewareBuilder.UseHsts(config, maxAge')
            | None, Some includeSubDomains' ->
                SecureHeadersMiddlewareBuilder.UseHsts(config, includeSubDomains = includeSubDomains')
            | None, None ->
                SecureHeadersMiddlewareBuilder.UseHsts(config)

It's a bit ugly, but it will make the rest of your code nicer.

Both the above are good answers, another way would be to use a type alias, which keeps your code short and fluent and this can handle all default arguments too.

#r "nuget: OwaspHeaders.Core, 4.2.0"
open OwaspHeaders.Core.Extensions

type SHMB = SecureHeadersMiddlewareBuilder

let config = SHMB.UseHsts(SHMB.CreateBuilder(),1200,false).Build()
Related