You are here:   Blog
Register   |  Login

LightSwitch News

 

Apr 10

Written by: Michael Washington
4/10/2012 9:33 PM  RssIcon

image

Visual Studio LightSwitch (In Visual Studio 11 Beta) allows you to access your LightSwitch application via OData. This provides access to the security and business rules of your LightSwitch application.

This article is a continuation of the article: Calling LightSwitch 2011 OData Using Server Side Code. In that article only reading the OData source was covered. In this article we will cover Creating, Reading, Updating, and Deleting (otherwise known as CRUD). We will also use JQuery Mobile and target the sample application to work with mobile devices. This is done only so that we can create a small application to easily present the relevant CRUD operations.

The Application

image

When the LightSwitch application runs, navigate to MobileMenu.aspx page and you will be presented with a login menu.

Note: If using Internet Explorer 9 in “compatibility mode” the login won’t work so turn it off for testing. I did not detect any problems with any mobile devices.

 

image

If a user is an Administrator they will see all Orders, otherwise they will only see (and be able to edit) their own orders.

image image

Clicking on an Order displays the details.

To remove an item, set the Quantity to 0 and click Save.

Clicking the Delete button allows an Order to be deleted.

A non-administrator will not be able to delete an Order (this is by design).
image image
Clicking on the dropdown at the bottom of the Order details table allows you to choose a Product to add. Entering a Quantity and clicking Save adds the Product to the Order.
image image

The validation, including the messages, are generated by LightSwitch. Error codes are also returned if you need to craft more user friendly validation errors.

The Business Layer

image

The only difference in the LightSwitch code between this example and the one in: Calling LightSwitch 2011 OData Using Server Side Code is that the CanDelete methods were implemented on the FlowerShopOrder and FlowerShopOrderDetails entities to prevent any non Administrator from deleting:

 

        partial void FlowerShopOrders_CanDelete(ref bool result)
        {
            result = this.Application.User.HasPermission(Permissions.SecurityAdministration);
        }
        partial void FlowerShopOrderDetails_CanDelete(ref bool result)
        {
            result = this.Application.User.HasPermission(Permissions.SecurityAdministration);
        }

 

The ASP.NET Web Pages

image

The remainder of the application is in the ASP.NET web pages that we can access in the File View.

image

All the pages are contained in the Server / Mobile folder.

The Android.aspx page was covered in the article: Communicating With LightSwitch Using Android App Inventor.

The OrderEdit.aspx page was added for this tutorial, and the existing Login.aspx page and MobileMenu.aspx pages were altered for this tutorial.

The Login Page

image

The Login.aspx page was altered to the following code to implement the JQuery Mobile framework that optimizes the page for mobile devices:

 

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="LightSwitchApplication.Login" %>
<!DOCTYPE html>
<html>
<head id="Head1" runat="server">
    <title>Mobile Login</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
    <script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script>
