65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 IFrames 将 Visual Studio LightSwitch 应用程序集成到现有网站中

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.77/5 (22投票s)

2011年6月13日

Ms-PL

13分钟阅读

viewsIcon

101794

downloadIcon

1008

一个高级 LightSwitch 教程,涵盖预处理查询、电子邮件、弹出窗口、WCF RIA 服务和 HTML 页面

实时示例

有关 LightSwitch 的入门文章,请参阅

注意:您必须拥有 Visual Studio Professional 或更高版本,才能执行本教程中的所有步骤。

您可以从此链接下载 Visual Studio LightSwitch

将多个 LightSwitch 应用程序放入您的网站

Microsoft Visual Studio LightSwitch 存在我称之为“全屏限制”的问题。LightSwitch 希望填满整个屏幕,并且希望管理角色和用户。如果您只有一个应用程序,这没关系,但是有很多情况下,您希望 LightSwitch 应用程序成为单个门户中一组应用程序的一部分。您希望所有应用程序共享相同的用户、角色和数据库。

与描述正常“LightSwitch 仅部署”的文章 Online Ordering 不同,本文将探讨将 LightSwitch 应用程序部署到包含其他应用程序的 ASP.NET 应用程序中的技术。在本文中,将使用 DotNetNuke,但是本文中的所有内容都可以用于任何 ASP.NET 应用程序。

LightSwitch 集成到 ASP.NET 应用程序中的关键是使用 IFrames

要求

在此示例中,我们将创建一个满足以下要求的应用程序

  • 允许注册用户发帖人)能够创建他们要出售的物品的帖子,而无需发布他们的电子邮件地址
  • 允许匿名用户买家)能够查看帖子,而无需他们安装 Silverlight 插件
  • 允许买家回复帖子,并自动发送电子邮件给发帖人
  • 允许发帖人查看和回复所有按帖子排序的通信
  • 允许管理员编辑所有数据

这可能不是一个大型应用程序,但可能需要几天的时间。使用 LightSwitch,您可以在大约一个小时内创建整个应用程序。

“待售物品”应用程序的演练

您可以在此链接尝试实时待售物品应用程序

当您未登录时,您将看到可以浏览的帖子列表。

您可以点击帖子发帖人发送消息。

登录后,您将能够创建帖子,并查看与帖子相关的任何消息(当您的帖子收到新消息时,您将收到电子邮件)。

另请注意,LightSwitch 会自动实现许多其他功能,例如 并发检查自动省略

创建应用程序

您可以从此链接下载 Visual Studio LightSwitch

安装后,使用文件新建项目来创建 LightSwitch 应用程序。

解决方案资源管理器中双击 属性

将应用程序设置为Web 应用程序。

将其设置为使用表单身份验证

类别表和屏幕

创建类别表和编辑它们的屏幕,这项任务可以在一分钟内完成。

右键单击解决方案资源管理器中的数据源节点,然后选择添加表

单击表名更改名称。输入Category作为名称。

创建上面的表。

右键单击屏幕节点,然后选择添加屏幕...

使用Categories创建一个可编辑网格屏幕(LightSwitch 会自动“复数化”表名)。

屏幕将显示。

F5运行应用程序。

我们现在可以在应用程序中创建类别

关闭您的网页浏览器以停止应用程序。

创建剩余的表

创建一个具有上述架构的Post表。

创建一个具有上述架构的Message表。

创建关系

打开Message表,然后单击Relationship按钮。

添加新关系框中,输入上面的设置。

打开Post表。

添加新关系框中,输入上面的设置。

关系已完成。

设置关系对于 LightSwitch 非常重要。它允许重要功能,例如创建屏幕,其中与 Posts 相关的 PostsMessages 始终保持同步,而无需任何代码。

任何 Entity(表)与一个或多个其他 Entities 没有关系的情况非常罕见。

设置记录创建时的默认值

打开Message表,然后选择编写代码,然后选择 Message Created

将方法更改为以下内容

         partial void Message_Created()
        {
            this.MessageCreated = DateTime.UtcNow;   
        }

