Wednesday, July 12, 2017

Calling Web API not working in AngularJS using $http service

When calling ASP.NET Web API service inside the solution, I encountered an issue that is 404 not found. Given that this issue persists, I tried adding a forward slash before the url in the Ajax call which works.
AngularJS
$http({
        //url: "EmployeeRoute/GetAll", //404 error
 url: "/EmployeeRoute/GetAll",
 dataType: 'json',
 method: 'POST',
 data: GetAll,
 headers: {
  "Content-Type": "application/json"
 }
}).then(function (resp) {
 if (typeof resp.data === 'object') {
  return resp.data;
 } else {
  return $q.reject(response.data);
 }
}, function (err) {
 return $q.reject(err.data);
});
I also make sure that the WebApiConfig.Register method gets executed in Global.asax.cs.
Global.asax.cs
protected void Application_Start(object sender, EventArgs e)
{
 GlobalConfiguration.Configure(WebApiConfig.Register);
}

Monday, July 10, 2017

AngularJS $http service returns html instead of JSON string

Good day!
I've been trying to consume an ASP.NET Web Method using AngularJS $http service and all I get from the response is the html page source instead of string data. After investigating and doing some searching, the workaround is to set the responseType to json and pass an empty data to the Web Method given that the Web Method has no parameter.
var myapp = angular.module('myApp', []);
myapp.controller('ctrl', function ($scope, $http) {
 $http({
  url: "63MakeAjaxCallAndReturnJSONWebService.aspx/HelloWorld",
  dataType: 'json',
  method: "POST",
  responseType: 'json',
  data: {},
  headers: { "Content-Type": "application/json;" }
 }).then(function (response) {
  $scope.value = response.data.d;
 });
});
And also declare the Web Method as static.
[WebMethod()]
public static string HelloWorld()
{
 return "Hello World!";
}

Saturday, July 8, 2017

ASP.NET 4.5 Has Not Been Registered on the Web Server (Visual Studio 2012)

This issue "ASP.NET 4.5 Has Not Been Registered on the Web Server" occurred when I opened an asp.net application built with Visual Studio 2012 recently when I installed Visual Studio 2015 in my laptop with a Windows 8 operating system. Given that this happens I assume that some settings may have been updated or corrupted by the recent version of VS. The solutions I have tried included registering asp.net through Visual Studio command tools with no effect.
After searching through the web, I found a solution which is to download the hotfix for VS 2012 here Unexpected dialog box appears when you open projects in Visual Studio 2012 after you install the .NET Framework 4.5.3. After downloading and installing the hotfix, the issue was resolved.

Thursday, July 6, 2017

Custom DateTimePicker Control With Background Color and Icon

Hello
Here's a custom DateTimePicker with background color and image icon instead of using the ComboBoxRenderer class. The icon is an image that is added to the project as part of it's resource. The adding of icon is processed through the WndProc method while the setting of background color is handled in the OnPaint() event. Notice that in the constructor, the SetStyle()'s parameters are ControlStyles.UserPaint so that the control paints itself and true to apply the specified style to the control.
public class DateTimePickerWithBackground : DateTimePicker
{
 private Bitmap _bmp;

 enum BorderSize
 {
  One = 1,
  Two = 2
 };

 public DateTimePickerWithBackground()
 {
  _bmp = new Bitmap(ClientRectangle.Height, ClientRectangle.Width);
  this.SetStyle(ControlStyles.UserPaint, true);
 }

 protected override void WndProc(ref Message m)
 {
  base.WndProc(ref m);
  if (m.Msg == 0xf) //WM_PAINT message
  {   
   Graphics g = Graphics.FromHwnd(m.HWnd);
   g.DrawImage(_bmp, ClientRectangle.Width - Convert.ToInt32(9 * ClientRectangle.Width / 100), 2);
   g.Dispose();
  }
 }

