Support us .Net Basics C# SQL ASP.NET ADO.NET MVC Slides C# Programs Subscribe Buy DVD

Part 7 - KnownType attribute in WCF

Suggested Videos
Part 4 - Single wcf service implementing multiple service contracts
Part 5 - How to make changes to wcf service without breaking clients
Part 6 - WCF DataContract and DataMember



If we have classes related by inheritance, the wcf service generally accepts and returns the base type. If you expect the service to accept and return inherited types, then use KnownType attribute.

There are other ways of associating known types, which we will discuss in next video session.



Code used in the demo:
SQL:
Alter table tblEmployee Add 
EmployeeType int, AnnualSalary intHourlyPay int, HoursWorked int

Alter procedure spGetEmployee  
@Id int  
as  
Begin  
 Select Id, Name, Gender, DateOfBirth, 
EmployeeType, AnnualSalary, HourlyPay, 
HoursWorked  
 from tblEmployee where Id = @Id  
End

Alter procedure spSaveEmployee  
@Id int,  
@Name nvarchar(50),  
@Gender nvarchar(50),  
@DateOfBirth DateTime,
@EmployeeType int,
@AnnualSalary int = null,
@HourlyPay int = null,
@HoursWorked int = null
as  
Begin  
 Insert into tblEmployee  
 values (@Id, @Name, @Gender, @DateOfBirth, 
@EmployeeType, @AnnualSalary, @HourlyPay, 
@HoursWorked)  
End

FullTimeEmployee.cs
namespace EmployeeService
{
    public class FullTimeEmployee : Employee
    {
        public int AnnualSalary { get; set; }
    }
}

PartTimeEmployee.cs
namespace EmployeeService
{
    public class PartTimeEmployee : Employee
    {
        public int HourlyPay { get; set; }
        public int HoursWorked { get; set; }
    }
}

Employee.cs
using System;
using System.Runtime.Serialization;

namespace EmployeeService
{
    [KnownType(typeof(FullTimeEmployee))]
    [KnownType(typeof(PartTimeEmployee))]
    [DataContract(Namespace = "http://pragimtech.com/Employee")]
    public class Employee
    {
        private int _id;
        private string _name;
        private string _gender;
        private DateTime _dateOfBirth;

        [DataMember(Order = 1)]
        public int Id
        {
            get { return _id; }
            set { _id = value; }
        }

        [DataMember(Order = 2)]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        [DataMember(Order = 3)]
        public string Gender
        {
            get { return _gender; }
            set { _gender = value; }
        }

        [DataMember(Order = 4)]
        public DateTime DateOfBirth
        {
            get { return _dateOfBirth; }
            set { _dateOfBirth = value; }
        }

        [DataMember(Order = 5)]
        public EmployeeType Type { get; set; }
    }

    public enum EmployeeType
    {
        FullTimeEmployee = 1,
        PartTimeEmployee = 2
    }
}