</head>
<body>
    <form id="form1" runat="server">
    <div data-role="page" class="type-interior">
        <div data-role="header" data-theme="b">
            <h1>Mobile Menu</h1>
        </div>
        <!-- /header -->
        <div data-role="content">
            <asp:login runat="server" id="ctrlLogin" onauthenticate="ctrlLogin_Authenticate">
                <LayoutTemplate>
                    <table border="0" cellpadding="1" cellspacing="0" 
                        style="border-collapse:collapse;" width="100%">
                        <tr>
                            <td>
                                <table border="0" cellpadding="0" width="100%">
                                    <tr>
                                        <td data-role="fieldcontain">
                                            <asp:Label ID="UserNameLabel" runat="server" 
                                                AssociatedControlID="UserName">User Name:</asp:Label>
                                            <asp:TextBox ID="UserName" runat="server"></asp:TextBox>
                                            <asp:RequiredFieldValidator ID="UserNameRequired" runat="server" 
                                                ControlToValidate="UserName" ErrorMessage="User Name is required." 
                                                ToolTip="User Name is required." 
                                                ValidationGroup="MainLogin">*</asp:RequiredFieldValidator>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td data-role="fieldcontain">
                                            <asp:Label ID="PasswordLabel" runat="server" 
                                                AssociatedControlID="Password">Password:</asp:Label>
                                            <asp:TextBox ID="Password" runat="server" TextMode="Password"></asp:TextBox>
                                            <asp:RequiredFieldValidator ID="PasswordRequired" runat="server" 
                                                ControlToValidate="Password" ErrorMessage="Password is required." 
                                                ToolTip="Password is required." 
                                                ValidationGroup="MainLogin">*</asp:RequiredFieldValidator>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <asp:CheckBox ID="RememberMe" runat="server" Text="Remember me next time." />
                                        </td>
                                    </tr>
                                    <tr>
                                        <td align="left" style="color:Red;">
                                            <asp:Literal ID="FailureText" runat="server" EnableViewState="False"></asp:Literal>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td align="left" data-role="fieldcontain">
                                            <asp:Button ID="LoginButton" runat="server" CommandName="Login" Text="Log In" 
                                                ValidationGroup="MainLogin" data-ajax="false" data-icon="star" data-theme="b" />
                                            <a data-ajax="false" data-icon="star" data-role="button" href="MobileMenu.aspx">
                                            Cancel</a>&nbsp;</td>
                                    </tr>
                                    <tr>
                                        <td align="left">
                                            &nbsp;</td>
                                    </tr>
                                </table>
                            </td>
                        </tr>
                    </table>
                </LayoutTemplate>
            </asp:login>
        </div>
        <!-- /content -->
    </div>
    <!-- /page -->
    </form>
</body>
</html>

 

This is the code behind in Login.aspx.cs:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace LightSwitchApplication
{
    public partial class Login : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // When a user first comes to this page log them out
            if (this.Request.QueryString["logoff"] != null)
            {
                if (this.Request.QueryString["logoff"] == "true")
                {
                    FormsAuthentication.SignOut();
                }
            }
        }
        protected void ctrlLogin_Authenticate(object sender, AuthenticateEventArgs e)
        {
            if (Membership.ValidateUser(ctrlLogin.UserName, ctrlLogin.Password))
            {
                // Set the forms authentication cookie that will be used in the OData requests
                FormsAuthentication.SetAuthCookie(ctrlLogin.UserName, true); 
                e.Authenticated = true;
                Response.Redirect("~/MobileMenu.aspx");
            }
            else
            {
                e.Authenticated = false;
                ctrlLogin.FailureText = "Login failed";
            }
        }
    }
}

 

Mobile Menu Page

image

The MobileMenu.aspx page was altered to the following code:

 

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="MobileMenu.aspx.cs" 
    Inherits="LightSwitchApplication.Mobile.MobileMenu" %>
<!DOCTYPE html> 
<html>
	<head>
    <title>Orders</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1"> 
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
    <script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script>
</head>
<body>
    <form id="form1" runat="server">
    <div data-role="page" class="type-interior">
        <div data-role="header" data-theme="b">
            <h1>Orders</h1>
        </div>
        <!-- /header -->
            <div data-role="content">
                <asp:datalist class="content-primary" id="gvOrders" style="width: 100%" runat="server">
                   <ItemTemplate>
                    <ul data-role="listview" data-inset="true" data-theme="c">
			            <li><a data-ajax="false" href='<%# Eval("HyperLink") %>'>
				            <h3><asp:Label runat="server" Text='<%# Eval("OrderName") %>' /></h3>
				            <p><strong><asp:Label runat="server" Text='<%# Eval("OrderDate") %>' /></strong></p>
			            </a></li>
                    </ul>        
                   </ItemTemplate>  
                </asp:datalist>
                <br />
                    <asp:hyperlink id="lnkLogOff" runat="server" navigateurl="~/Login.aspx?logoff=true"
                        data-role="button" data-ajax="false" data-icon="star" data-theme="b" text="Log Off" />
            </div>
            <!-- /content -->
        </div>
        <!-- /page -->
    </form>