 protected override void OnPaint(PaintEventArgs e)
 {
  base.OnPaint(e);
  e.Graphics.FillRectangle(new SolidBrush(Color.LawnGreen), ClientRectangle);
  ControlPaint.DrawBorder(e.Graphics, ClientRectangle,
          Color.LightGray, (int)BorderSize.One, ButtonBorderStyle.Solid,
          Color.LightGray, (int)BorderSize.One, ButtonBorderStyle.Solid,
          Color.LightGray, (int)BorderSize.One, ButtonBorderStyle.Solid,
          Color.LightGray, (int)BorderSize.One, ButtonBorderStyle.Solid);
  TextRenderer.DrawText(e.Graphics, Text, Font, Rectangle.FromLTRB(0, 0, Width - Height, Height), 
   SystemColors.ControlText);
  Image img = Properties.Resources.calendar_picker;
  _bmp = new Bitmap(img, new Size(img.Width, img.Height));
 }
}
Output
The source is available in Github. :-)

Wednesday, July 5, 2017

Load Images in a Windows Form Custom Control

Good day!
Often times when developing custom controls you will add images or icons to enhance the UI through the Bitmap class. But when getting the image from file using Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + @"\calendar.png") you may encounter issues such as "path is null" since the path pointed by the BaseDirectory isn't the executable path. A simple workaround is to set the path of the image using hardcoded like Image.FromFile(@"C:\Images\ProjectX\calendar.png"). While this is acceptable, it is ugly to look at and may cause potential issues once the image has been transferred to another location. An accepted solution is to add the image as a project resource then reference it in the custom control code. To accomplish that, here are the steps.
* Right Click on the Project -> Properties
* In Resources, select Add Resource Dropdown -> Add Existing File
- Choose the image or icon to be used as resource. Once done, it will resemble as the photo below.
* In your custom control code, you can access the resource using Properties.Resources.Resource_Name
protected override void OnPaint(PaintEventArgs e)
{
 base.OnPaint(e);
 Image img = Properties.Resources.calendar_picker;
 bmp = new Bitmap(img, new Size(img.Width, img.Height));
}

Done! :-)

Tuesday, July 4, 2017

MVVM Basics with TextBlock Control

Hello,
This post is based on the article Understanding the basics of MVVM design pattern. The author demonstrated the basics of MVVM using TextBlock controls. However, the code samples have several issues and in order for the sample application to work, I revise them with the following changes.
BindableBase.cs - since SetProperty method uses T in it's parameter, you also need to reference T in your classname.
public class BindableBase<T> : INotifyPropertyChanged
{
   ...
}
MainPageViewModel.cs - update the code in the constructor to bind a single object to the TextBlock controls.
public class MainPageViewModel : BindableBase<Book>
{
 private Book _book;

 public Book Book
 { 
  get
  {
   return _book;
  } 
  set
  {
   SetProperty(ref _book, value);
  } 
 }
 
 public MainPageViewModel()
 {           
  Book = new Book()
  {
   Title = "Harry Potter",
   Author = "J. K. Rowling",
   Category = "Young-adult fiction",
   Language = "English"
  };
 }
}
XAML - Prefix the properties with the classname when binding it with the control
<TextBlock x:Name="bookTitle" HorizontalAlignment="Left" TextWrapping="Wrap" Grid.Row="0" Width="500" Text="{Binding Book.Title}" />


Hope it helps! :-)

Tuesday, June 27, 2017

Export ASP.NET GridView To Excel and Preserve Leading Zeros

Hi,
There was a question raised on how to export data from ASP.NET Gridview to Microsoft Excel and preserve leading zeros of numeric values. A workaround that we have is to insert an   character before the cell value if that value starts with zero (0). So if the value starts with zero such as 0001, the result would be " 0001". Thus when exported to Excel, the leading zero is kept.
cell.Text = string.Format("&nbsp;{0}", cell.Text);
A suggested solution is to insert a Tab character ( ) but this fails on some occasions. After doing some research, replacing the tab character with &ensp; or &emsp; would also fix the issue.
cell.Text = string.Format("&ensp;{0}", cell.Text);
//or
cell.Text = string.Format("&emsp;{0}", cell.Text);

ASP.NET GridView Export Excel Report
Cheers!

Sunday, June 25, 2017

WPF DataGrid Databinding using MVVM Pattern

Hello,

