Saturday, February 25, 2017

ASP.NET MVC with Dapper ORM in VB.NET

Konnichiwa,
Here's a VB.NET ASP.NET MVC CRUD project using Dapper ORM which is the counterpart of this post ASP.NET MVC with Dapper ORM. The only file in the Models folder that has updates is Customer.cs class such as applying Display and DisplayAttributes.
Imports System.ComponentModel.DataAnnotations

Public Class Customer

    Public Property CustomerID() As Integer
        Get
            Return m_CustomerID
        End Get
        Set(value As Integer)
            m_CustomerID = value
        End Set
    End Property
    Private m_CustomerID As Integer

    <Display(Name:="Company Name")>
    Public Property CompanyName() As String
        Get
            Return m_CompanyName
        End Get
        Set(value As String)
            m_CompanyName = value
        End Set
    End Property
    Private m_CompanyName As String

    <Display(Name:="Address")>
    Public Property Address() As String
        Get
            Return m_Address
        End Get
        Set(value As String)
            m_Address = value
        End Set
    End Property
    Private m_Address As String

    <Display(Name:="City")>
    Public Property City() As String
        Get
            Return m_City
        End Get
        Set(value As String)
            m_City = value
        End Set
    End Property
    Private m_City As String

    <Display(Name:="State")>
    Public Property State() As String
        Get
            Return m_State
        End Get
        Set(value As String)
            m_State = value
        End Set
    End Property
    Private m_State As String

    <Display(Name:="Intro Date")>
    <DisplayFormat(DataFormatString:="{0:yyyy-MM-dd}", ApplyFormatInEditMode:=True)>
    Public Property IntroDate() As DateTime
        Get
            Return m_IntroDate
        End Get
        Set(value As DateTime)
            m_IntroDate = value
        End Set
    End Property
    Private m_IntroDate As DateTime

    <Display(Name:="Credit Limit")>
    <DisplayFormat(DataFormatString:="{0:n2}")>
    Public Property CreditLimit() As Decimal
        Get
            Return m_CreditLimit
        End Get
        Set(value As Decimal)
            m_CreditLimit = value
        End Set
    End Property
    Private m_CreditLimit As Decimal

End Class

You may download the project with create table script here Github ASP.NETMVCDapperVB
Cheers!

Thursday, February 23, 2017

ASP.NET MVC with Dapper ORM

Hi All,
Here's an ASP.NET MVC CRUD(Create/Update/Delete) project with Dapper ORM. The model classes and interface are based from this post Using Dapper ORM in ASP.NET Web Forms with few modifications in Customer class. The updates are adding Display attribute and DisplayFormat attribute to CreditLimit and IntroDate properties.
using System;
using System.ComponentModel.DataAnnotations;

namespace ASPMVCDapper.Models
{
    public class Customer
    {
        public int CustomerID { get; set; }

        [Display(Name="Company Name")]
        public string CompanyName { get; set; }

        [Display(Name = "Address")]
        public string Address { get; set; }

        [Display(Name = "City")]
        public string City { get; set; }

        [Display(Name = "State")]
        public string State { get; set; }

        [Display(Name = "Intro Date")]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime IntroDate { get; set; }

        [Display(Name = "Credit Limit")]
        [DisplayFormat(DataFormatString = "{0:n2}")]
        public decimal CreditLimit { get; set; }
    }
}
Output The source code and Create table script are available in Github ASP.NET MVC With Dapper.

Cheers!

Wednesday, February 22, 2017

Unable to cast object of type 'DapperRow' to return Type