</body>
</html>

 

The MobileMenu.aspx.cs page was altered to the following code:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.VisualBasic;
namespace LightSwitchApplication.Mobile
{
    public partial class MobileMenu : System.Web.UI.Page
    {
        #region BaseSiteUrl
        public static string BaseSiteUrl
        {
            get
            {
                HttpContext context = HttpContext.Current;
                string baseUrl = context.Request.Url.Scheme 
                    + "://" 
                    + context.Request.Url.Authority 
                    + context.Request.ApplicationPath.TrimEnd('/') + '/';
                return baseUrl;
            }
        }
        #endregion
        protected void Page_Load(object sender, EventArgs e)
        {
            if (User.Identity.IsAuthenticated) // Logged in
            {
                ShowOrders();
            }
            else // Not Logged In
            {
                Response.Redirect("~/Login.aspx");
            }
        }
        #region ShowOrders
        private void ShowOrders()
        {
            // Create DataContext
            ODataServiceReference.ApplicationData objApplicationData =
                new ODataServiceReference.ApplicationData(
                    new Uri(string.Format(@"{0}applicationdata.svc/", BaseSiteUrl)));
            // Query OData source
            var result = from FlowerShopOrders in objApplicationData.FlowerShopOrders
                             .Expand(x => x.FlowerShopCustomer)
                             .Expand(x => x.FlowerShopOrderDetail)
                         select FlowerShopOrders;
            // Collection to hold Orders
            List<OrderInfo> colOrderInfo = new List<OrderInfo>();
            // Loop thru orders
            foreach (var item in result)
            {
                // Get the Order Total
                double dblOrderTotal = 0.00d;
                // Create a new DataContext
                ODataServiceReference.ApplicationData objApplicationData2 =
                    new ODataServiceReference.ApplicationData(
                        new Uri(string.Format(@"{0}applicationdata.svc/", BaseSiteUrl)));
                // Query OData source
                var objOrderDetails = from OrderDetails in objApplicationData2.FlowerShopOrderDetails
                                           .Expand(x => x.FlowerShopProduct)
                                      where OrderDetails.FlowerShopOrder.Id == item.Id
                                      select OrderDetails;
                // Loop thru order details to get order total
                foreach (var OrderDetail in objOrderDetails)
                {
                    dblOrderTotal = dblOrderTotal 
                        + Convert.ToDouble((OrderDetail.FlowerShopProduct.Price * OrderDetail.Quantity));
                }
                // Create new Order object
                OrderInfo objOrderInfo = new OrderInfo();
                objOrderInfo.OrderID = item.Id;
                objOrderInfo.OrderName =
                    String.Format("[{0}] {1}, {2} - ${3}",
                    item.Id,
                    item.FlowerShopCustomer.LastName,
                    item.FlowerShopCustomer.FirstName,
                    dblOrderTotal);
                objOrderInfo.OrderDate = item.OrderDate;
                objOrderInfo.HyperLink = String.Format(@"OrderEdit.aspx?Id={0}", item.Id);
                // Add the order object to the final collection
                colOrderInfo.Add(objOrderInfo);
            }
            // Bind entire collection to GridView
            gvOrders.DataSource = colOrderInfo;
            gvOrders.DataBind();
        }
        #endregion
        #region OrderInfo
        public class OrderInfo
        {
            int _OrderID;
            public int OrderID
            {
                get { return _OrderID; }
                set { _OrderID = value; }
            }
            string _OrderName;
            public string OrderName
            {
                get { return _OrderName; }
                set { _OrderName = value; }
            }
            DateTime _OrderDate;
            public DateTime OrderDate
            {
                get { return _OrderDate; }
                set { _OrderDate = value; }
            }
            string _HyperLink;
            public string HyperLink
            {
                get { return _HyperLink; }
                set { _HyperLink = value; }
            }
        }
        #endregion
    }
}

 