这将设置创建 Message 时的日期。请注意,我们使用的是“UtcNow”,因此时间以协调世界时 (UTC) 记录。显示时间时,我们可以将其转换为用户的本地时间。

打开Post表,然后选择编写代码,然后选择 Post Updating

将方法更改为以下内容

         partial void Posts_Updating(Post entity)
        {
            entity.PostUpdated = DateTime.UtcNow;
        }

打开Post表,然后选择编写代码,然后选择 Post Created

将方法更改为以下内容

         partial void Post_Created()
        {
            this.PostedBy = this.Application.User.Name;
            this.PostCreated = DateTime.UtcNow;
            this.PostUpdated = DateTime.UtcNow;
            this.Active = true;
        }

请注意该行

this.PostedBy = this.Application.User.Name;

这就是按用户分割数据所需的所有内容。

在运行时,DotNetNuke 站点(或任何在表单身份验证下运行的 ASP.NET 站点)将为“this.Application.User.Name”提供用户名。

在后续步骤中,我们将使用 PreProcess 查询来限制用户只能查看他们自己的 Posts(和 Messages)。

发送电子邮件

此应用程序需要发送电子邮件。现在让我们启用此功能。

为此,我们需要切换到文件视图

Server 项目中,添加对 System.configurationSystem.Messaging 的引用。

Server 项目的 UserCode 文件夹中添加一个名为 MailHelper.cs 的类。

使用以下代码

// Adapted from:
// http://www.paulspatterson.com/technology/lightswitch/
//   microsoft-lightswitch-sending-emails-from-the-client/#more-2896

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);
        }
    }
}

单击解决方案资源管理器中的项目名称,然后选择显示所有文件

这将允许您看到 ServerGenerated 项目。

此项目由 LightSwitch 创建,并在 LightSwitch 部署为 Web 应用程序时使用。这是我们将最终放置用于生成 HTML 页面的 .aspx 文件的位置。目前,我们只需要在 Web.config 文件中添加一些条目

这将使我们在部署应用程序时能够轻松更改 SMTP 邮件服务器设置。

切换回逻辑视图

打开Message表,然后选择 Messages_Inserted 方法。

为该方法使用以下代码(用于发送电子邮件)

        #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;

            // Create the MailHelper class created in the Server project.
            MailHelper mailHelper =
                new MailHelper(
                    entity.NameFrom,
                    entity.EmailTo,
                    entity.NameTo,
                    strSubject,
                    strMessage);

            // Send Email
            mailHelper.SendMail();
        }
        #endregion

创建帖子和消息屏幕

解决方案资源管理器中,右键单击屏幕节点并选择添加屏幕...

创建一个列表和详细信息屏幕。

注意:由于我们在表之间创建了关系,因此可以通过勾选一个框来使帖子消息显示在同一个屏幕上。

屏幕将显示

运行应用程序时,您将能够输入帖子消息

将应用程序部署到 DotNetNuke 网站

在此处遵循有关将应用程序部署到 DotNetNUke 网站的说明: Easy DotNetNuke LightSwitch Deployment

我们现在有了上面所示的基本布局。LightSwitch 应用程序运行在 IFrame 中,并具有相同的数据库连接MachineKeyForms Cookie,因此它能够与托管它的 DotNetNuke 站点通信并共享用户身份验证。

对于许多应用程序来说,这就足够了。在我们的示例中,我们需要确定用户是否是管理员,因为我们希望为管理员提供额外的功能。

我们可以简单地将 DotNetNuke 用户和角色表添加到 LightSwitch 应用程序作为外部表,但我发现这有时会导致用户表锁定(请参阅 此链接了解更多信息)。

添加 WCF RIA Service 可以防止任何锁定问题。

创建 WCF RIA 服务

(注意:您必须拥有 Visual Studio Professional 或更高版本,才能执行以下步骤。)

(请参阅 此链接了解有关为 LightSwitch 创建 WCF RIA Services 的官方信息。)

添加新项目

创建一个新的类库

右键单击创建的 Class1.cs 文件并删除它。

添加实体数据模型...

连接到DotNetNuke数据库。

通常,我们只需要添加 vw_UserRoles 视图来确定用户是否是管理员。

