comment
WebSharper 4.1.2 is now available on NuGet, and as a vsix installer on the WebSharper website.
It contains enhancements to the EndPoint
attribute and C# routing as well as fixes for JSON serialization and remoting of F# Map
and Set
values.
Documentation: WebSharper 4.1 for C# and WebSharper 4.1 for F#.
The release notes are also found on GitHub.
New features
- WebSharper for C# now supports syntax introduced in C# 7.2:
in
arguments andref readonly
returns, non-trailing named arguments, numeric literals with leading underscores,private protected
.
Fixes/improvements
- WebSharper build errors and warnings in F# projects now show up correctly in Errors window and as squiggly underlines.
- Fixed deserializing an empty
Set
value sent to aRemote
function. Map
andSet
values with any key type can now be serialized into JSON withJson.Serialize
. Maps are stored as a flat list of key/value pairs.Map<string>
still serializes to a single JSON object.- C# inferred routers now respect HTTP methods same as F#: declared either by the
Method
attribute or likeEndPoint("POST /post")
- Multiple
EndPoint
attributes can be used on types and members. Equivalently, theEndPoint
attribute can be passed multiple string arguments. In the case of multiple attributes, they can be ordered by setting theorder
parameter of theEndPoint
attibute contructor. - C# subclasses used in inferred routers have the option to declare the full route to parse/write, not inheriting from base class by having
inheritRoute: false
on anEndPoint
attribute, EndPoint "/"
can be used on a union case with fields (for example another union, allowing breaking up a big endpoint definition into multiple union types)- Decoding/encoding string values by
Router.Infer
(andRouter.rString
) are now using the same logic as WebSharper 4.0: any non-alphanumeric character replaced to~xx
or~uxxxx
. This ensures that string values are recovered properly and are passing standard URL correctness checks.
Example for C# routing
A C# class hierarchy can define an inferred router:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
[JavaScript, EndPoint("/", "/home")] public class Home { [EndPoint("/article/{Id}")] public class Article : Home { public int Id; [EndPoint("/page/{Page}")] [EndPoint("/article-page/{Id}/{Page}", order: 1, inheritRoute: false)] public class Page : Article { public int Page; } } public static Router<Home> Router = InferRouter.Router.Infer<Home>(); }
Then Home.Router
will be able to parse these routes:
1 2 3 4 5 6 7 8 9 10
/ /home => new Home() /article/1 /home/article/1 => new Home.Article { Id = 1 } /article/1/page/2 /home/article/1/page/2 /article-page/1/2 (because inheritRoute is false, it is re-defining whole route) => new Home.Article.Page { Id = 1, Page = 2 }
The first of these paths is the canonical form that will be used for writing links.
See the details of how to use a router to serve a site and create links here under "Using the router".