The Order Edit Page

image

The OrderEdit.aspx page displays a single order, allows Order Detail items to be added, and for Orders to be deleted.

This is the code for the OrderEdit.aspx page:

 

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="OrderEdit.aspx.cs" 
    Inherits="LightSwitchApplication.Mobile.OrderEdit" %>
<!DOCTYPE html>
<html>
<head>
    <title>Order Details</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.css" />
    <script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.0.1/jquery.mobile-1.0.1.min.js"></script>
    <style type="text/css">
        table
        {
            width: 100%;
        }
            table caption
            {
                text-align: center;
            }
            table thead th
            {
                text-align: left;
                border-bottom-width: 1px;
                border-top-width: 1px;
            }
            table th, td
            {
                text-align: center;
                padding: 6px;
            }
        ul
        {
            width: 100%;
            margin-left: 0px;
            padding: 0px;
        }
            ul li
            {
                list-style-type: none;
                border-bottom: 1px dashed gray;
                margin-top: 10px;
            }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div data-role="page" class="type-interior">
        <div data-role="header" data-theme="b">
            <h1>
            <asp:label id="lblOrderHeader" runat="server" />
            </h1>
        </div>
        <!-- /header -->
        <div data-role="content">
            <asp:gridview id="gvOrderDetails" runat="server" autogeneratecolumns="False"
                datakeynames="Id" horizontalalign="Center" data-role="fieldcontain" 
                ShowFooter="True">
                    <Columns>    
                        <asp:TemplateField HeaderText="Product" ItemStyle-HorizontalAlign="Left">
                            <FooterTemplate>
                                <asp:DropDownList ID="dllProducts" runat="server" data-native-menu="false" />
                            </FooterTemplate>
                            <ItemTemplate>
                                <asp:Label ID="lblId" runat="server" Text='<%# Bind("Id") %>' Visible="False" />
                                <asp:Label ID="lblProduct" runat="server" Text='<%# Bind("Product") %>' />
                            </ItemTemplate>
                            <HeaderStyle HorizontalAlign="Center" />
                            <ItemStyle HorizontalAlign="Left" Width="90%" />
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="Quantity" ItemStyle-HorizontalAlign="Center">
                            <FooterTemplate>
                                <asp:TextBox ID="txtInsertQuantity" runat="server" Columns="2" data-mini="true" 
                                    MaxLength="3" style="text-align: center" Text='<%# Bind("Quantity") %>' 
                                    type="number" Width="40px" />
                            </FooterTemplate>
                            <ItemTemplate>
                                <asp:TextBox ID="txtQuantity" runat="server" Text='<%# Bind("Quantity") %>' 
                                    Columns="2" data-mini="true" MaxLength="3" Width="40px" type="number" 
                                    style="text-align: center" />
                            </ItemTemplate>
                            <HeaderStyle HorizontalAlign="Center" />
                            <ItemStyle HorizontalAlign="Center" />
                        </asp:TemplateField>
                    </Columns>
                    <EmptyDataTemplate>
                        No records found
                    </EmptyDataTemplate>
                </asp:gridview>
            <asp:Label ID="lblError" runat="server" ForeColor="Red" 
                ViewStateMode="Disabled"></asp:Label>
            <br />
            <asp:Button ID="btnSave" runat="server" Text="Save" data-icon="gear" 
                data-role="button" data-ajax="false" data-theme="e" OnClick="btnSave_Click" />
            <asp:Button ID="btnDelete" runat="server" Text="Delete" data-icon="delete" 
                data-role="button" data-ajax="false" data-theme="a" 
                OnClientClick='if (!confirm("Are you sure you want to delete?") ){return false;}'
                OnClick="btnDelete_Click" />
            <asp:hyperlink id="lnkMainMenu" runat="server" navigateurl="~/MobileMenu.aspx" data-role="button"
                data-ajax="false" data-icon="star" data-theme="b" text="Main Menu" />
        </div>
        <!-- /content -->
    </div>
    <!-- /page -->
    </form>