但是,我们还将添加 CategoryPostMessage 表,因为我们还将在后续步骤中创建的 .aspxHTML)页面中使用实体数据模型

生成项目。

添加域服务类

我们只需要 Domain Service Class 中的 vw_userRoles。此外,取消选中启用客户端访问以增加安全性,因为我们不需要它。

将创建域服务类

[Query(IsDefault = true)] 添加到(自动创建的)方法的顶部。

保存文件并生成解决方案

右键单击数据源节点,然后选择添加数据源...

选择WCF RIA Service然后单击下一步

(如果框消失且长时间没有发生任何事情,请不要感到惊讶。另外,框现在可能隐藏在Visual Studio主窗口后面。)

单击添加引用

选择数据项目然后单击确定

等待域服务类出现在列表框中。有时需要 1-2 分钟。

出现时,选择它,然后单击下一步

通过选中其框来选择要使用的实体(在这种情况下,我们要使用 vw_UserRoles)。

请勿在连接字符串中输入任何内容,因为我们将在 Web.config 中手动设置它。

点击**完成**。

数据源将显示。

从数据项目的 App.config 中复制连接字符串

切换到文件视图,然后打开 Web.config,然后添加连接字符串

使用 WCF RIA 服务

为了演示如何使用我们新的 WCF RIA Service,请打开 EditableCategoriesGrid 屏幕并选择 EditableCategoriesGrid_CanRun 事件。

将方法更改为以下代码

        partial void EditableCategoriesGrid_CanRun(ref bool result)
        {
            // Must be an Administrator for this link to show            
            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);       
        }

单击解决方案资源管理器中的项目。

这将允许您选择发布

重新发布应用程序。

您必须重做在遵循 Easy DotNetNuke LightSwitch Deployment 中的说明时对 web.config 所做的所有更改,因为在创建 WCF RIA Service 时,web.config 中添加了新内容。

当您在 DotNetNuke 网站中运行应用程序时,只有管理员才能看到编辑类别的链接。

使用预处理查询启用安全性

其中一项要求是管理员可以看到所有帖子,而非管理员只能看到他们自己的帖子(和消息)。

打开Posts实体,然后选择Posts All PreprocessQuery

将代码更改为以下内容

         partial void Posts_All_PreprocessQuery(ref IQueryable<Post> query)
        {
            // Only run this PreProcess Query if user is Authenticated
            if (this.Application.User.IsAuthenticated)
            {
                string UserName = this.Application.User.Name;

                // Connect to DotNetNuke Data
                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 User is not an Administrator 
                // The User can only see their own posts
                if (UserInRole == null)
                {
                    query = query.Where(x => x.PostedBy == this.Application.User.Name);
                }
            }
        }

模态窗口(弹出窗口)

模态窗口(也称为弹出窗口)是一个重要的用户界面工具,因为它们要求用户在执行其他任何操作之前完成指定的任务。

在此示例应用程序中,我们希望在用户查看现有消息或回复消息时显示弹出窗口

还有其他弹出窗口,但它们由 LightSwitch 自动创建。

当前,当打开现有消息时,它会显示所有字段,如上图所示。

我们希望弹出窗口类似于上图。

为此,我们将创建自己的弹出窗口,然后覆盖打开当前弹出窗口的代码,以打开我们的弹出窗口

在屏幕设计器中,选择详细信息列,然后添加消息选定项

它将显示。

将该部分更改为模态窗口

将所有文本框更改为标签并删除其余项。

选择模态窗口,并记下窗口的名称。取消选中显示按钮框(否则 LightSwitch 会在屏幕底部显示一个按钮来打开窗口)。

单击消息数据网格,展开命令栏,右键单击编辑按钮,然后选择覆盖代码

将代码更改为以下内容

         partial void MessagesEditSelected_Execute()
        {
            this.OpenModalWindow("Messages_SelectedItem");
        }

现在,如果我们选择编辑按钮,它将打开我们的自定义弹出窗口

我们将在下一步添加一个回复按钮,该按钮将允许我们实际创建一条消息,作为对 HTML 页面(将在后续步骤中创建)中输入的消息的回复。

