Live example:
http://lightswitchhelpwebsite.com/Demos/ThingsForSale.aspx
For an introductory article on LightSwitch, see:
http://lightswitchhelpwebsite.com/Blog/tabid/61/EntryId/12/Online-Ordering-System-An-End-To-End-LightSwitch-Example.aspx
Note: You must have
Visual Studio Professional, or higher, to perform all
the steps in this tutorial
You can download Visual Studio LightSwitch from this link:
http://www.microsoft.com/visualstudio/en-us/lightswitch
Putting Multiple LightSwitch Applications Into Your Website
Microsoft Visual Studio LightSwitch suffers from what I call the "full screen
limitation". LightSwitch wants to fill the entire screen, and it wants to manage
the roles and users. This is fine if you only have one application, however in
many situations, you want a LightSwitch application to be part of a group of
applications in a single portal. You want all applications to share the same
users, roles and database.
Unlike the article
Online Ordering, that describes a normal "LightSwitch only" deployment, this
article will explore the techniques used to deploy a LightSwitch application
inside a ASP.NET application that contains other applications. In this article,
DotNetNuke will be used, however, everything
here can be used in any ASP.NET application.
The key to integrating LightSwitch into an ASP.NET application, is to use
IFrames.
The Requirements
In this example, we will create an application that meets the following
requirements:
- Allow Registered Users (the Posters), the ability to create
Posts
of things they have for sale, without the need to post their email address
- Allow Anonymous Users (the Buyers) the ability to see the
Posts without
requiring them to have the Silverlight plug-in installed
- Allow the Buyers the ability to respond to a Post, and automatically
email the Poster
- Allow the Poster the ability to view and respond to all
communications sorted by Post
- Allow Administrators the ability to edit all data
This may not be considered a large application, but it would take a few days
effort. With LightSwitch, you can create the entire application in about an
hour.
Walk-Thru Of The 'Things For Sale' Application
You can try out the live Things For Sale application at this
link:
http://lightswitchhelpwebsite.com/Demos/ThingsForSale.aspx
When you are not logged-in, you will see a list of Posts
that you can browse.

You can click on a Post to send the Poster
a message.

When you log in, you will have the ability to create Posts,
and to see any Messages related to a Post (you will be emailed when a new
Message
is created for one of your Posts).

Also note, that there are a lot of other features such as
Concurrency Checking and
Automatic Ellipses that LightSwitch implements
automatically.
Creating The Application

You can download Visual Studio LightSwitch from this link:
http://www.microsoft.com/visualstudio/en-us/lightswitch
After installing it, use File, New Project
to create a LightSwitch application.

Double-click on Properties in the Solution
Explorer.

Set the application as a Web application.

Set it to use Forms Authentication.
Categories Table And Screen

Creating a table for Categories and a screen to edit them, is
a task that can be completed in under a minute.
Right-click on the Data Sources node in the
Solution Explorer, and select Add Table.

Click on the table name to change the name. Enter Category
for the name.

Create the table above.

Right-click on the Screens node, and select
Add Screen...

Create an Editable Grid Screen using Categories
(LightSwitch automatically 'pluralizes' the name of the table).

The screen will display.

Hit F5 to run the application.

We can now create Categories in the application.
Close your web browser to stop the application.
Create The Remaining Tables

Create a Post table with the schema above.

Create a Message table with the schema above.
Create Relationships

Open the Message table, and click the Relationship
button.

In the Add New Relationship box, enter the settings above.

Open the Post table.
In the Add New Relationship box, enter the settings above.

The relationships are complete.
Setting relationships is very important with LightSwitch. It
allows important features, such as allowing you to create screens, where the
Posts and the Messages related to the
Posts, always stay in sync, without requiring any code.
It is very rare for any Entity (table) to not have a
relationship to one or more other Entities.
Set Default Values On Record Creation

Open the Message table, and select Write Code, then
Message Created.
Change the method to the following:
partial void Message_Created()
{
this.MessageCreated = DateTime.UtcNow;
}
This will set the date for a Message when it is created.
Notice that we are using "UtcNow"
so that the time is recorded in Coordinated Universal Time (UTC) time. When we
display the time, we can convert it to the user's local time.

Open the Post table, and select Write Code, then
Post Updating.
Change the method to the following:
partial void Posts_Updating(Post entity)
{
entity.PostUpdated = DateTime.UtcNow;
}

