This project is read-only.
Creating the Hello World sample application.

You have to be familiar with C# and ASP.NET to follow this walkthrough.
You need an ASP.NET IDE to create a web application fast and painless. You gone need a good XML editor to get around customizing LWAS configuration file.
I use Visual Web Developer 2010 Express and Notepad++.

Grab the core
Download LWAS minimal runtime package.
Unzip in a convenient location we're going to make a ASP.NET web application out of it.

Create the web application
I ask VWD to open the location where I unzipped the runtime package as a Local Filesystem Web Site. While doing it I dismiss the proposal to reconfigure the application with .NET 4.0, although we can go ahead and accept it.

At this stage if you run the web site it's gone give you a 404 File Not Found error cause it's looking for the login page. LWAS needs to have a user logged in to properly function.

Add a webform named login.aspx and plug the LWAS infrastructure into it. If you don't get this step right LWAS won't boot and the Authenticator service used bellow won't work.
There are two steps to plug LWAS into an ASP.NET page:
1 Register the infrastructure namespace. Insert the following at the top of the page
<%@ Register Assembly="LWAS" Namespace="LWAS.Infrastructure" TagPrefix="LWASI" %>
2 Declare the LWAS Manager right bellow the <form .. > opening tag. Your code should look like
    <form id="form1" runat="server">
    <LWASI:Manager ID="webPartManager" runat="server" />

Now that we have LWAS plugged let's continue to build the login page. Put a login control in login.aspx.
Then go into the codebehind file and declare the usage of LWAS security namespace
using LWAS.Infrastructure.Security;
Finally add the event handler for the authentication event of login control
    protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
        e.Authenticated = Authenticator.Instance.Verify(this.Login1.UserName, this.Login1.Password);
Now you can run your web site and use "admin" as username and "admin" as password. It should give you another 404 error saying the default.aspx page cannot be found. Those credentials worked cause they're shipped with the LWAS runtime minimal configuration and are stored into App_Data\config\users.xml file. Note the password is not kept in clear text but it's hashed.

The default.aspx page
Create another webform named default.aspx and plug LWAS into it as above.
We gone have more LWAS components on this page. Because LWAS components are WebParts they must be declared as such, that is in a WebPartZone.
Register two more namespaces as bellow
<%@ Register Assembly="LWAS" Namespace="LWAS.WebParts" TagPrefix="LWASWP" %>
<%@ Register Assembly="LWAS" Namespace="LWAS.WebParts.Zones" TagPrefix="LWASWPZ" %>
We need ScriptManager on this page so let's add it right before Manager. Your code should look like
    <form id="form1" runat="server">
    <asp:ScriptManager ID="scriptManager" runat="server" ScriptMode="Release" />
    <LWASI:Manager ID="webPartManager" runat="server" EnableAuthorizer="true" />
You may use ToolkitScriptManager as well instead of asp built-in one though you have to register the Ajax Control Toolkit namespace at the top of the page.
Proceed with adding the WebParts and their zones after the Manager declaration as follows
    <LWASWPZ:TableZone ID="Workspace" runat="server" PersonalizationProviderID="personalizationProvider">
            <LWASWP:FormViewWebPart ID="greetingsForm" runat="server" Title="Greetings" />

    <asp:WebPartZone ID="Infrastructure" runat="server" Visible="false">
            <LWASWP:WorkFlowManagerWebPart ID="workflowManagerWebPart" runat="server" Initialization="1001" Completion="1001" />

    <asp:WebPartZone ID="Providers" runat="server" Visible="false">
            <LWASWPZ:TableZonePersonalizationProvider runat="server" ID="personalizationProvider" />

We use TableZone to host a Form webpart to showcase the usage of a special LWAS webparts zone that is layout aware. In a more complex scenario we would have more webparts on the screen and would like to arrange them in a way. The TableZone stores it's layout in a separate component TableZonePersonalizationProvider.

Notice the form webpart is not shown upon running the website. That's because we have no layout defined for the hosting TableZone and that's what we do next.

Automagically generate a LWAS screen
An interesting feature of the WebParts framework is that it (re)creates the personalization definition whenever is missing. So if the framework finds a so called static webpart (defined in the page like we did above) it will generate the personalization for it and tries to store that personalization. That's where the LWAS xml personalization service kicks in, gets the personalization and stores it as xml files. For the last sections of this walkthrough we going to deal a lot with this xml files.

But first we have to switch a setting of the LWAS core. By default the ability to create screens on the fly comes turned off, mostly because you have to set write permissions on the web site - most people don't like that part. We already have write permission on our walkthrough website and the web server built into VWD (Cassini) will use them.

To switch on the creation of LWAS screens on the fly go to lwas.settings.config and set to True the DESIGN setting
        Switch DESIGN setting to True to have LWAS automatically creating a default configuration file 
          for each new SCREEN requested through QueryString
        Granted the ASP.NET has write permissions to the location of the .aspx file invoked
  <add key="DESIGN" value="True"/>
Now run your web site, pass the login screen and go to default.aspx page. Notice that a new file default.xml apears in the same location with the page.

Multiple LWAS screens are hosted by a single ASP.NET webform page
What's all this talk about more than one LWAS screen while we're on the same ASP.NET page? Well, having DESIGN=true if you go to /your-web-site/default.aspx?screen=onescreen you will have a onescreen.xml file generate in your web site root. While changing the screen QueryString value to something new, you will have new screen definition generated.

All the screens generate from the same page will have the same LWAS services as defined in the .aspx part. From that on it's up to us to make each screen unique by configuring the aspects of the LWAS components and thus changing the fields shown in our form or its behaviour (flows).

First steps into a LWAS screen configuration
We should have a screen definition generated for our default page name default.xml. Let's open in up.
Navigate to
<personalization version="">
  <part id="personalizationProvider">
    <property name="Configuration" sensitive="false" scope="0">
      <value type="LWAS.Infrastructure.Configuration.Configuration, LWAS">
Change the contents of this node as belllow
        <Configuration configKey="">
            <section configKey="Workspace">
                <element configKey="0">
                  <attributes />
                    <element configKey="0">
                        <attribute configKey="part" value="greetingsForm" type="System.String, mscorlib, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
                      <elements />
            <section configKey="TabZone">
              <elements />
            <section configKey="Infrastructure">
              <elements />
Run your web site go to default.aspx page and notice the text "Greetings". That's the title of our LWAS.FormViewWebPart as defined in the .aspx. Have a look back to the xml node we changed. See how some more <attribute> nodes where created next to <attribute configKey="part" ... /> ? Those attributes apply to the html table cell (<TD>) containing our form webpart.

If you go in default.aspx file and change the title of greetingsForm to something else it will not be updated on the screen. That's because after a screen configuration has been created the webparts personalized properties are loaded from there. So if you want to change the form title you should change this xml node
<personalization version="">
  <part id="greetingsForm">
    <property name="Title" sensitive="false" scope="0">
      <value type="System.String, mscorlib, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089">
Notice there are more personalized properties for our form webpart and that's the same for every webpart in our default.xml file.

Configure the form template
Most if not all webparts personalization stored in a LWAS screen configuration file will have a Configuration property
<property name="Configuration" sensitive="false" scope="0">
That's the xml node we need to change to have our LWAS webpart doing what we are up to. For our form webpart in default xml we want to obtain the same screen as in the Hello World sample so let's change the <part id="greetingsForm"> configuration property to the xml from this file

That's quite a lengthy piece of xml! Truth is it could be considerably smaller for the sake of usability but the system is not intended to be configured directly in xml files (though it surely can). For our walkthrough we will do just fine editing those xml files.

That been said run your web site and witness the shaping of our form webpart. Now it has a nice instructions label, a text box and a button much like in this picture bellow
greetings form.png

However pressing the button changes nothing and we want our greetings displayed instead of the instructions text.

Before implementing this logic, have a look at a few important properties we have defined previously for the controls of our form webpart. These properties where set in the xml from from this file. Find the node
                    <element configKey="0">
                        <attribute configKey="type" value="Label" type="System.String" />