注意:要理解后续步骤,建议您阅读: This Is How LightSwitch Does MVVM

切换到文件视图,并在 Client 项目中添加对 System.Windows.Controls引用(以便我们可以以编程方式将 PopUp 作为 ChildWindow 进行交互)。

选择添加数据项...

创建一个类型为 Message本地属性,并将其命名为 Message_Response

它将显示在屏幕的“视图模型”上(请参阅: This Is How LightSwitch Does MVVM 以了解视图模型的解释)。

选择详细信息列部分,并将消息响应属性添加到屏幕。

将其更改为模态窗口

属性将显示。

  • 删除除收件人姓名收件人电子邮件消息文本之外的所有控件
  • 收件人姓名更改为标签
  • 模态窗口属性中,取消选中显示按钮

模态窗口命令栏添加一个按钮,并将其命名为 SaveResponse

按钮属性中,将显示名称更改为保存消息

右键单击按钮,然后选择编辑执行代码

将代码更改为

         #region SaveResponse_Execute
        partial void SaveResponse_Execute()
        {
            this.CloseModalWindow("Message_Response");
            this.Save();
        } 
        #endregion

导航到消息数据网格命令栏,删除添加按钮,然后添加一个新按钮

将其命名为 RespondToMessage

将其拖到其他两个剩余按钮的顶部,然后右键单击它并选择编辑执行代码

使用以下代码创建新的 Message 并打开弹出窗口,还可以检测弹出窗口何时关闭(单击弹出窗口右上角的 x 时),并删除任何未保存的 Messages

         #region RespondToMessage_Execute
        partial void RespondToMessage_Execute()
        {
            // Create a new Message
            Message_Response = new Message();

            //Set the Post
            Message_Response.Post = Posts.SelectedItem;

            // Set Email defaults
            Message_Response.MessageBy = this.Application.User.Name;

            // these values are from the currently selected Message
            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");

            // Wire up an event to detect when the Modal window is closed
            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))
            {
                // Remove unsaved records            
                foreach (Message message in 
                         this.DataWorkspace.ApplicationData.Details.GetChanges()
                    .AddedEntities.OfType<Message>())
                {
                    message.Details.DiscardChanges();
                }
            }
        }
        #endregion

您还需要将 using System.Windows.Controls; 添加到类的顶部。

创建 HTML 页面

切换到文件视图

ServerGenerated 项目添加对 System.configuration引用

添加一个名为 PublicPage.aspx.aspx 页面,并为代码隐藏使用以下代码(请从下载中获取HTML代码)

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)
        {
            // Collections to hold the final results
            List<DNNData.Category> lstCategories = new List<DNNData.Category>();

            // Connect to DotNetNuke Data
            string _IntrinsicData = Convert.ToString
                  (ConfigurationManager.ConnectionStrings["DotNetNuke5Entities"]);
            DotNetNuke5Entities db = new DotNetNuke5Entities(_IntrinsicData);

            int intCategoryID = -1;

            // Get selected category
            if (!FillCategories)
            {
                intCategoryID = Convert.ToInt32(ddlCategories.SelectedValue);
            }

            if (FillCategories)
            {
                // execute query
                var colCatagories = (from Cat in db.Categories
                                     select Cat).ToList();

                // Add an All option
                DNNData.Category objCategory = new DNNData.Category();
                objCategory.Id = -1;
                objCategory.CategoryName = "All";
                lstCategories.Add(objCategory);

                // Add Categories
                foreach (var item in colCatagories)
                {
                    lstCategories.Add(item);
                }

                // We now have the results - bind then to the dropdown
                ddlCategories.DataSource = lstCategories;
                ddlCategories.DataBind();
            }

            // Get Posts

            // create query
            var colPosts = from PST in db.Posts
                           select PST;

            // Get active posts
            colPosts = colPosts.Where(x => x.Active == true);

            // Get Category
            if (intCategoryID != -1)
            {
                colPosts = colPosts.Where(x => x.Category.Id == intCategoryID);
            }

            // Do paging
            colPosts =
                colPosts.OrderByDescending(x => x.PostUpdated).
                Skip(((intPage - 1) * 10)).Take(10);

            // We now have the results - bind then to the dropdown
            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;

                // Validate
                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;
                }

                // Connect to DotNetNuke Data
                string _IntrinsicData = Convert.ToString
                       (ConfigurationManager.ConnectionStrings["DotNetNuke5Entities"]);
                DotNetNuke5Entities db = new DotNetNuke5Entities(_IntrinsicData);

                // Get the information for the user who made the Post
                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();

                // Create New Message
                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();

                // Get the information for the Post
                var PostInfo = (from PST in db.Posts
                                where PST.Id == CurrentPostID
                                select PST).FirstOrDefault();

                // Send Email

                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;

                // Create the MailHelper class created in the Server project.
                MailHelper mailHelper =
                    new MailHelper(
                        txtName.Text,
                        DNNUser.Email,
                        DNNUser.DisplayName,
                        strSubject,
                        strMessage);

                // Send Email
                mailHelper.SendMail();


                lblError.Text = "Success";

                // Clear fields
                txtMessage.Text = "";
            }
            catch (Exception ex)
            {
                lblError.Text = ex.Message;
            }
        }
        #endregion

        #region IsValidEmail
        public static bool IsValidEmail(string strIn)
        {
            // Return true if strIn is in valid e-mail format.
            // From: http://msdn.microsoft.com/en-us/library/01escwtf.aspx
            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
    }
}