Open the Post table, and select Write Code, then
Post Created.
Change the method to the following:
partial void Post_Created()
{
this.PostedBy = this.Application.User.Name;
this.PostCreated = DateTime.UtcNow;
this.PostUpdated = DateTime.UtcNow;
this.Active = true;
}
Note the line:
this.PostedBy = this.Application.User.Name;
This is all that is required to segment the data by user.
At run-time, the DotNetNuke site (or any ASP.NET site
running under Forms Authentication), will provide the username
for "this.Application.User.Name".
In a later step, we will use a PreProcess query to restrict
a user to only see their own Posts (and Messages).
Sending Emails

This application will require emails to be sent. Let's enable that
functionality now.
To do this, we will need to switch to File View.

In the Server project, add references to System.configuration
and System.Messaging.

Add a class called MailHelper.cs to the UserCode
folder of the Server project.
Use the following code:
using System.Net;
using System.Net.Mail;
using System.Configuration;
using System;
namespace LightSwitchApplication
{
public class MailHelper
{
private string _SMTPSendingEmailAddress { get; set; }
private string _SMTPServer { get; set; }
private string _SMTPUserId { get; set; }
private string _SMTPPassword { get; set; }
private int _SMTPPort { get; set; }
private bool _SMTPSSL { get; set; }
private string _MailFromName { get; set; }
private string _MailToEmail { get; set; }
private string _MailToName { get; set; }
private string _MailSubject { get; set; }
private string _MailBody { get; set; }
public MailHelper(
string SendFromName, string SendToEmail,
string SendToName, string Subject,
string Body)
{
_MailFromName = SendFromName;
_MailToEmail = SendToEmail;
_MailToName = SendToName;
_MailSubject = Subject;
_MailBody = Body;
_SMTPSendingEmailAddress = Convert.ToString(ConfigurationManager.AppSettings["SMTPSendingEmailAddress"]);
_SMTPServer = Convert.ToString(ConfigurationManager.AppSettings["SMTPServer"]);
_SMTPUserId = Convert.ToString(ConfigurationManager.AppSettings["SMTPUserID"]);
_SMTPPassword = Convert.ToString(ConfigurationManager.AppSettings["SMTPPassword"]);
_SMTPPort = Convert.ToInt32(ConfigurationManager.AppSettings["SMTPPort"]);
_SMTPSSL = Convert.ToBoolean(ConfigurationManager.AppSettings["SMTPSSL"]);
}
public void SendMail()
{
MailMessage mail = new MailMessage();
System.Net.Mail.MailAddress mailFrom =
new System.Net.Mail.MailAddress(_SMTPSendingEmailAddress, _MailFromName);
System.Net.Mail.MailAddress mailTo =
new System.Net.Mail.MailAddress(_MailToEmail, _MailToName);
var _with1 = mail;
_with1.From = mailFrom;
_with1.To.Add(mailTo);
_with1.Subject = _MailSubject;
_with1.Body = _MailBody;
SmtpClient smtp = new SmtpClient(_SMTPServer, _SMTPPort);
smtp.EnableSsl = _SMTPSSL;
smtp.Credentials =
new NetworkCredential(_SMTPUserId, _SMTPPassword);
smtp.Send(mail);
}
}
}

Click on the project name in the Solution Explorer, then
select Show All Files.

This will allow you to see the ServerGenerated project.
This project is created by LightSwitch and used when
LightSwitch is deployed as a web application. It is the place where we
will eventually place the .aspx files that will generate the
HTML pages. For now, we only want to add some entries to the Web.config
file:

This will allow us to easily change the SMTP Mail Server settings when the application is
deployed.

Switch back to Logical View.

Open the Message table, and select the
Messages_Inserted method.
Use the following code for the method (to send the email):
#region Messages_Inserted
partial void Messages_Inserted(Message entity)
{
string strSubject = "Message From ThingsForSale";
string strMessage = String.Format("{0}",
"This is a message From the Things For Sale program.")
+ Environment.NewLine + Environment.NewLine;
strMessage = strMessage + String.Format("Regarding the post '{0}'",
entity.Post.Description) + Environment.NewLine;
strMessage = strMessage + String.Format("This message was sent by {0}",
entity.NameFrom) + Environment.NewLine + Environment.NewLine;
strMessage = strMessage + String.Format("Message: {0}",
entity.MessageText) + Environment.NewLine;
MailHelper mailHelper =
new MailHelper(
entity.NameFrom,
entity.EmailTo,
entity.NameTo,
strSubject,
strMessage);
mailHelper.SendMail();
}
#endregion
Create The Posts And Messages Screen