EmployeeService.cs
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace EmployeeService
{
    public class EmployeeService : IEmployeeService
    {
        public Employee GetEmployee(int Id)
        {
            Employee employee = null;
            string cs = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
            using (SqlConnection con = new SqlConnection(cs))
            {
                SqlCommand cmd = new SqlCommand("spGetEmployee", con);
                cmd.CommandType = CommandType.StoredProcedure;
                SqlParameter parameterId = new SqlParameter();
                parameterId.ParameterName = "@Id";
                parameterId.Value = Id;
                cmd.Parameters.Add(parameterId);
                con.Open();
                SqlDataReader reader = cmd.ExecuteReader();
                while (reader.Read())
                {
                    if ((EmployeeType)reader["EmployeeType"] == EmployeeType.FullTimeEmployee)
                    {
                        employee = new FullTimeEmployee
                        {
                            Id = Convert.ToInt32(reader["Id"]),
                            Name = reader["Name"].ToString(),
                            Gender = reader["Gender"].ToString(),
                            DateOfBirth = Convert.ToDateTime(reader["DateOfBirth"]),
                            Type = EmployeeType.FullTimeEmployee,
                            AnnualSalary = Convert.ToInt32(reader["AnnualSalary"])
                        };
                    }
                    else
                    {
                        employee = new PartTimeEmployee
                        {
                            Id = Convert.ToInt32(reader["Id"]),
                            Name = reader["Name"].ToString(),
                            Gender = reader["Gender"].ToString(),
                            DateOfBirth = Convert.ToDateTime(reader["DateOfBirth"]),
                            Type = EmployeeType.PartTimeEmployee,
                            HourlyPay = Convert.ToInt32(reader["HourlyPay"]),
                            HoursWorked = Convert.ToInt32(reader["HoursWorked"]),
                        };
                    }
                }
            }
            return employee;
        }

        public void SaveEmployee(Employee employee)
        {
            string cs = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
            using (SqlConnection con = new SqlConnection(cs))
            {
                SqlCommand cmd = new SqlCommand("spSaveEmployee", con);
                cmd.CommandType = CommandType.StoredProcedure;
                SqlParameter parameterId = new SqlParameter
                {
                    ParameterName = "@Id",
                    Value = employee.Id
                };
                cmd.Parameters.Add(parameterId);

                SqlParameter parameterName = new SqlParameter
                {
                    ParameterName = "@Name",
                    Value = employee.Name
                };
                cmd.Parameters.Add(parameterName);

                SqlParameter parameterGender = new SqlParameter
                {
                    ParameterName = "@Gender",
                    Value = employee.Gender
                };
                cmd.Parameters.Add(parameterGender);

                SqlParameter parameterDateOfBirth = new SqlParameter
                {
                    ParameterName = "@DateOfBirth",
                    Value = employee.DateOfBirth
                };
                cmd.Parameters.Add(parameterDateOfBirth);

                SqlParameter parameterEmployeeType = new SqlParameter
                {
                    ParameterName = "@EmployeeType",
                    Value = employee.Type
                };
                cmd.Parameters.Add(parameterEmployeeType);

                if (employee.GetType() == typeof(FullTimeEmployee))
                {
                    SqlParameter parameterAnnualSalary = new SqlParameter
                    {
                        ParameterName = "@AnnualSalary",
                        Value = ((FullTimeEmployee)employee).AnnualSalary
                    };
                    cmd.Parameters.Add(parameterAnnualSalary);
                }
                else
                {
                    SqlParameter parameterHourlyPay = new SqlParameter
                    {
                        ParameterName = "@HourlyPay",
                        Value = ((PartTimeEmployee)employee).HourlyPay,
                    };
                    cmd.Parameters.Add(parameterHourlyPay);

                    SqlParameter parameterHoursWorked = new SqlParameter
                    {
                        ParameterName = "@HoursWorked",
                        Value = ((PartTimeEmployee)employee).HoursWorked
                    };
                    cmd.Parameters.Add(parameterHoursWorked);
                }

                con.Open();
                cmd.ExecuteNonQuery();
            }
        }
    }
}