Aloha,
Given the following code which generates an exception "Unable to cast object of type 'DapperRow", the cause for this is that the return type of FirstOrDefault() dynamic.
public Customer FindById(int Id)
{
 return this._db.Query("SELECT * FROM Customer WHERE CustomerID=@Id", new { Id = Id }).FirstOrDefault();
}
In order to solve this error, you have several options. One is to use Query.<TReturn>() instead of Query() wherein you can explicity specify the type.
public Customer FindById(int Id)
{
 return this._db.Query<Customer>("SELECT * FROM Customer WHERE CustomerID=@Id", new { Id = Id }).FirstOrDefault();
}
Another option is to modify the code with issue, that is to store the result of the query in a dynamic variable and then assign the dynamic properties value to the class properties.
public Customer FindById(int Id)
{
 dynamic customerRecord = this._db.Query("SELECT * FROM Customer WHERE CustomerID=@Id", new { Id = Id }).FirstOrDefault();
 
 return new Customer()
 {
  CustomerID = Convert.ToInt32(customerRecord.CustomerID),
  Address = customerRecord.Address,
  City = customerRecord.City,
  CompanyName = customerRecord.CompanyName,
  CreditLimit = Convert.ToDecimal(customerRecord.CreditLimit),
  IntroDate = Convert.ToDateTime(customerRecord.IntroDate),
  State = customerRecord.State
 };
}

Monday, February 20, 2017

Using Dapper ORM in ASP.NET Web Forms (Visual Basic.NET)

Hi,
This is a conversion of this post Using Dapper ORM in ASP.NET WebForm to VB.NET language.
Customer.vb
Public Class Customer

    Public Property CustomerID() As Integer
        Get
            Return m_CustomerID
        End Get
        Set(value As Integer)
            m_CustomerID = Value
        End Set
    End Property
    Private m_CustomerID As Integer

    Public Property CompanyName() As String
        Get
            Return m_CompanyName
        End Get
        Set(value As String)
            m_CompanyName = Value
        End Set
    End Property
    Private m_CompanyName As String

    Public Property Address() As String
        Get
            Return m_Address
        End Get
        Set(value As String)
            m_Address = Value
        End Set
    End Property
    Private m_Address As String

    Public Property City() As String
        Get
            Return m_City
        End Get
        Set(value As String)
            m_City = Value
        End Set
    End Property
    Private m_City As String

    Public Property State() As String
        Get
            Return m_State
        End Get
        Set(value As String)
            m_State = Value
        End Set
    End Property
    Private m_State As String

    Public Property IntroDate() As DateTime
        Get
            Return m_IntroDate
        End Get
        Set(value As DateTime)
            m_IntroDate = Value
        End Set
    End Property
    Private m_IntroDate As DateTime

    Public Property CreditLimit() As Decimal
        Get
            Return m_CreditLimit
        End Get
        Set(value As Decimal)
            m_CreditLimit = Value
        End Set
    End Property
    Private m_CreditLimit As Decimal

End Class
ICustomerRepository.vb
Public Interface ICustomerRepository

    Function GetAll() As List(Of Customer)
    Function FindById(Id As Integer) As Customer
    Function AddCustomer(customer As Customer) As Boolean
    Function UpdateCustomer(customer As Customer) As Boolean
    Function DeleteCustomer(Id As Integer) As Boolean

End Interface
CustomerRepository.vb
Imports System.Data.SqlClient
Imports Dapper