I've been developing WPF applications before but not having applied the MVVM design pattern and have been wanting to create a simple program that loads data into the DataGrid control. According to Wikipedia, the components of an MVVM pattern are:
Model
Model refers either to a domain model, which represents real state content (an object-oriented approach), or to the data access layer, which represents content (a data-centric approach).
View
As in the MVC and MVP patterns, the view is the structure, layout, and appearance of what a user sees on the screen.
View model
The view model is an abstraction of the view exposing public properties and commands. Instead of the controller of the MVC pattern, or the presenter of the MVP pattern, MVVM has a binder. In the view model, the binder mediates communication between the view and the data binder.The view model has been described as a state of the data in the model.
Binder
Declarative data and command-binding are implicit in the MVVM pattern. In the Microsoft solution stack, the binder is a markup language called XAML.
Given the explanations above, here's the code that applies a plain MVVM approach.
ViewModel (CustomerViewModel.cs)
The model used here is the Northwind Customer
public class CustomerViewModel : ViewModelBase
    {
        private ObservableCollection<Customer> _cusGridData;
        private NorthwindEntities _context;

        public CustomerViewModel()
        {
            _context = new NorthwindEntities();
            LoadInitialData();
        }

        private void LoadInitialData(){
            CustomerData = new ObservableCollection<Customer>(from c in _context.Customers select c);
        }

        public ObservableCollection<Customer> CustomerData
        {
            get 
            { 
                return _cusGridData; 
            }
            set
            {
                _cusGridData = value;
                OnPropertyChanged("CustomerData");
            }
        }
    }
View (XAML)
<Window x:Class="WPFMVVMDataGrid.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ViewModel="clr-namespace:WPFMVVMDataGrid"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <ViewModel:CustomerViewModel/>
    </Window.DataContext>
    <Grid>
        <DataGrid ItemsSource="{Binding Path=CustomerData}" x:Name="dgCustomer"
             AutoGenerateColumns="False"
             SelectionMode="Single"
             SelectionUnit="FullRow"
             GridLinesVisibility="Horizontal"
             CanUserDeleteRows="True"
             CanUserAddRows="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Width="SizeToCells" MinWidth="125" Binding="{Binding CustomerID}" />
                <DataGridTextColumn Header="Age" Width="SizeToCells" MinWidth="200" Binding="{Binding ContactName}"/>
                <DataGridTextColumn Header="Description" Width="SizeToCells" MinWidth="200" Binding="{Binding Address}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
For the details on how MVVM works see this thread WPF Having Trouble with binding a Datagrid control on load

Source Code: DataGridMVVMWPF In Github

Cheers! :-)

Monday, June 5, 2017

Disable button in AngularJS using ng-disabled on it's first page load in ASP.NET MVC

Hello,
One might notice that during page load of an ASP.NET MVC application, the button with ng-disabled attribute and have values such as $invalid or $dirty does not disable the button. Thus, this will enable the user to submit the form with empty values to the controller method. In order to disable the button on page load, add $pristine values in the ng-disabled attribute such as the code below.
Original Code
<input type="submit" id="btnAddEmployee" class="btn btn-primary" value="Save" ng-click="Save()" 
 ng-disabled="AddEmp.fname.$dirty && AddEmp.fname.$invalid
     || AddEmp.lname.$dirty && AddEmp.lname.$invalid
     || AddEmp.salary.$dirty && AddEmp.salary.$invalid" />
Modified code with $pristine
<input type="submit" id="btnAddEmployee" class="btn btn-primary" value="Save" ng-click="Save()" 
 ng-disabled="AddEmp.fname.$dirty && AddEmp.fname.$invalid || AddEmp.fname.$pristine
     || AddEmp.lname.$dirty && AddEmp.lname.$invalid || AddEmp.lname.$pristine
     || AddEmp.salary.$dirty && AddEmp.salary.$invalid || AddEmp.salary.$pristine" />

Saturday, June 3, 2017

$location.path() method not reloading new data in ASP.NET MVC Web API with AngularJS

