UserSession is essentially a thin wrapper around ASP.NET Forms authentication. Thus, when using protected sitelets, be sure to set this up in your Web.Config:

1
2
3
4
<configuration>
  <system.web>
    <authentication mode="Forms"/>
    ...
By on 2/14/2012 1:16 AM ()

This was the bit that tripped me up - it might be worth noting that (at least when running locally) you always get a user back when this isn't set, and the user can't be set using UserSession - I lost quite a lot of time trying to work out why, until I spotted the Sample project had this in the config file.

By on 2/19/2012 5:13 AM ()

Did you have to add anything to the config other than

1
<authentication mode="Forms"/>

I still can't get this to work and I'm not sure what else to try. I'm hoping to recommend WebSharper to my employer, but forms authentication will have to work for them to replace ASP.NET.

By on 2/22/2012 7:15 AM ()

I wonder - using the same Web.config, can you use forms authentications from regular ASP.NET files?

It doesn't seem to be a problem with WebSharper as much as with IIS/ASP.NET configurations (perhaps someone uninstalled a necessary feature from IIS?).

By on 2/22/2012 7:32 AM ()

I tried your suggestion and forms authentication works. The only difference between the config files being the following, which I had to add to the ASP.NET project:

1
2
3
4
5
<forms loginUrl="~/Login.aspx"/> <!-- under authentication -->

<authorization>
  <deny users="?"/>
</authorization>

I don't need the authorization section in WebSharper, do I? I tried adding it and couldn't even access the login page afterward.

I'm sorry if I'm asking dumb questions. I'm not a web developer, but I thought this would be easier.

Did you see my prior comment: I can see the authentication cookie and the redirect in the login response. However, the target of the redirect responds with 301 Moved Permanently. That makes me think the sitelet is configured wrong. I copied it from the article referenced above and haven't found any other examples of using UserSession to which I could compare it.

There's some other weirdness with my application too (perhaps related?). When I replace

1
Sitelet.Protect filter <| Sitelet.Content "/protected" Action.About AboutPage

with just

1
Sitelet.Content "/protected" Action.About AboutPage