Public Class CustomerRepository
    Implements ICustomerRepository

    Private _db As IDbConnection

    Public Sub New()
        _db = New SqlConnection(ConfigurationManager.ConnectionStrings("CustomerInformation").ConnectionString)
    End Sub

    Public Function GetAll() As List(Of Customer) Implements ICustomerRepository.GetAll
        Return Me._db.Query(Of Customer)("SELECT * From Customer;").ToList()
    End Function

    Public Function FindById(Id As Integer) As Customer Implements ICustomerRepository.FindById
        Return Me._db.Query("SELECT * FROM Customer WHERE CustomerID=@Id", New With { _
            Key .Id = Id _
        }).FirstOrDefault()
    End Function

    Public Function AddCustomer(customer As Customer) As Boolean Implements ICustomerRepository.AddCustomer
        Dim parameters As SqlParameter() = {
            New SqlParameter("@CompanyName", customer.CompanyName),
            New SqlParameter("@Address", customer.Address),
            New SqlParameter("@City", customer.City),
            New SqlParameter("@State", customer.State),
            New SqlParameter("@IntroDate", customer.IntroDate),
            New SqlParameter("@CreditLimit", customer.CreditLimit)}

        Dim query As String = "INSERT INTO Customer(CompanyName,Address,City,State,IntroDate,CreditLimit)" + " Values(@CompanyName,@Address,@City,@State,@IntroDate,@CreditLimit)"

        Dim args = New DynamicParameters()
        For Each p As SqlParameter In parameters
            args.Add(p.ParameterName, p.Value)
        Next

        Try
            Me._db.Query(Of Customer)(query, args).SingleOrDefault()
        Catch generatedExceptionName As Exception
            Return False
        End Try

        Return True
    End Function

    Public Function UpdateCustomer(customer As Customer) As Boolean Implements ICustomerRepository.UpdateCustomer
        Dim parameters As SqlParameter() = {
            New SqlParameter("@CustomerID", customer.CustomerID),
            New SqlParameter("@CompanyName", customer.CompanyName),
            New SqlParameter("@Address", customer.Address),
            New SqlParameter("@City", customer.City),
            New SqlParameter("@State", customer.State),
            New SqlParameter("@IntroDate", customer.IntroDate), _
            New SqlParameter("@CreditLimit", customer.CreditLimit)}

        Dim query As String = " UPDATE Customer SET CompanyName = @CompanyName,Address = @Address, " + " City = @City,State = @State,IntroDate = @IntroDate,CreditLimit = @CreditLimit" + " WHERE CustomerID = @CustomerID"

        Dim args = New DynamicParameters()
        For Each p As SqlParameter In parameters
            args.Add(p.ParameterName, p.Value)
        Next

        Try
            Me._db.Execute(query, args)
        Catch generatedExceptionName As Exception
            Return False
        End Try

        Return True
    End Function

    Public Function DeleteCustomer(Id As Integer) As Boolean Implements ICustomerRepository.DeleteCustomer
        Dim deletedCustomer As Integer = Me._db.Execute("DELETE FROM Customer WHERE CustomerID = @Id", New With { _
            Key .Id = Id _
        })
        Return deletedCustomer > 0
    End Function

End Class
CustomerService.vb
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web

Public Class CustomerService
    Private _repository As ICustomerRepository

    Public Sub New()
        _repository = New CustomerRepository()
    End Sub

    Public Function GetAll() As List(Of Customer)
        Return _repository.GetAll()
    End Function

    Public Function FindById(Id As Integer) As Customer
        Return _repository.FindById(Id)
    End Function

    Public Function AddCustomer(customer As Customer) As Boolean
        Return _repository.AddCustomer(customer)
    End Function

    Public Function UpdateCustomer(customer As Customer) As Boolean
        Return _repository.UpdateCustomer(customer)
    End Function

    Public Function DeleteCustomer(Id As Integer) As Boolean
        Return _repository.DeleteCustomer(Id)
    End Function
End Class

Screenshot
The source code is available for download in Github Repository.

Note: When running this project, download the create table script here and then change the target database in the script. Then run the script using SQL Server query window.
That's it.. :-)

Using Dapper ORM in ASP.NET Web Forms

Hello,
This is a simple tutorial of using Dapper Micro ORM in an ASP.NET Webform application. According to Wikipedia, Dapper is an object-relational mapping (ORM) product for the Microsoft .NET platform: it provides a framework for mapping an object-oriented domain model to a traditional relational database. Its purpose is to relieve the developer from a significant portion of relational data persistence-related programming tasks.
The key feature of Dapper is performance as presented in Dapper website (github). It is second to Hand coded SQLDataReader class when querying specific number of records.
To get started with, create an Empty ASP.NET WebForm project and then add the Dapper to our project via NuGet. Make sure to alter the connection string in Web.Config to point to your database. Then we need to add one interface and three classes in our Models folder which applies the idea of Repository.
Customer.cs
public class Customer
{
 public int CustomerID { get; set; }