Hello,
I was trying to integrate AngularJS into a simple ASP.NET MVC Web API application with Save functionality. Basically, when you have finished posting data the next logic will be to redirect the user to the display all page. However, I stumbled into an issue in which the $location service does not reload data.
According to the docs,the $location service allows you to change only the URL; it does not allow you to reload the page. So after placing breakpoints in the Api Controller, I noticed that the GetAll() method is called first next is the Save() method. The solution to this dilemma is to transfer the $location.path() method inside the success function so that the Save() method in the Api Controller is executed first.
Code With Issue: $location.path() is outside the success function.
 $scope.Add = function () {
  $http({ method: "POST", data: $scope.employee, url: "/api/employees" })
  .then(function (response) {
   $scope.employees = response.data;
   $scope.employee = {
    "FirstName": "",
    "LastName": "",
    "Age": "",
    "Salary": ""
   };   
  });
  $location.path('/allemployees'); 
}
Fix: $location.path() is inside the success function.
$scope.Add = function () {
  $http({ method: "POST", data: $scope.employee, url: "/api/employees" })
  .then(function (response) {
   $scope.employees = response.data;
   $scope.employee = {
    "FirstName": "",
    "LastName": "",
    "Age": "",
    "Salary": ""
   };
   $location.path('/allemployees'); 
  });  
}

Cheers! :-)

Wednesday, May 17, 2017

Adding ASP.NET 5 Templates to VS 2015

Good day!
One might notice that the ASP.NET 5 templates are not visible when creating a new Web Application Project in Visual Studio 2015 given that this is a fresh installation of the software. So to add the ASP.NET 5 Templates, download the ASP.NET 5 run-time tools Microsoft ASP.NET and Web Tools 2015 (RC) – Visual Studio 2015 and proceed with the setup. Restart your machine afterwards.
That's it.. :-)

This version of Visual Studio requires the April 2014 update to Windows 8.1 (VS 2015)

Hello,
Now that I've got the time to install Visual Studio 2015 Enterprise on my laptop with Windows 8.1 Operating System I decided to give it a go. That's when the moment I opened the installer file, an issue pops out of the screen with the description "This version of Visual Studio requires the April 2014 update to Windows 8.1 and Windows Server 2012 R2 known as KB2919355".
The solution to this issue can easily be found at stackoverflow. But missing the links of the packages needed to resolve the problem. A step by step example is presented below.
1. Download update package 2919442 and install update to your pc. This is the pre-requisite update of package 2919355
   x86
   x64
2. Download update package 2919355 and install update to your pc.
   x86
   x64
3. After those updates have been installed, restart the computer for the updates to take effect.
Cheers! :-)

Monday, May 1, 2017

How to Post JSON data with WebRequest in .NET

Hello,
There was a question on how to post a JSON data using the WebRequest class given that using Ajax, the post data would look like this.
data: '{ "age": "78", "weight": "51" }'
In .NET, you need to store the JSON data into a string object and escape those double quotes before passing it to the WebRequest object.
C#.NET
string postData = "{ \"age\": \"78\", \"weight\": \"51\" }";
VB.NET
Dim postData As String = "{ ""age"": ""78"", ""weight"": ""51"" }"

Cheers! :-)

Wednesday, April 12, 2017

Sorting of <li> elements using jQuery sort() not working (refresh page only) in ASP.NET

Given the simple sorting code below which changes the order of <li> elements to ascending order and assuming that the text content of each li elements are numbers.
$(function () {
 $('#sortList').click(function (e) {
  // Select all the li items
  var numbersList = $('#numbersList li');
  
  numbersList.sort(function (a, b) {
   return parseInt($(a).text(), 10) > parseInt($(a).text(), 10);
  }).appendTo(numbersList.parent());
 });
});
The code should work only to find out that the page will only refresh after the button click. And then the re-arranging of the elements are discarded. The simple fix to this issue is to add the preventDefault() to prevent the button's default behavior that is to post back.
$(function () {
 $('#sortList').click(function (e) {
         //add preventDefault() to reflect the changes after sorting
  e.preventDefault();
  // Select all the li items
  var numbersList = $('#numbersList li');
  
  numbersList.sort(function (a, b) {
   return parseInt($(a).text(), 10) > parseInt($(a).text(), 10);
  }).appendTo(numbersList.parent());
 });
});
Fiddle: Sort Unordered list items