In the Solution Explorer, right-click on the
Screens node and select Add Screen...

Create a List and Details Screen.
Note: because we created relationships between the tables,
we can enable Posts and Messages to be on the
same screen, by simply checking a box.

The screen will show.

When you run the application, you will be able to enter Posts
and Messages.
Deploy Application Into A DotNetNuke Website
Follow the directions here to deploy the application into a
DotNetNUke website:
Easy DotNetNuke LightSwitch Deployment.

We now have the basic layout illustrated above. The LightSwitch
application is running in an IFrame and has the same
Database Connection, MachineKey, and Forms
Cookie, so it is able to communicate with the DotNetNuke
site hosting it, and share user authentication.
For many applications, this is enough. In our example we need to determine if
a user is an Administrator or not, because we want to provide additional
features to Administrators.
We could simply add the DotNetNuke user and roles tables to
the LightSwitch application as external tables, but I have
found that this can sometimes cause the user table to lock (see
this link for more information).

Adding a WCF RIA Service prevents any locking issues.
Creating A WCF RIA Service
(note: you must have
Visual Studio Professional, or higher, to perform the
following steps)
(see this
link for official information on creating WCF RIA Services
for LightSwitch)

Add a New Project.

Create a new Class Library.

Right-click on the Class1.cs file that is created
and delete it.

Add a Entity Data Model...

Connect to the DotNetNuke database.

Normally we only need to add the vw_UserRoles view to
determine if a user is an Administrator or not.
However, we will also add the Category, Post,
and Message tables, because we will also use the Entity
Data Model for the .aspx (HTML) pages
that we will create in a later step.

Build the project.

Add a Domain Service Class.

We only need the vw_userRoles in the Domain Service
Class. Also, un-check Enable client access
for added security because we wont need it.

The Domain Service Class will be created.
Add [Query(IsDefault = true)] to the top of the method (that is
automatically created).

Save the file and Build Solution.

Right-click on the Data Sources node, and select
Add Data Source...

Select WCF RIA Service and click Next.
(do not be surprised if the box goes away and nothing happens for a long
time. Also the box may now be hidden behind the Visual Studio
main window)

Click Add Reference.

Select the Data Project and click OK.

Wait for the Domain Service Class to appear in the list box.
Sometimes it can take 1-2 minutes.
When it appears, select it, and click Next.

Select the Entity to use by checking it's box (in this case we want to use
the vw_UserRoles)
Don't bother entering anything for the Connection String
because we will set it in the Web.config manually.
Click Finish.

The data source will show up.

Copy the connection string from the App.config
of the data project.

Switch to File View, and open the Web.config,
and add the connection string.
Using The WCF RIA Service

To demonstrate how we can use our new WCF RIA Service, open
the EditableCategoriesGrid screen and select the
EditableCategoriesGrid_CanRun event.
Change the method to the following code:
partial void EditableCategoriesGrid_CanRun(ref bool result)
{
var WorkSpace = this.CreateDataWorkspace();
var UserInRole = (from DNNUser in WorkSpace.DNNDomainServiceData.vw_UserRoles
where DNNUser.Username == this.User.Name
where DNNUser.RoleName == "Administrators"
select DNNUser).FirstOrDefault();
result = (UserInRole != null);
}

Click on the project in the Solution Explorer.

This will allow you to select Publish.
Re-publish the application
You will have to redo all the changes you made to the web.config when you followed the
directions described in
Easy DotNetNuke LightSwitch Deployment because new things have been added
to the web.config when we created the WCF RIA Service.

When you run the application in the DotNetNuke website, only
an administrator will see the link to edit the Categories.
Enabling Security Using A Pre-Process Query
One of the requirements is that an administrator can see all Posts,
but a non-administrator can only see their own Posts (and
Messages).
Open the Posts Entity, and select Posts All
PreprocessQuery.
Change the code to the following:
partial void Posts_All_PreprocessQuery(ref IQueryable<Post> query)
{
if (this.Application.User.IsAuthenticated)
{
string UserName = this.Application.User.Name;
var WorkSpace = this.Application.CreateDataWorkspace();
var UserInRole = (from DNNUser in WorkSpace.DNNDomainServiceData.vw_UserRoles
where DNNUser.Username == UserName
where DNNUser.RoleName == "Administrators"
select DNNUser).FirstOrDefault();
if (UserInRole == null)
{
query = query.Where(x => x.PostedBy == this.Application.User.Name);
}
}
}
Modal Windows (PopUps)
Modal Windows (otherwise known as Popups)
are an important User Interface tool because the require the
user to complete the task set before them before doing anything else.
In this sample application we want Popups to show when a
user is viewing an existing Message or responding to a
Message.
There are other Popups, but they are created automatically
by LightSwitch.
Currently, when an existing Message is opened, it shows all
the fields like the image above.

We desire the PopUp to resemble the image above.
To do this, we will make our own PopUp and then override the
code that opens the current PopUp, to open our PopUp.
In the screen designer, select the Details Column, then
Add the Selected Item for Messages.

It will display.

Change the section to a Modal Window.

Change all the TextBoxes to Labels and
delete the remaining items.

Select the Modal Window, and note the name of the window.
Uncheck the Show Button box (otherwise LightSwitch
would show a button at the bottom of the screen to open the window).

Click on the Messages Data Grid, expand the Command
Bar, right-click on the Edit button, and
select Override Code.
Change the code to the following:
partial void MessagesEditSelected_Execute()
{
this.OpenModalWindow("Messages_SelectedItem");
}

Now if we select the Edit button it opens our custom Popup.
We will add a Respond button in the next step, that will
allow us to actually create a Message, as a response to a
Message entered in the HTML page (to be created in a later
step).
Note: To understand the next steps, it is suggested that you
read:
This Is How LightSwitch Does MVVM.

Switch to File View, and add a Reference,
in the Client project, to
System.Windows.Controls (this is so we can programmatically interact
with a PopUp as a ChildWindow).

Select Add Data Item...

Create a Local Property of type Message and call it
Message_Response.

It will show on the screen's "View Model" (see:
This Is How LightSwitch Does MVVM for an explanation of View Model).

Select the Details Column section, and add the
Message Response
property to the screen.

Change it to Modal Window.

The properties will show.

- Remove all the controls except the Name To,
Email To, and Message Text
- Change the Name To to a Label
- In the Properties of the Modal Window,
uncheck Show Button

Add a Button to the Command Bar of the Modal Window and call
it SaveResponse.

In the Properties for the Button, change the Display
Name to Save Message.

Right-click on the Button, and select Edit
Execute Code
Change the code to:
#region SaveResponse_Execute
partial void SaveResponse_Execute()
{
this.CloseModalWindow("Message_Response");
this.Save();
}
#endregion

Navigate up the object tree to the Command Bar for the
Messages Data Grid, and delete the Add button, and add a New Button.

Call it RespondToMessage.

Drag it to the top of the other two remaining buttons, and right-click on it and
select Edit Execute Code.
use the following code to create a new Message and open the
Popup,
also to detect when the PopUp is closed (when clicking the x in
the upper right corner of the Popup), and to remove any unsaved
Messages:
#region RespondToMessage_Execute
partial void RespondToMessage_Execute()
{
Message_Response = new Message();
Message_Response.Post = Posts.SelectedItem;
Message_Response.MessageBy = this.Application.User.Name;
Message_Response.NameFrom = Messages.SelectedItem.NameTo;
Message_Response.EmailFrom = Messages.SelectedItem.EmailTo;
Message_Response.NameTo = Messages.SelectedItem.NameFrom;
Message_Response.EmailTo = Messages.SelectedItem.EmailFrom;
this.OpenModalWindow("Message_Response");
this.FindControl("Message_Response").ControlAvailable +=
new EventHandler<ControlAvailableEventArgs>(PostsListDetail_ControlAvailable);
}
#endregion
#region PostsListDetail_ControlAvailable
void PostsListDetail_ControlAvailable(object sender, ControlAvailableEventArgs e)
{
ChildWindow window = (ChildWindow)e.Control;
window.Closed += new EventHandler(Message_Response_Closed);
}
#endregion
#region Message_Response_Closed
void Message_Response_Closed(object sender, EventArgs e)
{
ChildWindow window = (ChildWindow)sender;
if (!(window.DialogResult.HasValue))
{
foreach (Message message in this.DataWorkspace.ApplicationData.Details.GetChanges()
.AddedEntities.OfType<Message>())
{
message.Details.DiscardChanges();
}
}
}
#endregion

You will also need to add using System.Windows.Controls; to
the top of the class.
Creating HTML Pages