在 LightSwitch 中创建指向 HTML 页面的链接

Client 项目中添加对 System.Windows.Browser引用

切换到逻辑视图

添加屏幕...

添加一个名为 PublicPage新数据屏幕,不选择屏幕数据

选择 PublicPage_Run 方法。

将其更改为以下代码

        partial void PublicPage_Run(ref bool handled)
        {
            // Set handled to 'true' to stop further processing.
            Dispatchers.Main.Invoke(() =>
            {
                HtmlPage.Window.Navigate(new Uri("PublicPage.aspx", UriKind.Relative));
            });

            handled = true;
        }

您还需要将以下 using 语句添加到类中

using Microsoft.LightSwitch.Threading;
using System.Windows.Browser;

现在我们需要将 PublicPage.aspx 添加到生成文件中,以便 LightSwitch 将其包含在生成中。

注意:您将希望在执行以下步骤之前备份整个解决方案

切换到文件视图,右键单击LightSwitch项目并选择卸载项目

右键单击已卸载的项目并选择编辑

将以下内容添加到 _buildFile 部分的底部

    <_BuildFile Include="ServerGenerated\PublicPage.aspx">
          <SubFolder>
          </SubFolder>
          <PublishType>
          </PublishType>
      </_BuildFile>

重新加载项目。

现在您可以运行项目并单击公共页面链接...

...并导航到 HTML 页面。

在您的应用程序中,您将希望使 HTML 页面对未经验证的用户可用。

LightSwitchHelpWebsite 上的实时演示有一个直接指向 PublicPage.aspxIFrame,并且仅显示给未经验证的用户。第二个 IFrame,仅对注册用户启用,显示正常的 LightSwitch 应用程序。

收尾工作

帖子屏幕上,删除发帖人,因为它是在编程方式设置的。

但是,请注意它仍然显示在自动创建的弹出窗口上。

打开Post实体,然后选择PostedBy字段,然后取消选中默认显示框。

弹出窗口将不再显示该字段。

帖子屏幕上,将消息数据网格设置为使用只读控件

选择回复消息按钮的CanExecute Code

将代码更改为以下内容

        #region RespondToMessage_CanExecute
        partial void RespondToMessage_CanExecute(ref bool result)
        {
            // Must have a Message Selected
            result = (Messages.SelectedItem != null);
        } 
        #endregion

消息编辑按钮执行相同的操作。

这会导致按钮在未选择 Message 时被禁用。

转到项目的属性,将帖子列表详细信息屏幕设置为启动屏幕。

高级 LightSwitch 应用程序

这演示了一个高级 LightSwitch 应用程序。但是,LightSwitch 还有很多内容。例如,可以使用 Silverlight 自定义控件控制整个 UI。

© . All rights reserved.