WebForm1.aspx
<table style="font-family: Arial; border: 1px solid black;">
    <tr>
        <td>
            <b>ID</b>
        </td>
        <td>
            <asp:TextBox ID="txtID" runat="server">
            </asp:TextBox>
        </td>
    </tr>
    <tr>
        <td>
            <b>Name</b>
        </td>
        <td>
            <asp:TextBox ID="txtName" runat="server">
            </asp:TextBox>
        </td>
    </tr>
    <tr>
        <td>
            <b>Gender</b>
        </td>
        <td>
            <asp:TextBox ID="txtGender" runat="server">
            </asp:TextBox>
        </td>
    </tr>
    <tr>
        <td>
            <b>Date Of Birth</b>
        </td>
        <td>
            <asp:TextBox ID="txtDateOfBirth" runat="server">
            </asp:TextBox>
        </td>
    </tr>
    <tr>
        <td>
            <b>Employee Type</b>
        </td>
        <td>
            <asp:DropDownList ID="ddlEmployeeType" runat="server" 
                OnSelectedIndexChanged="ddlEmployeeType_SelectedIndexChanged"
                AutoPostBack="True">
                <asp:ListItem Text="Select Employee Type" Value="-1">
                </asp:ListItem>
                <asp:ListItem Text="Full Time Employee" Value="1">
                </asp:ListItem>
                <asp:ListItem Text="Part Time Employee" Value="2">
                </asp:ListItem>
            </asp:DropDownList>
        </td>
    </tr>
    <tr id="trAnnualSalary" runat="server" visible="false">
        <td>
            <b>Annual Salary</b>
        </td>
        <td>
            <asp:TextBox ID="txtAnnualSalary" runat="server">
            </asp:TextBox>
        </td>
    </tr>
    <tr id="trHourlPay" runat="server" visible="false">
        <td>
            <b>Hourly Pay</b>
        </td>
        <td>
            <asp:TextBox ID="txtHourlyPay" runat="server">
            </asp:TextBox>
        </td>
    </tr>
    <tr id="trHoursWorked" runat="server" visible="false">
        <td>
            <b>Hours worked</b>
        </td>
        <td>
            <asp:TextBox ID="txtHoursWorked" runat="server">
            </asp:TextBox>
        </td>
    </tr>
    <tr>
        <td>
            <asp:Button ID="btnGetEmployee" runat="server" 
            Text="Get Employee" OnClick="btnGetEmployee_Click" />
        </td>
        <td>
            <asp:Button ID="btnSave" runat="server" 
            Text="Save Employee" OnClick="btnSave_Click" />
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <asp:Label ID="lblMessage" runat="server" 
                ForeColor="Green" Font-Bold="true">
            </asp:Label>
        </td>
    </tr>
</table>

WebForm1.aspx.cs
protected void btnGetEmployee_Click(object sender, EventArgs e)
{
    EmployeeService.EmployeeServiceClient client = 
        new EmployeeService.EmployeeServiceClient();
    EmployeeService.Employee employee = 
        client.GetEmployee(Convert.ToInt32(txtID.Text));

    if (employee.Type == EmployeeService.EmployeeType.FullTimeEmployee)
    {
        txtAnnualSalary.Text = 
            ((EmployeeService.FullTimeEmployee)employee).AnnualSalary.ToString();
        trAnnualSalary.Visible = true;
        trHourlPay.Visible = false;
        trHoursWorked.Visible = false;
    }
    else
    {
        txtHourlyPay.Text = 
            ((EmployeeService.PartTimeEmployee)employee).HourlyPay.ToString();
        txtHoursWorked.Text = 
            ((EmployeeService.PartTimeEmployee)employee).HoursWorked.ToString();
        trAnnualSalary.Visible = false;
        trHourlPay.Visible = true;
        trHoursWorked.Visible = true;
    }
    ddlEmployeeType.SelectedValue = ((int)employee.Type).ToString();

            
            
    txtName.Text = employee.Name;
    txtGender.Text = employee.Gender;
    txtDateOfBirth.Text = employee.DateOfBirth.ToShortDateString();
    lblMessage.Text = "Employee retrieved";
}

protected void btnSave_Click(object sender, EventArgs e)
{
    EmployeeService.EmployeeServiceClient client = new 
        EmployeeService.EmployeeServiceClient();
    EmployeeService.Employee employee = null;

    if (((EmployeeService.EmployeeType)Convert.ToInt32(ddlEmployeeType.SelectedValue)) 
        == EmployeeService.EmployeeType.FullTimeEmployee)
    {
        employee = new EmployeeService.FullTimeEmployee
        {
            Id = Convert.ToInt32(txtID.Text),
            Name = txtName.Text,
            Gender = txtGender.Text,
            DateOfBirth = Convert.ToDateTime(txtDateOfBirth.Text),
            Type = EmployeeService.EmployeeType.FullTimeEmployee,
            AnnualSalary = Convert.ToInt32(txtAnnualSalary.Text),
        };
        client.SaveEmployee(employee);
        lblMessage.Text = "Employee saved";
    }
    else if (((EmployeeService.EmployeeType)Convert.ToInt32(ddlEmployeeType.SelectedValue)) 
        == EmployeeService.EmployeeType.PartTimeEmployee)
    {
        employee = new EmployeeService.PartTimeEmployee
        {
            Id = Convert.ToInt32(txtID.Text),
            Name = txtName.Text,
            Gender = txtGender.Text,
            DateOfBirth = Convert.ToDateTime(txtDateOfBirth.Text),
            Type = EmployeeService.EmployeeType.PartTimeEmployee,
            HourlyPay = Convert.ToInt32(txtHourlyPay.Text),
            HoursWorked = Convert.ToInt32(txtHoursWorked.Text),
        };
        client.SaveEmployee(employee);
        lblMessage.Text = "Employee saved";
    }
    else
    {
        lblMessage.Text = "Please select Employee Type";
    }
}