</body>
</html>

 

This is the code behind:

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;
namespace LightSwitchApplication.Mobile
{
    public partial class OrderEdit : System.Web.UI.Page
    {
        #region BaseSiteUrl
        public static string BaseSiteUrl
        {
            get
            {
                HttpContext context = HttpContext.Current;
                string baseUrl = context.Request.Url.Scheme 
                    + "://" 
                    + context.Request.Url.Authority 
                    + context.Request.ApplicationPath.TrimEnd('/') + '/';
                return baseUrl;
            }
        }
        #endregion
        protected void Page_Load(object sender, EventArgs e)
        {          
            if (!Page.IsPostBack)
            {
                // Display Order Details
                LoadOrder();
                // Populate the dropdown
                PopulateProducts();
            }
        }
        #region PopulateProducts
        private void PopulateProducts()
        {
            if (gvOrderDetails.FooterRow != null)
            {
                // Create DataContext
                ODataServiceReference.ApplicationData objApplicationData =
                    new ODataServiceReference.ApplicationData(
                        new Uri(string.Format(@"{0}applicationdata.svc/", BaseSiteUrl)));
                // Query OData source
                var colFlowerShopProducts = from FlowerShopProducts in objApplicationData.FlowerShopProducts
                                            select FlowerShopProducts;
                // Get an instance of the Dropdown
                DropDownList dllProducts = (DropDownList)gvOrderDetails.FooterRow.FindControl("dllProducts");
                // Bind items to Dropdown
                dllProducts.Items.Clear();
                dllProducts.DataSource = colFlowerShopProducts;
                dllProducts.DataValueField = "Id";
                dllProducts.DataTextField = "ProductName";
                dllProducts.Attributes.Add("data-overlay-theme", "b");
                dllProducts.DataBind();
                // Create default entry to top of Dropdown
                var objListItem = new ListItem("[Select a Product]", "0");
                objListItem.Attributes.Add("data-placeholder", "true");
                dllProducts.Items.Insert(0, objListItem);
                dllProducts.Items.FindByText("[Select a Product]").Selected = true;
                // Add JQuery Mobile attribute to items in Dropdown
                for (int i = 0; i < dllProducts.Items.Count; i++)
                {
                    dllProducts.Items[i].Attributes.Add("title", dllProducts.Items[i].Text);
                }
            }
        }
        #endregion
        #region LoadOrder
        private void LoadOrder()
        {
            if (this.Request.QueryString["Id"] != null)
            {
                // Load the order based on the Id passed
                LoadOrder(Convert.ToInt32(this.Request.QueryString["Id"]));
            }
        }
        #endregion
        #region LoadOrder(int Id)
        private void LoadOrder(int Id)
        {
            // Create DataContext
            ODataServiceReference.ApplicationData objApplicationData =
                new ODataServiceReference.ApplicationData(
                    new Uri(string.Format(@"{0}applicationdata.svc/", BaseSiteUrl)));
            // Collection to hold Order Details
            var OrderDetailsInfo = new List<OrderDetailsInfo>();
            // Value to hold Order Total
            double dblOrderTotal = 0.00d;
            // Query OData source
            var objOrderDetails = from OrderDetails in objApplicationData.FlowerShopOrderDetails
                                       .Expand(x => x.FlowerShopProduct)
                                  where OrderDetails.FlowerShopOrder.Id == Id
                                  select OrderDetails;
            foreach (var item in objOrderDetails)
            {
                // Create OrderDetails object
                OrderDetailsInfo NewOrderDetailsInfo = new OrderDetailsInfo();
                // Set values
                NewOrderDetailsInfo.Id = item.Id;
                NewOrderDetailsInfo.Product = item.FlowerShopProduct.ProductName;
                NewOrderDetailsInfo.Quantity = item.Quantity;
                // Add Order Detail to final collection
                OrderDetailsInfo.Add(NewOrderDetailsInfo);
                // Update order total
                dblOrderTotal = dblOrderTotal +
                    Convert.ToDouble((item.FlowerShopProduct.Price * item.Quantity));
            }
            // Bind collection to Grid
            gvOrderDetails.DataSource = OrderDetailsInfo;
            gvOrderDetails.DataBind();
            // Display the total
            lblOrderHeader.Text = String.Format("Total: $ {0}", dblOrderTotal);
        }
        #endregion
        #region btnSave_Click
        protected void btnSave_Click(object sender, EventArgs e)
        {
            try
            {
                // Get OrderID
                int intId = Convert.ToInt32(this.Request.QueryString["Id"]);
                // Create DataContext
                ODataServiceReference.ApplicationData objApplicationData =
                    new ODataServiceReference.ApplicationData(
                        new Uri(string.Format(@"{0}applicationdata.svc/", BaseSiteUrl)));
                #region Existing Order Details
                // Loop thru the Orders in the Grid
                var DataObject = gvOrderDetails.DataSourceObject;
                for (int i = 0; i < gvOrderDetails.Rows.Count; i++)
                {
                    // Get an instance of the Label and the TextBox
                    Label lblId = (Label)gvOrderDetails.Rows[i].Cells[0].FindControl("lblId");
                    TextBox txtQuantity = (TextBox)gvOrderDetails.Rows[i].Cells[0].FindControl("txtQuantity");
                    // Convert the Label and the TextBox to values
                    int intOrderDetailId = Convert.ToInt32(lblId.Text);
                    int intQuantity = Convert.ToInt32(txtQuantity.Text);
                    // Query OData source
                    var objOrderDetail = (from OrderDetails in objApplicationData.FlowerShopOrderDetails
                                               .Expand(x => x.FlowerShopProduct)
                                          where OrderDetails.Id == intOrderDetailId
                                          select OrderDetails).FirstOrDefault();
                    if (objOrderDetail != null)
                    {
                        // If Quantity is set to zero delete the Product entry
                        if (intQuantity == 0)
                        {
                            objApplicationData.DeleteObject(objOrderDetail);
                        }
                        else // Update the Product entry 
                        {
                            objOrderDetail.Quantity = intQuantity;
                            objApplicationData.UpdateObject(objOrderDetail);
                        }
                    }
                }
                #endregion
                #region New Order Details    
                // Get an instance of the Dropdown
                DropDownList dllProducts = (DropDownList)gvOrderDetails.FooterRow.FindControl("dllProducts");
                TextBox txtInsertQuantity = (TextBox)gvOrderDetails.FooterRow.FindControl("txtInsertQuantity");
                // Convert the Label and the TextBox to values
                string strProduct = dllProducts.SelectedItem.Text;
                int intProduct = Convert.ToInt32(dllProducts.SelectedValue);
                int intInsertQuantity = 0;
                // Only try an insert if txtInsertQuantity is an integer
                if (int.TryParse(txtInsertQuantity.Text, out intInsertQuantity))
                {
                    if (intProduct != 0 && intInsertQuantity > 0)
                    {
                        // Create a new FlowerShopOrderDetail
                        LightSwitchApplication.ODataServiceReference.FlowerShopOrderDetail objFlowerShopOrderDetail =
                            new LightSwitchApplication.ODataServiceReference.FlowerShopOrderDetail();
                        // Set values
                        objFlowerShopOrderDetail.OrderDetail_Order = intId;
                        objFlowerShopOrderDetail.OrderDetail_Product = intProduct;
                        objFlowerShopOrderDetail.Quantity = intInsertQuantity;
                        // Add new FlowerShopOrderDetail
                        objApplicationData.AddToFlowerShopOrderDetails(objFlowerShopOrderDetail);
                    }
                }
                #endregion
                // Save all changes as a single Batch call
                objApplicationData.SaveChanges(System.Data.Services.Client.SaveChangesOptions.Batch);
                // Go To Main Menu
                Server.Transfer("MobileMenu.aspx");
            }
            catch (Exception ex)
            {
                ShowError(ex);
                return;
            }            
        }
        #endregion
        #region btnDelete_Click
        protected void btnDelete_Click(object sender, EventArgs e)
        {
            if (this.Request.QueryString["Id"] != null)
            {
                try
                {
                    // Load the order based on the Id passed
                    int intId = Convert.ToInt32(this.Request.QueryString["Id"]);
                    // Create DataContext
                    ODataServiceReference.ApplicationData objApplicationData =
                        new ODataServiceReference.ApplicationData(
                            new Uri(string.Format(@"{0}applicationdata.svc/", BaseSiteUrl)));
                    // Get all the Order details 
                    var colOrderDetails = from OrderDetails in objApplicationData.FlowerShopOrderDetails
                                              .Expand(x => x.FlowerShopOrder)
                                          where OrderDetails.FlowerShopOrder.Id == intId
                                          select OrderDetails;
                    foreach (var item in colOrderDetails)
                    {
                        // Delete the Order detail item
                        objApplicationData.DeleteObject(item);
                    }
                    objApplicationData.SaveChanges(System.Data.Services.Client.SaveChangesOptions.Batch);
                    // Get the Order  
                    var objOrder = (from FlowerShopOrders in objApplicationData.FlowerShopOrders
                                    where FlowerShopOrders.Id == intId
                                    select FlowerShopOrders).FirstOrDefault();
                    if (objOrder != null)
                    {
                        // Delete the Order detail item
                        objApplicationData.DeleteObject(objOrder);
                        objApplicationData.SaveChanges(System.Data.Services.Client.SaveChangesOptions.Batch);
                    }   
                    
                    // Return to Main Menu
                    Server.Transfer("MobileMenu.aspx");
                }
                catch (Exception ex)
                {
                    ShowError(ex);
                }
            }
        }
        #endregion
        // Utility
        #region ShowError(Exception ex)
        private void ShowError(Exception ex)
        {
            // see: http://msdn.microsoft.com/en-us/magazine/hh580732.aspx
            if (ex.InnerException != null)
            {
                // This is a complex error 
                var sr = new StringReader(ex.InnerException.Message);
                using (sr)
                {
                    XElement root = XElement.Load(sr);
                    IEnumerable<XElement> message =
                        from el in root.Elements()
                        where el.Name.LocalName == "message"
                        select el;
                    foreach (XElement el in message)
                    {
                        lblError.Text = String.Format(@"{0}<br />", el.Value);
                    }
                }
                sr.Close();
            }
            else
            {
                // This is a simple error -- just show Message
                lblError.Text = String.Format(@"{0}", ex.Message);
            }
        }
        #endregion
        #region OrderDetailsInfo
        public class OrderDetailsInfo
        {
            int _Id;
            public int Id
            {
                get { return _Id; }
                set { _Id = value; }
            }
            string _Product;
            public string Product
            {
                get { return _Product; }
                set { _Product = value; }
            }
            int _Quantity;
            public int Quantity
            {
                get { return _Quantity; }
                set { _Quantity = value; }
            }
        }
        #endregion
    }
}

 