Switch to File View.
Add a Reference to System.configuration to the ServerGenerated project.

Add a .aspx page called PublicPage.aspx, and
use the following code for the code behind (please get the HTML
code from the download):
using DNNData;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text.RegularExpressions;
using System.Transactions;
using System.Web.UI;
using System.Web.UI.WebControls;
using LightSwitchApplication;
namespace ApplicationData.Implementation
{
public partial class PublicPage : System.Web.UI.Page
{
#region CurrentPage
public int CurrentPage
{
get
{
if (ViewState["CurrentPage"] == null)
{
return 1;
}
else
{
return (int)ViewState["CurrentPage"];
}
}
set
{
ViewState["CurrentPage"] = value;
}
}
#endregion
#region CurrentPostID
public int CurrentPostID
{
get
{
if (ViewState["CurrentPostID"] == null)
{
return -1;
}
else
{
return (int)ViewState["CurrentPostID"];
}
}
set
{
ViewState["CurrentPostID"] = value;
}
}
#endregion
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
GetPosts(true, CurrentPage);
}
}
#region GetPosts
private void GetPosts(bool FillCategories, int intPage)
{
List<DNNData.Category> lstCategories = new List<DNNData.Category>();
string _IntrinsicData = Convert.ToString(ConfigurationManager.ConnectionStrings["DotNetNuke5Entities"]);
DotNetNuke5Entities db = new DotNetNuke5Entities(_IntrinsicData);
int intCategoryID = -1;
if (!FillCategories)
{
intCategoryID = Convert.ToInt32(ddlCategories.SelectedValue);
}
if (FillCategories)
{
var colCatagories = (from Cat in db.Categories
select Cat).ToList();
DNNData.Category objCategory = new DNNData.Category();
objCategory.Id = -1;
objCategory.CategoryName = "All";
lstCategories.Add(objCategory);
foreach (var item in colCatagories)
{
lstCategories.Add(item);
}
ddlCategories.DataSource = lstCategories;
ddlCategories.DataBind();
}
var colPosts = from PST in db.Posts
select PST;
colPosts = colPosts.Where(x => x.Active == true);
if (intCategoryID != -1)
{
colPosts = colPosts.Where(x => x.Category.Id == intCategoryID);
}
colPosts =
colPosts.OrderByDescending(x => x.PostUpdated).
Skip(((intPage - 1) * 10)).Take(10);
gvPosts.DataSource = colPosts;
gvPosts.DataBind();
}
#endregion
#region ddlCategories_SelectedIndexChanged
protected void ddlCategories_SelectedIndexChanged(object sender, EventArgs e)
{
pnlMessage.Visible = false;
GetPosts(false, CurrentPage);
}
#endregion
#region btnLeft_Click
protected void btnLeft_Click(object sender, EventArgs e)
{
pnlMessage.Visible = false;
if (CurrentPage > 1)
{
CurrentPage--;
}
GetPosts(false, CurrentPage);
}
#endregion
#region btnRight_Click
protected void btnRight_Click(object sender, EventArgs e)
{
pnlMessage.Visible = false;
if (gvPosts.Rows.Count > 0)
{
CurrentPage++;
}
GetPosts(false, CurrentPage);
}
#endregion
#region gvPosts_RowCommand
protected void gvPosts_RowCommand(object sender, GridViewCommandEventArgs e)
{
LinkButton lnkButtton = (LinkButton)e.CommandSource;
CurrentPostID = Convert.ToInt32(lnkButtton.CommandArgument);
pnlMessage.Visible = true;
}
#endregion
#region btnSubmit_Click
protected void btnSubmit_Click(object sender, EventArgs e)
{
try
{
Transaction currentTrx = Transaction.Current;
Transaction.Current = null;
if (!IsValidEmail(txtEmail.Text))
{
lblError.Text = "Must use a valid Email";
return;
}
if (txtEmail.Text.Count() < 1)
{
lblError.Text = "Must enter a message";
return;
}
if (txtEmail.Text.Count() > 255)
{
lblError.Text = "Message must be less than 255 characters";
return;
}
string _IntrinsicData = Convert.ToString(ConfigurationManager.ConnectionStrings["DotNetNuke5Entities"]);
DotNetNuke5Entities db = new DotNetNuke5Entities(_IntrinsicData);
var DNNUser = (from PST in db.Posts
from vw_Users in db.vw_UserRoles
where PST.PostedBy == vw_Users.Username
where PST.Id == CurrentPostID
select vw_Users).FirstOrDefault();
DNNData.Message NewMessage = new DNNData.Message();
NewMessage.NameFrom = txtName.Text;
NewMessage.EmailFrom = txtEmail.Text;
NewMessage.NameTo = DNNUser.DisplayName;
NewMessage.EmailTo = DNNUser.Email;
NewMessage.MessageText = txtMessage.Text;
NewMessage.MessageCreated = DateTime.UtcNow;
NewMessage.Message_Post = CurrentPostID;
db.AddToMessages(NewMessage);
db.SaveChanges();
var PostInfo = (from PST in db.Posts
where PST.Id == CurrentPostID
select PST).FirstOrDefault();
string strSubject = "Message From ThingsForSale";
string strMessage = String.Format("{0}",
"This is a message From the Things For Sale program.")
+ Environment.NewLine + Environment.NewLine;
strMessage = strMessage + String.Format("Regarding the post '{0}'",
PostInfo.Description) + Environment.NewLine;
strMessage = strMessage + String.Format("This message was sent by {0}",
txtName.Text) + Environment.NewLine + Environment.NewLine;
strMessage = strMessage + String.Format("Message: {0}",
txtMessage.Text) + Environment.NewLine;
MailHelper mailHelper =
new MailHelper(
txtName.Text,
DNNUser.Email,
DNNUser.DisplayName,
strSubject,
strMessage);
mailHelper.SendMail();
lblError.Text = "Success";
txtMessage.Text = "";
}
catch (Exception ex)
{
lblError.Text = ex.Message;
}
}
#endregion
#region IsValidEmail
public static bool IsValidEmail(string strIn)
{
return Regex.IsMatch(strIn,
@"^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))" +
@"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$");
}
#endregion
}
}
Creating A Link To the HTML Page In LightSwitch

Add a Reference, in the Client project, to System.Windows.Browser

Switch to Logical View.
Add Screen...

Add a New Data Screen called PublicPage
with no Screen Data selected.

Select the PublicPage_Run method.
Change it to the following code:
partial void PublicPage_Run(ref bool handled)
{
Dispatchers.Main.Invoke(() =>
{
HtmlPage.Window.Navigate(new Uri("PublicPage.aspx", UriKind.Relative));
});
handled = true;
}
You will also need to add the following using statements to the class:
using Microsoft.LightSwitch.Threading;
using System.Windows.Browser;
We now need to ad the PublicPage.aspx to the build file, so
that LightSwitch will include it in the build.
Note: You will want to back up your entire solution before
performing the following steps:

Switch to File View, right-click on the LightSwitch project and select
Unload Project.

Right-click on the unloaded project and select Edit.

Add the following to the bottom of the _buildFile section:
<_BuildFile Include="ServerGenerated\PublicPage.aspx">
<SubFolder>
</SubFolder>
<PublishType>
</PublishType>
</_BuildFile>

Reload the project.

Now you can run the project and click on the Public Page
link...

... and navigate to the HTML page.
In your application, you will want to make the HTML page
available for your unauthenticated users.
The
live
demonstration on the LightSwitchHelpWebsite, has one IFrame
that is pointed directly at the PublicPage.aspx, and is only
shown to un-authenticated users. A second IFrame, enabled only
for Registered users, shows the normal LightSwitch application.
Finishing Touches

On the Posts screen, delete Posted By because it is set programmatically

However, notice that it still shows up on the automatically created
PopUp.

Open the Post Entity, and select the PostedBy field, then
un-check the Display by Default box.

The PopUp will no longer show the field.

On the Posts screen, set the Message Data Grid to Use Read-only Controls

Select the CanExecute Code for the Respond To
Message button.
Change the code to the following:
#region RespondToMessage_CanExecute
partial void RespondToMessage_CanExecute(ref bool result)
{
result = (Messages.SelectedItem != null);
}
#endregion
Do the same for the Message Edit button.
This causes the buttons to be disabled if there is no Message
selected.

Go into Properties for the project, set the Post
List Detail screen as the startup screen.
An Advanced LightSwitch Application
This demonstrates an advanced LightSwitch application.
However there is still a lot more to LightSwitch. For example, the entire UI can
be controlled using
Silverlight Custom Controls.
There are a ton of tutorials, tips, blogs, and forums at:
http://LightSwitchHelpWebsite.com