 public string CompanyName { get; set; }

 public string Address { get; set; }

 public string City { get; set; }

 public string State { get; set; }

 public DateTime IntroDate { get; set; }

 public decimal CreditLimit { get; set; }
}

ICustomerRepository.cs
public interface ICustomerRepository
{
 List<Customer> GetAll();
 Customer FindById(int Id);
 bool AddCustomer(Customer customer);
 bool UpdateCustomer(Customer customer);
 bool DeleteCustomer(int Id);
}

CustomerRepository.cs (This class references System.Configuration, Dapper, System.Data and System.Data.SqlClient namespaces. Note that this class also includes passing SqlParameters to DynamicParameters of Dapper given that using SQLParameters is the recommended practice for querying the database.
public class CustomerRepository : ICustomerRepository
{
 private IDbConnection _db;

 public CustomerRepository()
 {
  _db = new SqlConnection(ConfigurationManager.ConnectionStrings["CustomerInformation"].ConnectionString);
 }
 
 public List<Customer> GetAll()
 {
  return this._db.Query<Customer>("SELECT * From Customer;").ToList();
 }

 public Customer FindById(int Id)
 {
  return this._db.Query("SELECT * FROM Customer WHERE CustomerID=@Id", new { Id = Id }).FirstOrDefault();
 }

 public bool AddCustomer(Customer customer)
 {
  SqlParameter[] parameters = {
      new SqlParameter("@CompanyName",customer.CompanyName),      
      new SqlParameter("@Address",customer.Address),
      new SqlParameter("@City",customer.City),
      new SqlParameter("@State",customer.State),
      new SqlParameter("@IntroDate",customer.IntroDate),
      new SqlParameter("@CreditLimit",customer.CreditLimit)};

  string query = "INSERT INTO Customer(CompanyName,Address,City,State,IntroDate,CreditLimit)" 
       + " Values(@CompanyName,@Address,@City,@State,@IntroDate,@CreditLimit)";

  var args = new DynamicParameters(new { });
  parameters.ToList().ForEach(p => args.Add(p.ParameterName, p.Value));
  try
  {
   this._db.Query<Customer>(query, args).SingleOrDefault();
  }
  catch (Exception)
  {
   return false;
  }

  return true;
 }

 public bool UpdateCustomer(Customer customer)
 {
  SqlParameter[] parameters = {
      new SqlParameter("@CustomerID",customer.CustomerID),
      new SqlParameter("@CompanyName",customer.CompanyName),      
      new SqlParameter("@Address",customer.Address),
      new SqlParameter("@City",customer.City),
      new SqlParameter("@State",customer.State),
      new SqlParameter("@IntroDate",customer.IntroDate),
      new SqlParameter("@CreditLimit",customer.CreditLimit)};

  string query = " UPDATE Customer SET CompanyName = @CompanyName,Address = @Address, "
      + " City = @City,State = @State,IntroDate = @IntroDate,CreditLimit = @CreditLimit"
      + " WHERE CustomerID = @CustomerID";

  var args = new DynamicParameters(new { });
  parameters.ToList().ForEach(p => args.Add(p.ParameterName, p.Value));
  try
  {
   this._db.Execute(query, args);
  }
  catch (Exception)
  {
   return false;
  }

  return true;
 }

 public bool DeleteCustomer(int Id)
 {
  int deletedCustomer = this._db.Execute("DELETE FROM Customer WHERE CustomerID = @Id", new { Id = Id });
  return deletedCustomer > 0;
 }
}

CustomerService.cs This class will be used by the WebForm page. So instead of calling the repository class directly, the service class serves as middle tier between the ASPX page and Repository class.
public class CustomerService
{

 ICustomerRepository _repository;

 public CustomerService()
 {
  _repository = new CustomerRepository();
 }

 public List<Customer> GetAll()
 {
  return _repository.GetAll();
 }

 public Customer FindById(int Id)
 {
  return _repository.FindById(Id);
 }

 public bool AddCustomer(Customer customer)
 {
  return _repository.AddCustomer(customer);
 }

 public bool UpdateCustomer(Customer customer)
 {
  return _repository.UpdateCustomer(customer);
 }

 public bool DeleteCustomer(int Id)
 {
  return _repository.DeleteCustomer(Id);
 }
}
Next, we add a WebForm page to the project that will demonstrate Create/Update/Delete on dummy records using the CustomerService.cs class. This page does not apply any validation so it's up to you to modify the code by applying server or client side validations.
ASPX Code
<table id="tblEntryForm">
 <tr>
  <td colspan="3">
   <div>Customer Information Entry Form</div>
  </td>
 </tr>
 <tr>
  <td>
   CompanyName:
  </td>
  <td>                    
   <asp:TextBox ID="txtCompanyName"  runat="server" Width="150" />
  </td>
 </tr>
 <tr>                
  <td>
   Address:                    
  </td>
  <td>
   <asp:TextBox ID="txtAddress"  runat="server" Width="150" />
  </td>
 </tr>
 <tr>                
  <td>
   City:                    
  </td>
  <td>
   <asp:TextBox ID="txtCity"  runat="server" Width="150" />
  </td>
 </tr>
  <tr>                
  <td>
   State:                    
  </td>
  <td>
   <asp:TextBox ID="txtState"  runat="server" Width="150" />
  </td>
 </tr>
  <tr>                
  <td>
   Intro Date:                    
  </td>
  <td>
   <asp:TextBox ID="txtIntroDate"  type="date" runat="server" Width="150" />
  </td> 
 </tr>
  <tr>                
  <td>
   Credit Limit:                    
  </td>
  <td>
   <asp:TextBox ID="txtCreditLimit"  runat="server" Width="150" />
  </td>                  
 </tr>
 <tr>                
  <td colspan="2">
   <asp:Button ID="btnSubmit" runat="server" Text="Save" OnClick="btnAdd_Click"/>
  </td>
 </tr>
</table>
<div>
<br />
<asp:GridView ID="gvCustomer" ValidateRequestMode="Enabled" runat="server" AllowPaging="True" AutoGenerateColumns="False" DataKeyNames="CustomerID" 
 BackColor="White" BorderColor="#3366CC" BorderStyle="None" BorderWidth="1px" CellPadding="4" OnPageIndexChanging="gvCustomer_PageIndexChanging"
 OnRowDataBound="OnRowDataBound" OnRowEditing="OnRowEditing" OnRowCancelingEdit="OnRowCancelingEdit"
 OnRowUpdating="OnRowUpdating" OnRowDeleting="OnRowDeleting" EmptyDataText="Empty Customer Database">
 <Columns>                
  <asp:TemplateField HeaderText="Company Name" ItemStyle-Width="130">
   <ItemTemplate>
    <asp:Label ID="lblCompanyName" runat="server" Text='<%# Eval("CompanyName") %>'></asp:Label>
   </ItemTemplate>
   <EditItemTemplate>
    <asp:TextBox ID="txtCompanyName1"  runat="server" Text='<%# Eval("CompanyName") %>'></asp:TextBox>
   </EditItemTemplate>
  </asp:TemplateField>
  <asp:TemplateField HeaderText="Address" ItemStyle-Width="100">
   <ItemTemplate>
    <asp:Label ID="lblAddress" runat="server" Text='<%# Eval("Address") %>'></asp:Label>
   </ItemTemplate>
   <EditItemTemplate>
    <asp:TextBox ID="txtAddress1"  runat="server" Text='<%# Eval("Address") %>'></asp:TextBox>
   </EditItemTemplate>
  </asp:TemplateField>
  <asp:TemplateField HeaderText="City" ItemStyle-Width="100">
   <ItemTemplate>
    <asp:Label ID="lblCity" runat="server" Text='<%# Eval("City") %>'></asp:Label>
   </ItemTemplate>
   <EditItemTemplate>
    <asp:TextBox ID="txtCity1"  runat="server" Text='<%# Eval("City") %>'></asp:TextBox>
   </EditItemTemplate>
  </asp:TemplateField>
  <asp:TemplateField HeaderText="State" ItemStyle-Width="100">
   <ItemTemplate>
    <asp:Label ID="lblState" runat="server" Text='<%# Eval("State") %>'></asp:Label>
   </ItemTemplate>
   <EditItemTemplate>
    <asp:TextBox ID="txtState1"  runat="server" Text='<%# Eval("State") %>'></asp:TextBox>
   </EditItemTemplate>
  </asp:TemplateField>
  <asp:TemplateField HeaderText="Intro Date" ItemStyle-Width="100">
   <ItemTemplate>
    <asp:Label ID="lblIntroDate" runat="server" Text='<%# Eval("IntroDate", "{0:yyyy-MM-dd}") %>'></asp:Label>
   </ItemTemplate>
   <EditItemTemplate>
    <asp:TextBox ID="txtIntroDate1"  runat="server" Text='<%# Eval("IntroDate") %>'></asp:TextBox>
   </EditItemTemplate>
  </asp:TemplateField>
  <asp:TemplateField HeaderText="Credit Limit" ItemStyle-Width="100">
   <ItemTemplate>
    <asp:Label ID="lblCreditLimit" runat="server" Text='<%# Eval("CreditLimit", "{0:N2}") %>'></asp:Label>
   </ItemTemplate>
   <EditItemTemplate>
    <asp:TextBox ID="txtCreditLimit1"  runat="server" Text='<%# Eval("CreditLimit") %>'></asp:TextBox>
   </EditItemTemplate>
  </asp:TemplateField>
  <asp:CommandField ShowEditButton="True" ShowDeleteButton="True" ButtonType="Button"/>       
 </Columns>
 <FooterStyle BackColor="#99CCCC" ForeColor="#003399" />
 <HeaderStyle BackColor="#003399" Font-Bold="True" ForeColor="#CCCCFF" />
 <PagerStyle BackColor="#99CCCC" ForeColor="#003399" HorizontalAlign="Left" />
 <RowStyle BackColor="White" ForeColor="#003399" />
 <SelectedRowStyle BackColor="#009999" Font-Bold="True" ForeColor="#CCFF99" />
 <SortedAscendingCellStyle BackColor="#EDF6F6" />
 <SortedAscendingHeaderStyle BackColor="#0D4AC4" />
 <SortedDescendingCellStyle BackColor="#D6DFDF" />
 <SortedDescendingHeaderStyle BackColor="#002876" />
</asp:GridView>
<asp:Label ID="lblMessage" runat="server"></asp:Label>
Code Behind
public partial class CRUDSampleNoValidation : System.Web.UI.Page
{
 private Customer customer;
 private bool result = false;
 private CustomerService customerService = new CustomerService();

 protected void Page_Load(object sender, EventArgs e)
 {
  if (!Page.IsPostBack)
  {
   BindGrid();
  }
 }

 protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
 {
  if (e.Row.RowType == DataControlRowType.DataRow)
  {
   string item = e.Row.Cells[0].Text;
   foreach (Button button in e.Row.Cells[6].Controls.OfType<Button>())
   {
    if (button.CommandName == "Delete")
    {
     button.Attributes["onclick"] = "if(!confirm('Do you want to delete record?')){ return false; };";
    }
   }
  }
 }

 protected void OnRowDeleting(object sender, GridViewDeleteEventArgs e)
 {
  int CustomerId = Convert.ToInt32(gvCustomer.DataKeys[e.RowIndex].Values[0]);
  result = customerService.DeleteCustomer(CustomerId);
  if (result)
  {
   lblMessage.Text = string.Empty;
   lblMessage.Text = "Successfully deleted the reccord!";
  }

  BindGrid();
 }

 protected void OnRowEditing(object sender, GridViewEditEventArgs e)
 {
  gvCustomer.EditIndex = e.NewEditIndex;
  lblMessage.Text = string.Empty;
  this.BindGrid();
 }

 protected void OnRowUpdating(object sender, GridViewUpdateEventArgs e)
 {
  customer = new Customer();
  GridViewRow row = gvCustomer.Rows[e.RowIndex];
  customer.CustomerID = Convert.ToInt32(gvCustomer.DataKeys[e.RowIndex].Values[0]);
  customer.Address = (row.FindControl("txtAddress1") as TextBox).Text;
  customer.City = (row.FindControl("txtCity1") as TextBox).Text;
  customer.State = (row.FindControl("txtState1") as TextBox).Text;
  customer.CompanyName = (row.FindControl("txtCompanyName1") as TextBox).Text;
  customer.IntroDate = Convert.ToDateTime((row.FindControl("txtIntroDate1") as TextBox).Text);
  customer.CreditLimit = Convert.ToDecimal((row.FindControl("txtCreditLimit1") as TextBox).Text);
  result = customerService.UpdateCustomer(customer);

  if (result)
  {
   lblMessage.Text = string.Empty;
   lblMessage.Text = "Successfully updated the reccord";
  }

  gvCustomer.EditIndex = -1;
  BindGrid();
 }

 protected void gvCustomer_PageIndexChanging(object sender, GridViewPageEventArgs e)
 {
  gvCustomer.PageIndex = e.NewPageIndex;
  lblMessage.Text = string.Empty;
  BindGrid();
 }

 protected void OnRowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
 {
  gvCustomer.EditIndex = -1;
  lblMessage.Text = string.Empty;
  this.BindGrid();
 }

 protected void btnAdd_Click(object sender, EventArgs e)
 {
  customer = new Customer();
  customer.Address = txtAddress.Text;
  customer.City = txtCity.Text;
  customer.CompanyName = txtCompanyName.Text;
  customer.State = txtState.Text;
  customer.CreditLimit = Convert.ToDecimal(txtCreditLimit.Text);
  customer.IntroDate = Convert.ToDateTime(txtIntroDate.Text);
  result = customerService.AddCustomer(customer);

  if (result)
  {
   lblMessage.Text = string.Empty;
   lblMessage.Text = "Successfully added a new reccord";
  }

  BindGrid();
 }

 private void BindGrid()
 {
  gvCustomer.DataSource = customerService.GetAll();
  gvCustomer.DataBind();
 }           
}
Screenshots The entire project and create table script are available for download in Github Repository.

Sunday, February 19, 2017

ASP.NET Webform multiple server validation controls wide space issue.

Good day!

When working with multiple server validation controls for one input control, you often encountered wide space gap if the validation controls are placed inside a single container such as div or td such as the sample screenshot below.
The solution to remove the wide gap is to set the Display property of the validation controls to Dynamic.
<td>
 <asp:TextBox ID="txtCreditLimit" runat="server" Width="150" />
 <asp:RegularExpressionValidator ValidationGroup="valCustomerEntry" Display="Dynamic" ID="regexpName" runat="server" ErrorMessage="The value entered is not valid" 
   ControlToValidate="txtCreditLimit"  ValidationExpression="\d+(\.\d*)?|\.\d+" ForeColor="Red"/>
 <asp:RequiredFieldValidator ValidationGroup="valCustomerEntry" Display="Dynamic" ID="RequiredFieldValidator6" runat="server" ErrorMessage="Credit Limit cannot be blank" ControlToValidate="txtCreditLimit" ForeColor="Red"></asp:RequiredFieldValidator>  
</td>     
Notice that the Credit Limit field has multiple validation controls namely RequiredFieldValidator and RegularExpressionValidator.

Thursday, February 16, 2017

Serialize .NET Classes with Inheritance to XML

Good day!
Here's a simple example on how to Serialize .NET classes that applied the concept of Inheritance to XML. Given the model classes below:
[Serializable]
public class Employee
{
 public int EmployeeId { get; set; }
 public string Name { get; set; }
 public string Address { get; set; }
}

[Serializable]
public class Utility : Employee
{
 public string Category { get; set; }
}

[Serializable]
public class Supervisor : Employee
{
 public int OverrideCode { get; set; }
}
The code to populate and serialize the objects to XML is presented here using XmlSerializer class:
List<Employee> employees = new List<Employee>();

Supervisor supervisor1 = new Supervisor();
supervisor1.Name = "Michael";
supervisor1.Address = "Manila";
supervisor1.EmployeeId = 11111;
supervisor1.OverrideCode = 234;
employees.Add(supervisor1);

Utility utility1 = new Utility();
utility1.Name = "Erick";
utility1.Address = "Masbate";
utility1.EmployeeId = 33333;
utility1.Category = "Bus Driver";
employees.Add(utility1);

Supervisor supervisor2 = new Supervisor();
supervisor2.Name = "James";
supervisor2.Address = "Cebu";
supervisor2.EmployeeId = 22222;
supervisor2.OverrideCode = 567;
employees.Add(supervisor2);


try
{
 XmlSerializer serializeEmployees = new XmlSerializer(typeof(List<Employee>), 
  new Type[] { typeof(Supervisor), typeof(Utility) });
 serializeEmployees.Serialize(File.Create(@"C:\Codes\Employees.xml"), employees);
}
catch (Exception )
{
 //TODO
}
Note: If you do not specify the types in the second parameter of Serialize() method, this will create an exception {"The type [Namespace].Class was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."}
XML Output
<?xml version="1.0"?>
<ArrayOfEmployee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Employee xsi:type="Supervisor">
    <EmployeeId>11111</EmployeeId>
    <Name>Michael</Name>
    <Address>Manila</Address>
    <OverrideCode>234</OverrideCode>
  </Employee>
  <Employee xsi:type="Utility">
    <EmployeeId>33333</EmployeeId>
    <Name>Erick</Name>
    <Address>Masbate</Address>
    <Category>Bus Driver</Category>
  </Employee>
  <Employee xsi:type="Supervisor">
    <EmployeeId>22222</EmployeeId>
    <Name>James</Name>
    <Address>Cebu</Address>
    <OverrideCode>567</OverrideCode>
  </Employee>
</ArrayOfEmployee>

Wednesday, February 15, 2017

$.validator.unobtrusive.adapters.addBool() not working in ASP.NET MVC 5 CheckBoxFor().

Hello,
I was testing the addBool() method of jQuery validation to a CheckBoxFor() which will prevent the form from submitting if the checkbox is unchecked. To my surprise, the JavaScript code below doesn't work.
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/jqueryval")
    <script type="text/javascript" language="javascript">
        (function ($) {

            $.validator.addMethod('checkboxrequired', function (value, elem) {
                var $elem = $(elem);
                if ($elem.prop('type') == 'checkbox') {
                    if (!$elem.prop('checked')) {
                        return false;
                    }
                }
                return true;
            });
            $.validator.unobtrusive.adapters.addBool('checkboxrequired', 'required');
            
        }(jQuery));
    </script>
After series of investigation, I discovered that the jQuery and jQueryValidation scripts have been rendered twice on the page since it has reference to a Layout page that also rendered the jQuery and jQueryValidation scripts.

To fix the issue, I removed the statements @Scripts.Render("~/bundles/jquery") and @Scripts.Render("~/bundles/jqueryval") in my Validation.cshtml page. In my Layout.cshtml page, I transferred the rendering of jQuery and jQueryValidation statements just below the @Scripts.Render("~/bundles/modernizr") statement.
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/bundles/jqueryval")

Screenshot
That's it. :-)