that is, I un-protect it, it still redirects to the login page. (I'm using About and AboutPage where the article uses Clock/ClockPage.) I've rebuilt the solution, verified the build succeeded, checked the last modified time of the .js and .dll files, and restarted IIS--everything seems to be working.

Here's the complete sitelet, in case you can spot something incorrect:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    let Main =
      let home = 
          Sitelet.Content "/" Action.Home HomePage
 
      // An automatically inferred sitelet created for the basic parts of the application.
      let basic =
          Sitelet.Infer <| fun action ->
              match action with
              | Action.Home ->
                  HomePage
              | Action.Login action->
                  LoginPage action
              | Action.Logout ->
                  // Logout user and redirect to home
                  UserSession.Logout ()
                  Content.Redirect Action.Home
              | Action.About ->
                  Content.ServerError
 
      // A sitelet for the protected content that requires users to log in first.
      let authenticated =
          let filter : Sitelet.Filter<Action> =
              {
                  VerifyUser = fun _ -> true
                  LoginRedirect = Some >> Action.Login
              }
 
//          Sitelet.Protect filter <|
          Sitelet.Content "/protected" Action.About AboutPage
 
      // Compose the above sitelets into a larger one.
      [
          home
          authenticated
          basic
      ]
      |> Sitelet.Sum
By on 2/22/2012 9:10 AM ()

BTW, the WebSharper installer comes with a "WebSharper 2.4 Sample Web Application (Sitelets)" template that uses a similar setup with login/logout/protected content. Can you check that this sample application works for you?

By on 2/22/2012 3:24 PM ()

The samples were the first place I looked. I searched both of them (Html5 and Basic) for "Protect" and found nothing. Should there be another sample? Or can UserSession be employed a different way?

By on 2/23/2012 7:21 AM ()

I was referring to the VS template and not the samples.

By on 2/23/2012 11:07 AM ()

The sample sitelet template works fine. I diffed all the files in my project with those in the template and can't spot the difference. So...I started over using the template. The first thing I tried to do is protect a second page (the site will ultimately consist of dozens of protected pages). I tried protecting the Contact page following the example of Protected. However, if I click Contact on the menu, and log in, it doesn't redirect to the contact page. If I click on Protected, it works fine. Could you point me to a minimal example of protecting multiple pages? Apparently I'm doing something wrong.

By the way, the login URL is Login/Some/Contact and I'm randomizing the contact link in the menu, just like Protected. The login widget also shows I'm logged in. I guess I'm still overlooking something.

Thanks for all your help.

By on 2/23/2012 8:05 PM ()

Hi Daniel, I tried the same as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    let EntireSite =
        ...
        // 1. The Contact case is now handled elsewhere
        let basic =
            Sitelet.Infer <| fun action ->
                match action with
                ...
                | Action.Contact
                | Action.Protected ->
                    Content.ServerError

        // 2. Protect Protected and Contact with the same filter
        let authenticated =
            let filter : Sitelet.Filter<Action> =
                {
                    VerifyUser = fun _ -> true
                    LoginRedirect = Some >> Action.Login
                }

            [
                Sitelet.Protect filter <|
                    Sitelet.Content "/protected" Action.Protected Pages.ProtectedPage
                Sitelet.Protect filter <|
                    Sitelet.Content "/contact" Action.Contact Pages.ContactPage
            ]
            |> Sitelet.Sum
        // Compose the above sitelets into a larger one.
        [
            home
            authenticated
            basic
        ]
        |> Sitelet.Sum

And added URL randomization to the Contact link - this is needed because browsers try to be too smart with caching:

1
2
3
4
5
6
7
8
9
10
11
12
    let Template title main : Content<Action> =
        let menu (ctx: Context<Action>)=
            let ( ! ) x = ctx.Link x
            [
                    "Contact"   => (RandomizeUrl <| !Action.Contact)
                    "Protected" => (RandomizeUrl <| !Action.Protected)
                   ...
            ]
            ...
        Templates.Main.Main (Some title)
            { ...
            }

At this point, both resources are protected - I can't get to them unless I log in. I tested it in FF and Opera, works as expected in both. I also deployed the application (on IIS 6) on a public URL for your testing:
[link:test.intellifactorylabs.com].

Hope this helps.

By on 2/24/2012 3:19 AM ()

Thanks very much, Adam. I think caching was the problem. I turned on Cache > Always refresh from server in IE dev tools and it started working. I appreciate all your help.

By on 2/24/2012 7:52 AM ()

When you say "redirects to the login page", do you mean /protected (the sitelet page) or Login.aspx (the page you specified in your Web.Config)?

By on 2/22/2012 1:56 PM ()

Sorry, I wasn't clear. When I click on the link to /protected from the home page, it still redirects to the Login form (~/Login/Some/About in this case) when the call to Sitelet.Protect is omitted.

Does WebSharper use the login URL from the config file? I've been assuming it gets it from LoginRedirect on the filter.

By on 2/22/2012 2:24 PM ()

Right, it doesn't use the URL from the config file - unless your URL falls back to a non-sitelet-based page that happens to require authentication.

By on 2/22/2012 3:33 PM ()

After adding the config section, it's still not allowing access to protected content once logged in. Is there anything else I could do to troubleshoot?

Another oddity: every request continues to redirect to the login page even though I've removed the Login sitelet and all calls to Protect.

I wonder if this is a problem unique to using the VS dev web server.

By on 2/14/2012 7:59 PM ()

Then it seems that the server is still using an old application. If you are suing VS dev web server, make sure it is stopped (right-click on the icon in the tray bar, then stop) and then start again.

Also - be sure (in the Output window in Visual Studio) that the build succeeds. Sometimes you might miss the failure, and think the site was updated while it actually wasn't.

By on 2/14/2012 10:25 PM ()

I checked that the VS dev server was stopped and that the build succeeded (yes to both). I thought I'd try running in IIS, so that one's a fresh deployment (we can ignore the problems in VS dev--IIS is where it ultimately has to live). Static content renders fine (running in IIS) but my formlet doesn't appear at all. The JS files appear to be loading, so I'm not sure what's happening. Any troubleshooting tips?

By on 2/15/2012 7:15 AM ()

Is Firebug reporting any errors during loading the page? If dynamic content doesn't appear, it's usually a sign that either the sitelet handler is not configured properly, or that some of the core JS files are not loaded. Both should surface in Firebug.

By on 2/15/2012 3:46 PM ()

No, Sir. There is nothing in the Firebug console. The JS files appear to be served up, but they're empty. They're definitely not empty on disk. Any idea how that could happen?

Just figured it out: the static content handler was missing. The form renders now, so I'm back to the problem of being unable to access protected content after logging in. I've added the authentication config section.

By on 2/15/2012 7:26 PM ()

Are cookies enabled?

By on 2/16/2012 12:48 PM ()

Yes. And I've tried it in IE, FF, and Chrome. This is running locally

EDIT: A bit more info: I checked the logs and the authentication ticket is being created. After logging in, the redirect URL is requested, but the response is 301 Moved Permanently (Location=/Login). Does that mean the sitelet is configured incorrectly? As I mentioned in an earlier post, it's copied directly from the article.

By on 2/16/2012 3:03 PM ()

Ah, I didn't know this--thanks. Are there API docs for WebSharper? I only found a quick reference for formlets on the website, but nothing covering the entire API.

By on 2/14/2012 8:41 AM ()

There is also the WebSharper Manual. We'll clean up the WebSharper site shortly to make this more visible.

By on 2/14/2012 2:11 PM ()

I noticed the manual (and it's good) but I was looking specifically for API documentation (a la MSDN).

By on 2/14/2012 2:29 PM ()

Some of the assemblies are listed here (though I suspect these are old assemblies, at least several months old): [link:apistack.net].

By on 2/14/2012 10:45 AM ()

Thanks. That's a start.

By on 2/14/2012 12:09 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper