Tips and Tricks

Labels
AJAX(112) App Studio(7) Apple(1) Application Builder(245) Application Factory(207) ASP.NET(95) ASP.NET 3.5(45) ASP.NET Code Generator(72) ASP.NET Membership(28) Azure(18) Barcode(2) Barcodes(3) BLOB(18) Business Rules(1) Business Rules/Logic(140) BYOD(13) Caching(2) Calendar(5) Charts(29) Cloud(14) Cloud On Time(2) Cloud On Time for Windows 7(2) Code Generator(54) Collaboration(11) command line(1) Conflict Detection(1) Content Management System(12) COT Tools for Excel(26) CRUD(1) Custom Actions(1) Data Aquarium Framework(122) Data Sheet(9) Data Sources(22) Database Lookups(50) Deployment(22) Designer(177) Device(1) DotNetNuke(12) EASE(20) Email(6) Features(101) Firebird(1) Form Builder(14) Globalization and Localization(6) How To(1) Hypermedia(2) Inline Editing(1) Installation(5) JavaScript(20) Kiosk(1) Low Code(3) Mac(1) Many-To-Many(4) Maps(6) Master/Detail(36) Microservices(4) Mobile(63) Mode Builder(3) Model Builder(3) MySQL(10) Native Apps(5) News(18) OAuth(9) OAuth Scopes(1) OAuth2(13) Offline(20) Offline Apps(4) Offline Sync(5) Oracle(11) PKCE(2) Postgre SQL(1) PostgreSQL(2) PWA(2) QR codes(2) Rapid Application Development(5) Reading Pane(2) Release Notes(183) Reports(48) REST(29) RESTful(29) RESTful Workshop(15) RFID tags(1) SaaS(7) Security(81) SharePoint(12) SPA(6) SQL Anywhere(3) SQL Server(26) SSO(1) Stored Procedure(4) Teamwork(15) Tips and Tricks(87) Tools for Excel(2) Touch UI(93) Transactions(5) Tutorials(183) Universal Windows Platform(3) User Interface(338) Video Tutorial(37) Web 2.0(100) Web App Generator(101) Web Application Generator(607) Web Form Builder(40) Web.Config(9) Workflow(28)
Archive
Blog
Tips and Tricks
Thursday, July 1, 2010PrintSubscribe
Sending Email in Response to Action

Q. Is it possible to send email via OnTime? For example, click a record that has an email field and using Form Mail, generate an smtp connection (with username and password and smtp info) to send the email?

A.

It is possible to perform any sort of business logic in response to selection of a user interface action including sending an email.

Modify your project in Designer to create a user interface action that will be triggering an email. Declare a business rules handler for the data controller and implement the code that will send email. Selected row field values are passed from the client to the server code and can be used to determine the email recipient and any other action-specific parameters.

Here is a how you can define  a business rules handler and action.

See this and many other video tutorials on our YouTube channel at http://www.youtube.com/watch?v=M45hyY185Ck.

We have modified the sample project by adding Send Email action to Customers data controller.

The screen shot below shows the email option in action:

image 

The business rules class shows how to handle the action by sending an email from an existing gmail account to the selected recipient. Notice that the order of parameters in the business rule method is arbitrary. You can list every single field available in client-side view or limit the list of arguments  to only those that are really needed to compose an email. 

If you enable multiple selection of rows as described at /blog/2010/04/globalization-localization-multi-select.html then primary key values of selected rows can be selected by accessing Arguments.SelectedValues property within the business rules method.

VB.NET:

Imports MyCompany.Data
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Linq
Imports System.Net.Mail
Imports System.Net

Namespace MyCompany.Rules

    Partial Public Class CustomersBusinessRules
        Inherits MyCompany.Data.BusinessRules

        <ControllerAction("Customers", "Custom", "SendEmail")> _
        Sub SendAnEmailToACustomer(ByVal companyName As String, ByVal contactName As String, ByVal customerID As String)
            Dim message As MailMessage = New MailMessage()
            message.From = New MailAddress("SENDER@gmail.com", "Sales, Code OnTime")

            ' prepare smtp client
            Dim smtp As SmtpClient = New SmtpClient("smtp.gmail.com", 587)
            smtp.EnableSsl = True
            smtp.UseDefaultCredentials = False
            smtp.Credentials = New NetworkCredential("SENDER@gmail.com", "PASSWORD")

            ' compose and send an email message

            ' use CustomerID to find the recipient's email
            Dim sendTo As String = "recipient@contoso.com"

            message.To.Add(sendTo)
            message.Subject = String.Format("Hello {0} at {1}.", contactName, companyName)
            message.Body = "Hello there!"
            smtp.Send(message)

            Result.ShowAlert("Email has been sent.")

        End Sub

    End Class
End Namespace

C#:

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using MyCompany.Data;
using System.Net.Mail;
using System.Net;

namespace MyCompany.Rules
{
    public partial class CustomersBusinessRules : MyCompany.Data.BusinessRules
    {

        [ControllerAction("Customers", "Custom", "SendEmail")]
        public void SendAnEmailToACustomer(string companyName, string contactName, string customerId)
        {
            MailMessage message = new MailMessage();
            message.From = new MailAddress("SENDER@gmail.com", "Sales, Code OnTime");

            // prepare smtp client
            SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587);
            smtp.EnableSsl = true;
            smtp.UseDefaultCredentials = false;
            smtp.Credentials = new NetworkCredential("SENDER@gmail.com", "PASSWORD");

            // compose and send an email message

            // use CustomerID to find the recipient's email
            string sendTo = "recipient@contoso.com";

            message.To.Add(sendTo);
            message.Subject = String.Format("Hello {0} at {1}.", contactName, companyName);
            message.Body = "Hello there!";
            smtp.Send(message);

            Result.ShowAlert("Email has been sent.");

        }
    }
}

The following confirmation is displayed in the client browser.

image

Tuesday, June 29, 2010PrintSubscribe
Refreshing Master When Detail Changed

Q. Is there an easy way to force the Master View at the top of a page to automatically refresh (from the server) when an item is edited in the child/detail view at the bottom of the page ?

A. The example below is referring to the Northwind sample application.

Suppose you want to refresh a list of Suppliers when the detail Products view has been changed on page ~/Pages/Suppliers.aspx.

Here is the Suppliers page:

image

If the products shipped by the selected supplier have changed (inserted, updated, or deleted) then you want the list of suppliers to refresh its content.

Open the project in Designer and assign ProductsBusinessRules handler to Products data controller. If you generate the project then business rules class empty shall ~\App_Code\Rules\ProductsBusinessRules.cs file will be created for you. If you are using VB as a programming language of the generated application then the business rules class will be coded in VB.NET.

Here is the sample business rules class written in C#, which will do the trick of refresh the master:

using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using MyCompany.Data;

namespace MyCompany.Rules
{
    public partial class ProductsBusinessRules : MyCompany.Data.BusinessRules
    {
        [ControllerAction("Products", "Update", ActionPhase.After)]
        [ControllerAction("Products", "Insert", ActionPhase.After)]
        [ControllerAction("Products", "Delete", ActionPhase.After)]
        public void DoRefreshMaster(string companyName, int supplierID)
        {
            if (Result.Errors.Count == 0)
                Result.ExecuteOnClient(
                    "this.set_lastCommandName(null);" + // the action state machine is reset
                    "this.goToView('grid1');" + // show 'grid1'
                    "var dv=Web.DataView.find('view1Extender');" + // find specific master data view
                    "if(dv)dv.refresh();"); // if the view is found then ask it to refresh
        }
    }
}

Note that parameters in DoRefreshMaster are not playing any role here. You could use the field values to perform selective operations in the client when needed.

The view we are looking to refresh is view1Extender. This extender is available on page ~/App_Code/Pages/Suppliers.aspx.

Here is the page markup as created by code generator:

<%@ Page Language="C#" MasterPageFile="~/Main.master" AutoEventWireup="true" CodeFile="Suppliers.aspx.cs"
    Inherits="Pages_Suppliers" Title="Suppliers" %>

<asp:Content ID="Content1" ContentPlaceHolderID="PageHeaderContentPlaceHolder" runat="Server">
    Suppliers</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="PageContentPlaceHolder" runat="Server">
    <div factory:flow="NewRow" xmlns:factory="urn:codeontime:app-factory">
        <div id="view1" runat="server">
        </div>
        <aquarium:DataViewExtender ID="view1Extender" runat="server" TargetControlID="view1"
            Controller="Suppliers" View="grid1" ShowInSummary="True" />
    </div>
    <div factory:flow="NewRow" style="padding-top: 8px" xmlns:factory="urn:codeontime:app-factory">
        <div factory:activator="Tab|Products">
            <div id="view2" runat="server">
            </div>
            <aquarium:DataViewExtender ID="view2Extender" runat="server" TargetControlID="view2"
                Controller="Products" View="grid1" FilterSource="view1Extender" FilterFields="SupplierID"
                PageSize="5" AutoHide="Container" />
        </div>
    </div>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="SideBarPlaceHolder" runat="Server">
    <div class="TaskBox">
        <div class="Inner">
            <div class="Header">
                About</div>
            <div class="Value">
                This page allows suppliers management.</div>
        </div>
    </div>
</asp:Content>
Tuesday, June 22, 2010PrintSubscribe
Using My Own Folder For Code On Time Files

Q. How can I change the working directory for a project generated by CodeOnTime?

A.

Code OnTime Generator uses [My Documents]\Code OnTime folder to install the code generation library templates. The same folder is used to create code generation projects.

Download the file at /documents/codeontime.exe.zip.

The archive contains CodeOnTime.exe.config file. The contents of the file are listed below:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
            ..............
    </configSections>
    <applicationSettings>
        <CodeOnTime.Properties.Settings>
            <setting name="MyDocuments" serializeAs="String">
                <value>c:\Code OnTime Root</value>
            </setting>
        </CodeOnTime.Properties.Settings>
    </applicationSettings>
</configuration>

Unzip and copy the attached file to the [Program Files]\Code OnTime LLC\Code OnTime Generator folder.

Create a folder on your local hard drive and replace "c:\Code OnTime Root" in the CodeOnTime.exe.config with the path to your folder. The generator will start using this folder instead of [My Documents], when you restart the program.