Still… Use The Silverlight Screens When You Can

Silverlight is not “dead”. In fact it provides the best, most efficient user experience.

Also note, It took a full day to write the ASP.NET/JQuery code, and two full days to debug it, while the LightSwitch code that creates the Silverlight user interface was created in less than 15 minutes.

 

Also See

Calling LightSwitch 2011 OData Using Server Side Code

Communicating With LightSwitch Using Android App Inventor

Learn How To Make OData Calls In LightSwitch 2011

Accessing Your Visual Studio 2011 LightSwitch Application Using OData

Consume a LightSwitch OData Service from a Windows Phone application

Download Code

The LightSwitch project is available at:

http://lightswitchhelpwebsite.com/Downloads.aspx

Tags: OData
Categories:

12 comment(s) so far...


Gravatar

Re: A Full CRUD LightSwitch JQuery Mobile Application

Well thank you very much!!

How the heck am I supposed to concentrate at my day job now; knowing that I can do all this. I need to focus... FOCUS I tell you ...bah, forget it, I just got to try it now.

One of my favourite articles to date Michael!

Cheers,

Paul

By Paul Patterson on   4/11/2012 6:40 AM
Gravatar

Re: A Full CRUD LightSwitch JQuery Mobile Application

Awesome!

By DotNetLore on   4/11/2012 6:45 AM
Gravatar

Re: A Full CRUD LightSwitch JQuery Mobile Application

@Paul Patterson & @DotNetLore - Thank you for the feedback, it is appreciated.

By Michael Washington on   4/11/2012 7:46 AM
Gravatar

Re: A Full CRUD LightSwitch JQuery Mobile Application

Hi Michael,
it means that I can use this application with IOS devices?

By lolavar on   5/2/2012 2:10 AM
Gravatar

Re: A Full CRUD LightSwitch JQuery Mobile Application

@lolavar - Yes.

By Michael Washington on   5/2/2012 4:43 AM
Gravatar

Re: A Full CRUD LightSwitch JQuery Mobile Application

Hey Michael,

Thank you for example. I noticed that whenever you do a Server.Transfer or Response.Redirect from the C# code the page tranfers correctly but the URL is not correct. Example would be when you login instead of http://localhost:16978/MobileMenu.aspx showing in the URL we get http://localhost:16978/login.aspx#/login.aspx. Another example is when you edit an order and go back to the order list instead of http://localhost:17234/MobileMenu.aspx showing in the URL we get http://localhost:17234/OrderEdit.aspx?Id=1#/OrderEdit.aspx?Id=1. This would create problems if user hits refresh. Any idea what is causing this? Thanks for any help.

By David Moss on   6/13/2012 8:23 AM
Gravatar

Re: A Full CRUD LightSwitch JQuery Mobile Application

@David Moss - I used Server.Transfer to work around other jQuery Mobile issue I was having. The fact that the URL is not changed on a Server.Transfer is an unfortunate thing.

By Michael Washington on   6/13/2012 8:30 AM
Gravatar

Re: A Full CRUD LightSwitch JQuery Mobile Application

Should the "Remember Me" checkbox on the Login.aspx page be working? Username does not seem to be remembered.

Thanks

By David Moss on   10/22/2012 11:25 AM
Gravatar

Re: A Full CRUD LightSwitch JQuery Mobile Application

@David Moss - It works for me. Perhaps your cookies are disabled.

By Michael Washington on   10/22/2012 11:30 AM
Gravatar

Re: A Full CRUD LightSwitch JQuery Mobile Application

Cookies are enabled on clients. Could it be a server setting in the web.config? Also doesn't work when running with Test User on localhost. Thanks

By David Moss on   10/22/2012 12:07 PM
Gravatar

Re: A Full CRUD LightSwitch JQuery Mobile Application

Maybe I'm not understanding the "remember me" functionality. Should it be remembering the "User Name" the next time the login.aspx form is browsed?

By David Moss on   10/22/2012 12:13 PM
Gravatar

Re: A Full CRUD LightSwitch JQuery Mobile Application

@David Moss - I just tested and it is not working for me. I was mistaken.

By Michael Washington on   10/22/2012 3:10 PM

Your name:
Gravatar Preview
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Security Code
CAPTCHA image
Enter the code shown above in the box below
Add Comment   Cancel 

Microsoft Visual Studio is a registered trademark of Microsoft Corporation / LightSwitch is a registered trademark of Microsoft Corporation