protected void ddlEmployeeType_SelectedIndexChanged
    (object sender, EventArgs e)
{
    if (ddlEmployeeType.SelectedValue == "-1")
    {
        trAnnualSalary.Visible = false;
        trHourlPay.Visible = false;
        trHoursWorked.Visible = false;
    }
    else if (ddlEmployeeType.SelectedValue == "1")
    {
        trAnnualSalary.Visible = true;
        trHourlPay.Visible = false;
        trHoursWorked.Visible = false;
    }
    else
    {
        trAnnualSalary.Visible = false;
        trHourlPay.Visible = true;
        trHoursWorked.Visible = true;
    }
}

wcf tutorial

8 comments:

  1. Hello Sir,

    These all videos are very helpful for me. All WCF concepts were so hard to understand but now its easy for me. my basic concepts are clear now. Thank you very much.

    ReplyDelete
  2. Hello Sir,

    Is it possible to host multiple services using one host project with same biding and baseaddress?

    ReplyDelete
  3. I've noticed, or I'm assuming, that in your if statement:
    if (employee.Type == EmployeeService.EmployeeType.FullTimeEmployee) ,
    you are using the Enumeration defined in the same name space as your employee class. It was not marked with [DataMember] and you didn't use [Serialize], so how did it get passed to the client so that it's usable in your if statement?

    ReplyDelete
    Replies
    1. [DataMember(Order = 5)]
      public EmployeeType Type { get; set; }
      it is declared once check it out...

      Delete
  4. Thx for this tutorial! Well explained.

    ReplyDelete
  5. Hello Venkat Sir,

    Can you please make the videos for Restful service using WCF.

    Thanks,
    Suraj Kumar

    ReplyDelete
  6. Dear sir
    I have an exception,
    Enum value '0' is invalid for type 'EmployeeService_Web_WCF.EmployeeService.EmployeeType' and cannot be serialized. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute.
    I have employee class like this
    namespace EmployeeService
    {
    [KnownType(typeof(FullTimeEmployee))]
    [KnownType(typeof(PartTimeEmployee))]
    [DataContract(Namespace = "http://pragimtech.com/Employee")]
    public class Employee
    {
    private int _id;
    private string _name;
    private string _gender;
    private DateTime _dateOfBirth;

    [DataMember(Order=4)]
    public DateTime DateOfBirth
    {
    get { return _dateOfBirth; }
    set { _dateOfBirth = value; }
    }

    [DataMember(Order=3)]
    public string Gender
    {
    get { return _gender; }
    set { _gender = value; }
    }

    [DataMember(Order=2)]
    public string Name
    {
    get { return _name; }
    set { _name = value; }
    }

    [DataMember(Order=1)]
    public int ID
    {
    get { return _id; }
    set { _id = value; }
    }
    [DataMember(Order=5)]
    public EmployeeType Type { get; set; }
    }


    public enum EmployeeType
    {

    FullTimeEmployee = 1,

    PartTimeEmployee = 2
    }
    }

    ReplyDelete
    Replies
    1. Please check the values in the listitems of the ddlEmployeeType control. One of those 3 list items may be containing Value="0", or even if you don't mention explicit values, it will start from 0; and we don't have that value mentioned in our enum type. Hope it helps!

      Delete

If you like this website, please share with your friends on facebook and Google+ and recommend us on google using the g+1 button on the top right hand corner.