Saturday, April 8, 2017

$.getJSON() not loading JSON file within Visual Studio Project in ASP.NET WebForms

Hi,
I was trying to load a JSON file located within my Visual Studio project using $.getJSON(), however the code below doesn't work as expected.
$.getJSON('/Assets/misc/employee.json', function (data) {
 alert('processing!');
})
.done(function (r) {
 alert(r.message);
})
.fail(function (s) {
 alert('oops the file is missing!');
});
After investigating for a few hours, I tested the local path of the JSON file such as http://localhost:3766/Assets/misc/employee.json and the result was an exception "HTTP Error 404.3 - Not Found The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If the file should be downloaded, add a MIME map.".
I remember the solution in one of my ASP.NET project was to set the MimeMap in the web.config inside the system.webServer element. After setting the MimeMap for json files, I can now load local JSON files using $.getJSON().
<system.webServer>
 <staticContent>
   <mimeMap fileExtension=".json" mimeType="application/json" />
 </staticContent>
</system.webServer>

:-)

Friday, April 7, 2017

Visual Studio showing only "Attach" and no Debug options in ASP.NET Project

Hello,
Last night my computer shuts down unexpectedly due to power outage and when I opened an ASP.NET project this morning, it only shows "Attach" in the debug options. Running to different browsers such as Google Chrome, Firefox and Internet Explorer were missing.
After a few search, I encountered a solution which is to set again the ASP.NET Project as StartUp Project by right clicking the project and selecting the option Set as StartUp Project.
That's it.. :-)

Tuesday, March 21, 2017

Set an Html.RadioButtonFor() helper as default Checked

Good day!
Given that you have to set a radio button as default checked in razor view, a code to do that is presented below using conditional ternary operator. However, there is an issue with the code shown below. Even if you set the checked property with empty string, it will still render as checked during run-time.
@foreach (var answer in item.Answers)
{
 <p>
  @Html.RadioButtonFor(m => answer.ID, true,
     new
     {
      @disabled = "true",
      @Name = item.ID,
      @checked = (answer.IsCorrect) ? "checked" : ""
     })@answer.AnswerText
 </p>
}           
To ignore that issue, there are several ways to fix that. First one is to use if statement in the view itself.
@foreach (var answer in item.Answers)
{
 <p>
  @if (answer.IsCorrectAnswer)
  {
   @Html.RadioButtonFor(m => answer.ID, true,
     new
     {
      @disabled = "true",
      @Name = item.ID,
      @checked = "true"
     })@answer.AnswerText

  }
  else
  {

   @Html.RadioButtonFor(m => answer.ID, false,
     new
     {
      @disabled = "true",
      @Name = item.ID,
     })@answer.AnswerText
  }
 </p>
}
And another one is to create a custom RadioButton helper.
public static MvcHtmlString RadioButtonFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, 
 Expression<Func<TModel, TValue>> expression, object value, object htmlAttributes, bool checkedState)
{
 var htmlAttributeDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

 TagBuilder tagbuilder = new TagBuilder("input");
 tagbuilder.Attributes.Add("value", value.ToString());
 tagbuilder.Attributes.Add("type", "radio");
 tagbuilder.Attributes.Add("id", ExpressionHelper.GetExpressionText(expression));

 if (checkedState)
 {
  tagbuilder.Attributes.Add("checked", "checked");
 }

 foreach (var item in htmlAttributeDictionary)
 {
  tagbuilder.Attributes.Add(item.Key, item.Value.ToString());
 }

 return MvcHtmlString.Create(tagbuilder.ToString(TagRenderMode.Normal));
}
Usage of custom HtmlHelper
@Html.RadioButtonFor(m => answer.ID, (answer.IsCorrectAnswer) ? true : false, new
{
 @disabled = "true",
 @Name = String.Format("Question_{0}", item.ID),
}, answer.IsCorrectAnswer)@answer.Text

Cheers! :-)

Friday, March 17, 2017

Handle GridView TemplateFields null values in aspx markup

