Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Sep 17 14:16
    mrtank assigned #1200
  • Sep 17 14:16
    mrtank opened #1200
  • Sep 16 12:50
    granicz transferred #1166
  • Sep 16 10:31
    mrtank assigned #1166
  • Sep 14 07:29
    mdementyev starred dotnet-websharper/core
  • Sep 14 06:54
    myarichuk starred dotnet-websharper/core
  • Sep 14 06:14
    LayZeeDK starred dotnet-websharper/core
  • Sep 14 06:12
    pdabhiargus starred dotnet-websharper/core
  • Sep 13 11:58
    mrtank labeled #13
  • Sep 13 11:56
    mrtank assigned #13
  • Sep 13 11:55
    mrtank labeled #12
  • Sep 13 08:34
    mrtank assigned #2
  • Sep 13 08:34
    mrtank labeled #2
  • Sep 13 08:29
    mrtank closed #9
  • Sep 13 08:29
    mrtank labeled #9
  • Sep 13 08:29
    mrtank assigned #9
  • Sep 13 08:29
    mrtank assigned #9
  • Sep 13 08:28
    mrtank closed #8
  • Sep 13 08:28
    mrtank labeled #8
  • Sep 13 08:26
    Jand42 labeled #1116
Adam Granicz
@granicz
[<CompiledName "FSharpContent">]
type Content<'Endpoint> =
    | CustomContent of (Context<'Endpoint> -> Http.Response)
    | CustomContentAsync of (Context<'Endpoint> -> Async<Http.Response>)
I remember how this was introduced to shift everything to async, but I am wondering if this could now all be streamlined to a Task instead?
rbauduin
@rbauduin_gitlab
To generate links to an endpoint type, I use WebSharper.Sitelets.Context.Link. But in a Rpc function, I get the context with WebSharper.Web.Remoting.GetContext() which is of type WebSharper.Web.Context and doesn't have the Link method. Is there a typesafe way to generate a link to a Sitelet from a Rpc function?
10 replies
rbauduin
@rbauduin_gitlab
For context, this is what I'm doing: https://gitlab.com/myowndb/myowndb/-/blob/explorations/webui/Remoting.fs#L61
The RPC is sending a mail with a link to reset the account password. The link includes a token generated in the RPC. So generating the link should be done in the Rpc too.
rbauduin
@rbauduin_gitlab

I'm starting to use attr.classDyn, but actually attr.classDynPred would be more useful if it also took a view for the situation when the predicate is false. Now it sets the attr if the pred is true, and removes it if false. How do you best handle the situation where you want to set one value when the pred id true, and another when the pred is false. Now I use attr.classDyn and manage it manually, but I'm wondering if there's a better way than this:

let classMapper = fun b -> if b then BS.``text-success`` else BS.``text-danger``
// repeat these            
let lengthClass = lengthValid |> View.Map classMapper  
// later:
  div [attr.classDyn lengthClass]

I think that wiith an hypothetical classDynPredBoth it could become just:

  div [attr.classDynPredBoth lengthValid (View.Const BS.``text-success``) (View.Const  BS.``text-danger``)

Maybe it altready exists? I'll try and see if I can make it a helper in my app anyway :-)

3 replies
rbauduin
@rbauduin_gitlab
Javascript regexps support unicode, so it is possible to match string with an uppercase as explained here.
I'm trying to do it from websharper, but with no success. Anyone knowing how to do it?
Console.Log(RegExp("/\p{Lu}/u").Match("UPPER")
2 replies
rbauduin
@rbauduin_gitlab

I'm implementing password validators for ASP.Net so they handle unicode characters. Here is the one validating that the password has an uppercase letter:

    type HasUpper<'TUser when 'TUser : not struct>(t:I18n) =
        interface IPasswordValidator<'TUser> with
            member _.ValidateAsync(um:UserManager<'TUser>,user:'TUser,password:string) =
                async {
                    if PasswordValidators.hasUpper password then
                        return IdentityResult.Success
                    else
                        return IdentityResult.Failed( IdentityError(Code="NoUpper",Description=t.t("Password must have at least one uppercase letter")))

                }|> Async.StartAsTask

I will probably implement 3 or 4 others, having the same structure, but 3 differences (in addition to the name):

  • the error code
  • the error description
  • the PasswordValidators.* function
    I've seen websharper macros mentioned in an error I've had. Could macros help in my case to limit the boilerplate? Or should I just go and duplicate the code except for the 3 differences?
4 replies
rbauduin
@rbauduin_gitlab
What is the status of WebSharper.Forms? It's not available in the 5.0 packages, and I don't think it's used in the code generated by dotnet new websharper-web.
I will start work on forms related code in a data intensive app, and I'd rather know now if Websharper.Forms is the way to go or not. I also don't want to be stuck at WS 4. What do you advise? Embrace Websharper.Forms or avoid it ?
20 replies
steiner2001
@steiner2001

I'm implementing Conways Game of Life with ws.mvu for performance measuring and I ran into an issue. This is what my nodes look like:

div [
                on.click (fun _ _ -> dispatch (Check (x, y)))
                on.viewUpdate model (fun _ _ -> dispatch (Step (x, y)))
                attr.classDyn (tr.Map(fun x -> if x then "gol-box gol-triggered" else "gol-box"))
            ] [])

With Step (x, y) I'm changing the models (model: Grid: ((int int) bool), Triggered: bool) correct element (model.Grid[x width + y]) with switching its value. After that, with attr.classDyn I want to change the classes of the div based on the nodes new value, but with this implementation the model doesn't affect the classes - as far as I see. Can you advise me something to solve this problem?

1 reply
rbauduin
@rbauduin_gitlab

I'm writing some tests for a WS app, and I'm trying to start the app before the tests with

web.Program.BuildWebHost([||]).StartAsync(token)

The problem is that http://localhost:5000/Scripts/WebSharper/webws.js?h=1100870762 always returns a 404.
This is when I run ASPNETCORE_ENVIRONMENT=Development dotnet test
I put similar code in Program.fs:

web.Program.BuildWebHost([||]).StartAsync(token) |> Async.AwaitTask |> Async.RunSynchronously

and when I run it with ASPNETCORE_ENVIRONMENT=Development dotnet run, the problem doesn't occur. Any suggestion what could be the cause or how I can debug this?

10 replies
Adam Granicz
@granicz
steiner2001
@steiner2001
I'm updating Leaflet binding to the current version. Now working on Basic Types/Point
9 replies
Márton Garai
@mrtank
Booster thread
14 replies
rbauduin
@rbauduin_gitlab

When I install the package FSharp.Control.FusionTasks (see github), I get errors in my client async code:

WebSharper error FS9001: Type not found in JavaScript compilation: Microsoft.FSharp.Control.AsyncExtensionsModule

because the async extensions added by that package are not available in client side code. Is there a way to have these extensions only added to server side code's async{} ?

5 replies
pw242
@pw242

Hi, trying to work with ExtJs by replicating https://try.websharper.com/snippet/0000XW. Can't get the nuget package to work at all (ExtCfg isn't recognised). Tried to make my own WIG bindings but got nowhere (https://forums.websharper.com/topic/91004). I managed to use the [<Stub>] technology to establish a binding to the library.

[<Stub>]
    [<Name "Ext">]
    [<Require(typeof<Resources.ExtAll>)>]
    type Ext() =
        static member Date : Date = Unchecked.defaultof<_>

But I am not happy with this because I have to use a static member. In ExtJs, Ext is a singleton object, not a type/class per se. So my F# model does not really reflect the JS.
However if I try to use an instantiated object the binding fails, e.g. something like

    [<Stub>]
    [<Name "Ext">]
    [<Require(typeof<Resources.ExtAll>)>]
    let Ext : Ext= Unchecked.defaultof<_>
4 replies
rbauduin
@rbauduin_gitlab
FYI: WS5 release 77 - preview 1 let me compile my project on linux out of the box (end of lines issue is fixed). When I run the app though, it is not functional with no error logged (or I missed it...). For example, the forms are not displayed. It was working in 75 (after I manually fixed the new lines issue in wsfsc.sh)
3 replies
Adam Granicz
@granicz
you are right, 77 included metadata changes and broke the client helper, fix is being investigated - should be out shortly (will ping here)
Adam Granicz
@granicz
@pw242 I just responded to one of your Forums posts about Ext JS, feel free to ping me here if you need more help
Adam Granicz
@granicz
it would be awesome to have a WIG-based Ext JS binding out on GitHub
Adam Granicz
@granicz
the "enhanced" one I mentioned in my forum comment is generated from the documentation and its main feature is the SA integration, which we could slice off to a separate extension so the two could nicely coexist
(there is some very-very old documentation for the SA integration at https://developers.websharper.com/extensions/v4.x/fs/Sencha%20Architect)
Adam Granicz
@granicz
we have been discussing swagger schema generation for sitelets, i wonder if others have any ideas/suggestions for it here
currently, sitelets allow to pass all sorts of arbitrarily complex values on GET requests (so as part of the URL)
this makes the router way more delicate than a simple path specifier like "/book/%d"
also, not sure if swagger can describe those complex arguments either
has anyone encountered this before?
Adam Granicz
@granicz
so currently, given a sitelet, i see no way to extract the routes it can serve
one compromise would be to offer swagger schema generation for sitelets that are instantiated over a DU, assuming that all swagger info is coming from the type (and not weaved together via Sitelet.Content and other sitelet combinators, or custom/manually constructed routers/sitelets)
this would also mean that we restrict swagger schema to DU cases with simple arguments (so no records, unions, etc.)
however, this wouldn't address the most typical way in WebSharper to structure sitelets: using nested union types (for APIs, etc.)
so we would probably make the above restriction "DU cases with simple arguments or nested DUs"
thoughts?
1 reply
András Jankó
@Jand42

this would also mean that we restrict swagger schema to DU cases with simple arguments (so no records, unions, etc.)

I don't think so. Router/Sitelet.Infer supports nested types, unions with other unions and/or record for field types, so if we have logic thac creates OpenAPI json from an Endpoint type passed to Router/Sitelet.Infer, we can support all these.

Márton Garai
@mrtank

so in this documentation https://developers.websharper.com/docs/v4.x/fs/sitelets you mean

type EndPoint =
  | [<EndPoint "GET /">] Home
  | [<EndPoint "/api">] Api of ApiEndPoint

and ApiEndPoint =
  | [<EndPoint "GET /article">] GetArticle of int
  | [<EndPoint "POST /article">] PostArticle of int

example is the nested DU. If we can generate OpenApi doc from only Infer's output Sitelet<'T>, it is possible to merge these into one OpenApiPaths

András Jankó
@Jand42
What we might miss are combinators that take a lambda function, for example Sitelet.Filter, which allows only certain values through, possibly based on complex logic. Generated OpenAPI json won't be able to reflect this, so this can lead to 404's on requests that seem fine just by swagger definition
Adam Granicz
@granicz
There are many combinators and unless sitelets do internal bookkeeping there will always be missed endpoints. Hence my proposal to make this for DUs only
rbauduin
@rbauduin_gitlab
Not sure if it's related, but here's something that would be great to have in my case.
If I have an endpoint at url "/entities/352" which displays a page with a table listing entities of type 352, it would be great to easily publish a REST API so a GET /entities/352.json or GET /api/entities/352 would return the list of these entities in json format. Same for a POST /entities/352.json or POST /api/entities/352 to create a new entry, etc.
4 replies
rbauduin
@rbauduin_gitlab

I wanted to switch my app to WS5, but although it runs fine when I run the app with dotnet run, executing the startup code generated by the WS template which eventually call IWebHost.Run(); I encounter a problem in my test code, where the test setup code starts up the app by calling IWebHost.StartAsync(token).
The error I get is:

Exception: Error in InlineControl at /home/rb/gits/myowndb/app/webui/Site.fs: 57.22-57.78: Couldn't find translation of method web.Client.languageDropdown. The method or type should have JavaScript attribute or a proxy, and the assembly needs to be compiled with WsFsc.exe

which refers this code calling the client helper and the client code here.
When I manually run the app in the test environment (ASPNETCORE_ENVIRONMENT=Test dotnet run) I don't get this error.
I also didn't get this problem when WS4. I'm using WS5 79.
Is the way I start the app in my test code not working anymore with WS5?

the stack trace from a DeveloperExceptionPage:

    Microsoft.FSharp.Core.PrintfModule+PrintFormatToStringThenFail@1433.Invoke(string message) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\printf.fs
    WebSharper.Web.FSharpInlineControl.WebSharper.IRequiresResources.Requires(Info meta)
    Microsoft.FSharp.Collections.Internal+IEnumerator+map@75.DoMoveNext(ref b curr) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\seq.fs
    Microsoft.FSharp.Collections.Internal+IEnumerator+MapEnumerator<T>.System.Collections.IEnumerator.MoveNext() in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\seq.fs
    Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeOuter@273<T, TResult>(ConcatEnumerator<T, TResult> x, Unit unitVar0) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\seqcore.fs
    Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeInner@266<T, TResult>(ConcatEnumerator<T, TResult> x, Unit unitVar0) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\seqcore.fs
    Microsoft.FSharp.Collections.SetTreeModule.mkFromEnumerator<a>(IComparer<a> comparer, SetTree<a> acc, IEnumerator<a> e) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\set.fs
    Microsoft.FSharp.Collections.SetTreeModule.ofSeq<a>(IComparer<a> comparer, IEnumerable<a> c) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\set.fs
    WebSharper.Sitelets.ContentModule.writeResources<a>(Context ctx, IEnumerable<a> controls, FSharpFunc<RenderLocation, HtmlTextWriter> tw)
    WebSharper.Sitelets.ContentModule.getSeparateResourcesAndScripts<a>(Context ctx, IEnumerable<a> controls)
    WebSharper.Sitelets.ContextExtensions.GetSeparateResourcesAndScripts<?>(Context this, IEnumerable<?> controls)
    WebSharper.UI.Templating.Runtime.Server+write@813-2.Invoke(Context ctx, HtmlTextWriter w, bool r)
    WebSharper.UI.Elt.Write(Context ctx, HtmlTextWriter h, bool res)
    <StartupCode$WebSharper-UI>.$Doc.Server+Page@43-1.Invoke(Stream s)
    WebSharper.Sitelets.ContentHelper+writeResponseAsync@37-1.Invoke(MemoryStream _arg1)
    Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvoke<T, TResult>(AsyncActivation<T> ctxt, TResult result1, FSharpFunc<TResult, FSharpAsync<T>> part2) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\async.fs
    <StartupCode$WebSharper-Sitelets>.$Content+ToResponse@56.Invoke(AsyncActivation<Response> ctxt)
    <StartupCode$WebSharper-Sitelets>.$Content+Custom@439-1.Invoke(AsyncActivation<FSharpContent> ctxt)
    WebSharper.Sitelets.ContentModule+FromContext@241-4.Invoke(AsyncActivation<FSharpContent> ctxt)
    Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc<Unit, AsyncReturn> firstAction) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\async.fs
    Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
    Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
    Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
    Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
    Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware.Invoke(HttpContext context)
    Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
    Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
    Serilog.AspNetCore.RequestLoggingMiddleware.Invoke(HttpContext httpContext)
    Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
András Jankó
@Jand42
@rbauduin_gitlab Hm, it's probably got broken by my recent optimization to reduce Sitelets startup time, it currently reads metadata prepared by the compiler from the entry assembly which is not the sitelet project in your test case: https://github.com/dotnet-websharper/core/blob/websharper50/src/sitelets/WebSharper.Web/Shared.fs#L42-L43
quick workaround to try (but which might cause other problems possibly) is to make the test project a WebSharper project type web or bundle too...
otherwise we need to figure out how to best make assembly to look for sitelet metadata more flexible
rbauduin
@rbauduin_gitlab
There's no hurry at my side, I'd rather not make my test project a WebSharper project (after all it is not, it is just test code). Do you mean that this is something that could be left as is in the final release?
rbauduin
@rbauduin_gitlab
Maybe it would be possible to somehow provide a list of assemblies from which to read the metadata? In my case specifying it in an environment variable would be fine for example
András Jankó
@Jand42
@rbauduin_gitlab Having any module let static logic for something as important as runtime metadata load is just a relic from ASP.NET 4x times, I am looking into reworking it to have is instantiated via ASP.NET Core configuration, and then testing will become more flexible. I have created ticket dotnet-websharper/core#1197
rbauduin
@rbauduin_gitlab
ok, I've subscribed to the issue, but don't hesitate to let me know when something's available and I'll test it
rbauduin
@rbauduin_gitlab
I'm using WebSharper.Forms for a registration form, and a password reset form. Both forms have a password field and a password confirmation field. I extracted these fields definition in a function that I reuse in both forms, however for the render of the forms I have nearly similar code and I don't think I can do otherwise. See here and here. Am I doing things right? Is there a better way to augment a form (the set new password form) with a field (to get the registration form)?
6 replies
rbauduin
@rbauduin_gitlab

@Jand42 : I have tried to load the assembly from my tests, but I still get an error. Here's my code in the app:

            .UseWebSharper( fun builder -> builder.SiteletAssembly(Assembly.GetExecutingAssembly()) |> ignore)

but when I run the tests, I get

Exception: Error in InlineControl at /home/rb/gits/myowndb/app/webui/Site.fs: 59.22-59.78: Couldn't find translation of method web.Client.languageDropdown. The method or type should have JavaScript attribute or a proxy, and the assembly needs to be compiled with WsFsc.exe

In the ouput, I see Loaded hosting startup assembly "webws", which is the same as when using WS4.
Do I load the assembly in a wrong way?

For completeness: I also have this warning reported, but I have a similar warning with WS4 too:

/home/rb/gits/myowndb/app/webui/tests/unknown(1,1): warning FS3186: An error occurred while reading the F# metadata node at position 1 in table 'itycons' of assembly 'WebSharper.Core.JavaScript, Version=5.0.0.0, Culture=neutral, PublicKeyToken=451ee5fa653b377d'. The node had no matching declaration. Please report this warning. You may need to recompile the F# assembly you are using. [/home/rb/gits/myowndb/app/webui/tests/PlaywrightTests.fsproj]
16 replies
rbauduin
@rbauduin_gitlab
Is SlickGrid the recommended solution to display data tables with websharper? This will be the central functionality of my app, and choosing the right solution will be important. Any advice?
András Jankó
@Jand42
@rbauduin_gitlab I have tested a simple WebSharper server-client template with small modifications in Program class to allow integration testing, and this test:
[<Test>]
let Test1 () =
    let webAppFactory = new WebApplicationFactory<ClientServer.Startup>()
    let client = webAppFactory.CreateClient()
    async {
        let! resp = client.GetAsync("/") |> Async.AwaitTask
        resp.IsSuccessStatusCode |> should equal true
    }
    |> Async.StartAsTask
András Jankó
@Jand42

Then it was failing by default, but passed with your exact line

.UseWebSharper(fun builder -> builder.SiteletAssembly(Assembly.GetExecutingAssembly()) |> ignore)

I could not build your repo fully, have not tried Docker, only in Win, missing database.test.json (is there a script?). Which of your tests is still failing?