That's how the greetings label was introduced in the form webpart. This node has a descendant that defines the Text property for our label
                        <element configKey="Text">
                            <attribute configKey="member" value="Text" type="System.String" />
                            <attribute configKey="value" value="Hi there! Please enter your greetings in the box bellow" type="System.String" />
                            <attribute configKey="pull" value="Greetings" type="System.String" />
                            <attribute configKey="push" value="Greetings" type="System.String" />
                          <elements />
See where the greetings instruction text comes from? Notice the two sibling attributes "pull" and "push" next to it. Those attributes are special to LWAS, they tell the system that the value of the Text property of greetings label should be kept in a system storage under the key "Greetings". They actually tell the system to bind the property to that storage key in two ways: read from the storage at the proper time and write to the storage at a later time so that meanwhile the value can change by user input or by flow.

Have a look at the xml node defining the text box.
                    <element configKey="0">
                        <attribute configKey="type" value="Text" type="System.String" />
It should have a descendant element "Text" much like the Label with "pull" and "push" attributes pointing to "UserGreetings" key in LWAS storage.

There's a final interesting property in our form webpart configuration. Is this "CommandName" that appears as descendant node of our Button element.
                        <element configKey="CommandName">
                            <attribute configKey="member" value="CommandName" type="System.String" />
                            <attribute configKey="value" value="update greetings" type="System.String" />
This setting tells the webpart containing the button (the form webpart in our case) to launch the message (a milestone in LWAS terms) "update greetings" upon button click.

Let's put it all together now.

Configure the "Show my greetings" flow
What we have to do next is tell the system to copy from it's storage the value under the key "Greetings" and store it under "UserGreetings" key so that it will be "pulled" by the Label and displayed on the page. And we want this to happen when the user clicks the button, that is when the system gets the message "update greetings" from the form webpart.

For this to happen we going to configure a special LWAS component that makes available to us the LWAS service responsible with any automation, logic or movement (flow in LWAS terms) in our application: the WorkflowManagerWebPart. Locate the configuration node of this webpart as bellow
<personalization version="">
  <part id="workflowManagerWebPart">
    <property name="Configuration" sensitive="false" scope="0">
Replace the configuration node with the xml from this file

Run your web site, go to default.aspx enter a text of your choice into the text box and press the button.
This is what I got
greetings form working.png

Congratulations on your first LWAS screen!

More about LWAS flows
If you're wondering what's going on into a flow configuration here's the crush course.

All the flows in LWAS can have zero or more conditions and can contain zero or more transits. Basically conditions are milestones, i.e. messages like the "update greetings" above. Some milestones are built into the system, some may be defined by us. Likewise some are triggered by the system and some by user action. A transit is a very simple movement of data from a source to a destination as
greetingsForm.Data.Greetings = greetingsForm.Data.UserGreetings

Read it mathematically, i.e greetingsForm.Data.Greetings is the destination.
Both source and destination may be empty all together or one of them - in which case the system stores the data from the source or puts back in a destination the value read previously from a source.

A source or destination can be a member of a webpart like bellow
                            <element configKey="destination">
                                <attribute configKey="id" value="greetingsForm" type="System.String" />
                                <attribute configKey="member" value="CurrentItem.Data.Greetings" type="System.String" />
                              <elements />
                            <element configKey="source">
                                <attribute configKey="id" value="greetingsForm" type="System.String" />
                                <attribute configKey="member" value="CurrentItem.Data.UserGreetings" type="System.String" />
                              <elements />
Obviously only the source can also be an absolute value like
                            <element configKey="source">
                                <attribute configKey="value" value="These are my greetings" type="System.String" />
                              <elements />

A flow can do more than passing data around, it could trigger an action on the destination or source webpart of each of its transits. This is possible due to the convention taken by the system to have all webparts methods accesible through public properties (getters and setters) and to read them parameters from the context available.
For example a transit like bellow (in which "view" is a value source)
greetingsForm.Command = view

will trigger the form save action which in our case will display a message saying the form was saved and will put the form in read-only mode. To make it writable again issue the command "edit", either in a transit
greetingsForm.Command = edit

or as a button message

Last edited Sep 23, 2013 at 11:04 AM by t1b1c, version 21