Hello,
To handle null values in GridView TemplateFields through aspx/html markup rather than code-behind, you can simply use the language operators to those fields. One approach is to use the conditional ternary operator in C# and VB.NET. The sample codes below illustrates how to do in C# and VB.NET. For C#, use the (?) operator. While VB.NET uses If() operator.
C#.NET Code
 <asp:TemplateField HeaderText="Name" SortExpression="EmpName">
 <ItemTemplate>
    <asp:Label ID="lbl" runat="server" Text='<%# Eval("EmpName") %>'></asp:Label>
 </ItemTemplate>
 <EditItemTemplate>
  <asp:TextBox ID="txtEmployee" runat="server" Text='<%# Eval("EmpName") == System.DBNull.Value ? string.Empty : Eval("EmpName").ToString() %>' ></asp:TextBox>
 </EditItemTemplate>
</asp:TemplateField>
    
VB.NET Code
<asp:TemplateField HeaderText="Name" SortExpression="EmpName">
 <ItemTemplate>
    <asp:Label ID="lbl" runat="server" Text='<%# Eval("EmpName") %>'></asp:Label>
 </ItemTemplate>
 <EditItemTemplate>
  <asp:TextBox ID="txtEmployee" runat="server" Text='<%# If(IsDBNull(Eval("EmpName")), String.Empty, Eval("EmpName").ToString())%>' ></asp:TextBox>
 </EditItemTemplate>
</asp:TemplateField>

Cheers! :-)

Sunday, March 12, 2017

View in ASP.NET MVC not refreshing after calling Ajax Post in jQuery UI

Hello,
In an application wherein the controller is invoked using Ajax POST and that controller will redirect to a landing page such as Index after processing, an issue will occur such as the View of that landing page isn't updated or not refreshed. Normally, the View will be updated since the model is queried from the database.
[HttpPost]
public ActionResult Delete(int id)
{
 try
 {
  Customer customer = _customer.Customers.FirstOrDefault(t => t.CustomerID == id);
  if (customer != null)
  {
   _customer.Customers.Remove(customer);
   _customer.SaveChanges();
  }
 }
 catch
 {
  //TODO
 }

 return RedirectToAction("Index");
}
The fix for that is to change the RedirectToAction() statement to return the url of a landing page as JSON result. And in the ajax statement, add a statement that navigate to the url returned from the controller.
[HttpPost]
public ActionResult Delete(int id)
{
 try
 {
  Customer customer = _customer.Customers.FirstOrDefault(t => t.CustomerID == id);
  if (customer != null)
  {
   _customer.Customers.Remove(customer);
   _customer.SaveChanges();
  }
 }
 catch
 {
  //TODO
 }

 var url = this.Url.Action("Index", "Customer", null, Request.Url.Scheme);
 return Json(new { Url = url });
}
JavaScript Code:
$.post(url,"", function (data) {
 alert('Record successfully deleted from database!');
 window.location.href = data.Url
});
See related issue here: Return View() statement not redirecting to View in ASP.NET MVC using $.ajax() post.

Saturday, March 11, 2017

Url Variable Returns Forward Slash "/" instead of absolute Url in Controller Action

Hi,
When passing a url from a controller action to an Ajax $.post() result that is to navigate to the landing page, using the code below generates only a forward slash which is the root symbol instead of an absolute url. If the url value (/) will be used in window.location.href, it will cause an IIS page not found error.
var url = new UrlHelper(Request.RequestContext).Action("Index", "Customer");
return Json(new { Url = url });
So, to return the absolute url of the controller action in the current context, replace UrlHelper class with Url.Action() method. It is important to include the Request.Url.Scheme in the parameter to pass the correct protocol of the url. The code below will return an absolute url such as: http://localhost:7088 for the landing page.
var url = this.Url.Action("Index", "Customer", null, Request.Url.Scheme);
return Json(new { Url = url });

Wednesday, March 1, 2017

window.location.href not opening website

Hello,
The code below does not open the link, instead opens a blank page or IIS error. This issue occurs in all major browsers.
window.location.href  = 'www.nba.com';
In order to fix the issue,you must prepend the correct protocol before the website such as (http:// or https:// or ftp://). If the protocol is omitted, the link is interpreted as a file in the website.
window.location.href ='http://www.nba.com'; 

Cheers!

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.