Tuesday, November 1, 2011

Read Stream from a file in chuncks

Problem
I had a programming requirement where I need to read from a file but only 32kb could be transferred at a time. So how do we do that.

Solution
Solution to that problem is that we use binary reader to read only the chunk of data from the file then we use filewriter to write the file.


int chunkSize = 1024;
byte[] chunk = new byte[chunkSize];
         
string destinationPath = @"C:\Users\faraz\MyFileDestination\"+_filename;
string filepath = @"C:\Users\"+targetFile;
using (FileStream fileReader = new FileStream(filepath, FileMode.Open, FileAccess.Read) )
{
      FileStream filewriter = new FileStream(destinationPath, FileMode.Create, FileAccess.ReadWrite);
      BinaryReader binaryReader = new BinaryReader(fileRead);

      int bytesToRead = (int)fileReader.Length;

      do
      {
              chunk = binaryReader.ReadBytes(chunkSize);
              filewriter.Write(chunk, 0, chunk.Length);
              bytesToRead -= chunkSize;
      } while (bytesToRead > 0);

      filewriter.Close();
      binaryReader.Close();    
}
            
            ResultLlabel.Text = @"File Was written successfully.";

Wednesday, April 13, 2011

ASHX Generic Handler in ASP.Net

Problem:
I was working on WCF project where I was returning the list of objects, each object contained a field that holds Image, since it was a WCF project so I had to send images as byte[] array, now problem was that the picture was in byte[] array format, ASP.Net page does't convert it automatically into Image and when binding ListView to the collection, it was converting my byte[] array to a text field instead of Image.

Impact:
Web page does't display Images.

Solution:
Solution to that problem is to use ashx page. When creating a web page that dynamically returns an Image, XML file, PDF file or other non html web pages from the query string we use ashx page to perform those actions.

This solution will show how to use ahsx page to dynamically convert byte[] array to an image.

Step 1: Add new Generic Handler by right clicking on web project->Add New Item then select Generic Handler. Give it any name you want, I named mine HttpHandler.We need to pass the query string to the handler and handler will convert the byte[] array to an image and return a Url of that image, to do that go back to your aspx web page, in the ListView Item templet look for the column that is bound to the Image. It should look something like this.

ImageUrl='<%# Eval("Image") %>' //where Image is the name of the column.

Since ListView is bound to a collection of record and each record has an ID column that is associated with the Image, we will pass that Id as a query string instead of Image, and since we already have a collection we could create a session object that stores that collection so that we could access it in our handler, so do all that first replace your Eval("Image") with the following.

ImageUrl='<%# "HttpHandler.ashx?id=" + Eval("Id") %>'


Now we are passing the Id of that record to the HttpHandler.

Step 2: Create a Http Session object.
In the code behind file of you page, go to Page load method and create a session and pass your collection to that session.

private MovieServiceClient _movieService;
private List<Movie> _movies;

protected void Page_Load(object sender, EventArgs e)
{
        try
        {
            _movieService = new MovieServiceClient("MovieService_WsHttp");
            _movies = _movieService.GetAllMovies();
            Session["session"] = _movies;
        }
        catch (FaultException ex)
        {
            ErrorLabel.Text = ex.Message;
        }
        catch (Exception ex)
        {
            ErrorLabel.Text = ex.Message;
        }
}
        
Step 3: Code to convert byte[] into an image using HttpHandler.

In HttpHandler page we need to call session object and by default we sessions are not enabled in ashx pages, we use IRequiresSessionState Interface to enable it. Write the following code in your Process request method().


public class HttpHandler : IHttpHandler, IRequiresSessionState
{
    public void ProcessRequest (HttpContext context)
    {
        try
        {
            context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            context.Response.BufferOutput = false;
            //get the id from the query string.
            int id = Int32.Parse(context.Request.QueryString["id"]);
            //set the type to Image/jpeg, or png or gif, any type that you are returning.
            context.Response.ContentType = "Image/jpeg";
            //get the session object.
            context.Session["session"] = HttpContext.Current.Session["session"];
            if (context.Session["session"] != null)
            {
                //pass the session object to a List<>
                var list = context.Session["session"];

                foreach (var movie in (List<Service.Movie>)list)
                {
                    //check if the id of that record matches to that record.
                    if (id == movie.Id)
                    {
                        //set the response that convert byte[] to an image.
                        context.Response.BinaryWrite(movie.Image);
                        break;
                    }
                }

            }
        }
        catch (Exception ex)
        {
            context.Response.Write(ex.Message);
        }
      
    }

    public bool IsReusable
    {
        get { return false; }
    }
}

this will return one image at a time as your ListView loop through all the records, your web page should now show that Image.

Sunday, April 10, 2011

Hiding buttons in Gridview based on user.

Problem
I created a web project where I am binding the list of students to the GridView. I also enabled selection, edition and deletion. My application also involved security features where I had admin, power user and guest roles. Admin could add, edit and delete, power user could add, but can't delete, and guest user can only view the record, but the problem is I can't seem to find a way to hide the buttons depending on the user.

Impact
Can either completely hide or show the buttons.

Solution
when we bind the list to the grid view, grid view creates column and bind each field to each column, it also creates columns for each field we create for Edit, Delete, Insert or Select button. In the Item templet we have a property called Visible where we could hide or show columns. Since we don't know who the user will be until run time we have to create a method that returns the true or false depending on the user.


<ItemTemplate>
                        <asp:ImageButton ID="ImageButton1" runat="server" CausesValidation="False"
                            CommandName="Edit" ImageUrl="~/Images/database_edit.png" Text="Edit"                    Visible='<%# GetShowEditButton() %>' />
                        &nbsp;<asp:ImageButton ID="ImageButton2" runat="server" CausesValidation="False"
                            CommandName="Select" ImageUrl="~/Images/arrow_left.png" Text="Select" />
                        &nbsp;<asp:ImageButton ID="ImageButton3" runat="server" CausesValidation="False"
                            CommandName="Delete" ImageUrl="~/Images/delete.png" Text="Delete" Visible='<%# GetShowDeleteButton() %>' />
                    </ItemTemplate>

Code behind file where I created the highlighted methods.


public partial class StudentView : System.Web.UI.Page
{
    private StudentRepository _studentRepository = new StudentRepository();
    protected void Page_Load(object sender, EventArgs e)
    {
      
    }

    protected bool GetShowDeleteButton()
    {
        String[] rolesArray = Roles.GetRolesForUser();
        if (rolesArray != null)
        {
            if (rolesArray.Contains("Admin"))
                return true;
        }
        return false;
    }

    protected bool GetShowEditButton()
    {
        String[] rolesArray = Roles.GetRolesForUser();
        if (rolesArray != null)
        {
            if (rolesArray.Contains("Admin"))
                return true;
            if (rolesArray.Contains("PowerUser"))
                return true;
        }
        return false;
    }
    protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        GridView1.DataSource = _studentRepository.GetAllStudents();
        GridView1.PageIndex = e.NewPageIndex;

        GridView1.DataBind();
    }
}

Overriding Tostring method

Problem
I created a list of person class but when run it through foreach loop and print it to console I was getting namespace.Person instead of actual person name.

Impact
Can't print the name of the person in the class.

Solution
I is a very common mistake that people make when they are new to OOP languages, well at least I did. I did't understand how we use console.writeln() method to print out integer or double values even though it accept only string value.

Ever wondered why when we create a custom class, we get few methods and properties even thought we did't even created them. Every class in C# is ultimately driven from object class. object class defines all these methods, one of them is ToString() method. To string is the method that gets called automatically when we use and print the value of an object. Following program shows how we could override and use to string method to help us out solving that small problem.


namespace ToStingExample
{
    class Program
    {
        static void Main(string[] args)
        {
            Person person = new Person();
            Animal animal = new Animal("Dog");
            Vertex3D vertex3d = new Vertex3D(1,2,3);
            Console.WriteLine("Without overriding Tostring = {0}",person.ToString());
            Console.WriteLine("\nAfter Overridding Tostring method = {0}",animal.ToString());
            Console.WriteLine("\nAfter overridding and using Format method = {0}",vertex3d.ToString());
            Console.ReadLine();
        }
    }

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
    public class Animal
    {
        public string Name { get; set; }

        public Animal(string name)
        {
            Name = name;
        }

        public override string ToString()
        {
            return Name;
        }
    }

    public class Vertex3D
    {
        public int X { get; set; }
        public int Y { get; set; }
        public int Z { get; set; }

        public Vertex3D(int x,int y, int z)
        {
            X = x;
            Y = y;
            Z = z;
        }

        public override string ToString()
        {
            return string.Format("{0},{1},{2}", X, Y, Z);
        }
    }

}


And here is the output that we get after running our little program.

Thursday, April 7, 2011

Hashing In C#

Problem
It is a common practice to save the user and the password associated with the user as a plain text in the database, but there is one problem with this approach, your passwords are not secure, anyone one who has an access to the database can steal your data. How to make sure that your password is secure.

Impact
Data is not secure.

Solution
 To make sure that password or any kind of data you passing is secure we use a process called Hashing. In C# we could used MD5 or SHA1 Hashing. Following is an example of how to create a hash for a password that user entered in the textbox.




namespace PasswordEncription
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string password = PassWordTextBox.Text;
            byte[] buffer = GetCharArray(password);
            ResultTextBox.Text = EncriptPassword(buffer);
        }

        private byte[] GetCharArray(string password)
        {
            byte[] buffer = new byte[password.Length];
            int i = 0;
            foreach (byte c in password)
            {
                buffer[i] = c;
                i++;
            }
            return buffer;
        }

        private string EncriptPassword(byte[] password)
        {
            MD5CryptoServiceProvider encriptor = new MD5CryptoServiceProvider();
            byte[] encriptedPassword = encriptor.ComputeHash(password);
            StringBuilder stringBuilder = new StringBuilder();
            foreach (sbyte b in encriptedPassword)
            {
                stringBuilder.Append(b.ToString("x2"));
            }
            return stringBuilder.ToString();
        }
    }
}

Monday, March 28, 2011

Transaction object

Problem
I had a situation where I had to add a record in the table, and at the same time I needed to add record in another table but I needed an Id of the first table to enter in the second second table. What must I do to achieve that.

Impact
Program will not do what it is suppose to do.

Solution
Solution to this problem is to use transaction object. Think of it this way, if we go to bank and transfer the money from one account to another, first bank has to take money out of the account and then transfer it in the other account, what happens if first transaction succeeds but the second one does't.  C# uses transaction object to solve this issue. When we use transaction object both of these transactions must succeed before we enter the record in the database, if one fails all other transactions will rollback. Here is the code that I wrote where I am entering record in the data base and retrieving the id of the record just been entered and then committing to the action.


public int Save(Customer customer)
        {
            int roweffected = 0;
            try
            {
                //first open the connection to the database
                _connection.Open();
                //begin the transaction.
                using(SqlTransaction transaction = _connection.BeginTransaction())
                {
                    //create a command object to enter a record in the database.
                    using (SqlCommand command = new SqlCommand())
                    {
                        command.CommandText = "Insert into Customer (FirstName,LastName,DateOfBirth,HouseNumber," +
                                              "Street,City,Country,PostCode,Phone,Email) Values(@firstname,@lastname," +
                                              "@dateofbirth,@housenumber,@street,@city,@country," +
                                              "@postcode,@phone,@email)";
                        command.Connection = _connection;
                        command.Transaction = transaction;
                        command.Parameters.AddWithValue("@firstname", customer.FirstName);
                        command.Parameters.AddWithValue("@lastname", customer.LastName);
                        command.Parameters.AddWithValue("@dateofbirth", customer.DateOfBirth);
                        command.Parameters.AddWithValue("@housenumber", customer.HouseNumber);
                        command.Parameters.AddWithValue("@street", customer.StreetName);
                        command.Parameters.AddWithValue("@city", customer.City);
                        command.Parameters.AddWithValue("@country", customer.Country);
                        command.Parameters.AddWithValue("@postcode", customer.PostCode);
                        command.Parameters.AddWithValue("@phone", customer.Phone);
                        command.Parameters.AddWithValue("@email", customer.Email);
                        roweffected = command.ExecuteNonQuery();
                    }
                    //Create another command object to retrieve the record id you just entered.
                    using (SqlCommand command = new SqlCommand())
                    {
                        //this query returns the id of the last record entered in the customer table.
                        command.CommandText = "Select @@Identity from Customer";
                        command.Connection = _connection;
                        command.Transaction = transaction;
                        var value = command.ExecuteScalar();
                    }
                    transaction.Commit();
                }
              
                return roweffected;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

Saturday, March 26, 2011

How To Save Image To SqlServer

Problem: I am currently working on my college project where I was required to save images to the database and I had no idea how to do that.

Impact:
Unable to save images to the database.

Solution:
After doing some research I found some material on this topic, so I wrote a small program for this post to share my knowledge with you guys. First create a windows form application, add four button, load, browse, save and clear, Add two text boxes, A picture box and from Dialog Tool Box select openFileDialog. Here is the screen shot of my form.


First we need to up load the image to the picture box using open file dialog. When user click on browse open file dialog will pop up and the select the image. Following code shows how to get image in picture box.


private void BrowseButton_Click(object sender, EventArgs e)
{
            openFileDialog1.ShowDialog();
            //_file is a string declared as a private field at class level.
            _file = openFileDialog1.FileName;
            pictureBox1.Image = Image.FromFile(_file);
            FileBrowserTextBox.Text = _file; 
}


Now this is the hard part. Once the image is loaded in the picture box and you are sure that this is the image you want to save, then click on Save button. But before we save the image, we need to convert the image into  byte of array, and then pass it to the database. I used separate layer (Project) for database and created a class called ImageRepository. Image Repository does two things save and load, before I show you how to do that we need to convert the image into byte[]. Following code shows how to convert image into byte[] and then pass it to the database.


private void SaveButton_Click(object sender, EventArgs e)
        {
            try
            {
                //use ReadFile method to get byteArray
                byte[] data = ReadFile();
                ImageRepository repository = new ImageRepository();
                int result = repository.SaveImage(data);
                if(result==1)
                {
                    MessageBox.Show(@"Image Saved Successfully");
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }


private byte[] ReadFile()
        {
            byte[] data;
            //Use FileInfo object to get file size.
            FileInfo fileInfo = new FileInfo(_file);
            long fileLength = fileInfo.Length;
            //Open FileStream to read file
            FileStream fileStream = new FileStream(_file,FileMode.Open,FileAccess.Read,FileShare.Read);
            //Use BinaryReader to read file stream into byte array.
            BinaryReader binaryReader = new BinaryReader(fileStream);

             //When you use BinaryReader, you need to supply number of bytes
//to read from file.
      //In this case we want to read entire file. 
      //So supplying total number of bytes.
            data = binaryReader.ReadBytes((int)fileLength);
            //Close the file stream
            fileStream.Close();
            return data;
        }


Now we will use Repository to save the image.

public int SaveImage(byte[] imagedata)
        {
            try
            {
                byte[] imageData = imagedata;
                //get the connectin string.
                string connectionstring = @"Data Source=FARAZ-PC\FARAZ_K1;Initial Catalog=RentAMovieDB;Integrated Security=True";
                SqlConnection connection = new SqlConnection(connectionstring);

        //Open the connection to the database.

                connection.Open();
                SqlCommand command = new SqlCommand();
                //Insert image to the database. I am updating my record since I had a table with a column name Image. you could use Insert command instead of update.
                command.CommandText = "UPDATE Movie SET Image = @image where Name = 'Your                  Highness'";
                command.Connection = connection;
                //Adding the parameter to the command object.
                command.Parameters.AddWithValue("@image", imageData);
                //if the result is 1 that means that image was saved.
                int result = command.ExecuteNonQuery();
                connection.Close();
                return result;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

Now we need to load the image from the database. Since I have my Image stored in Movie table, so I will use Movie name to search for the image I am looking for. Getting the image from the database is other way round, before we were converting the image into byte[] array and then saving it, now we are getting the image from that database as byte[] array and we need to convert it back into image and load it to picture box. First I am providing the name of the movie to look for the image. Here is what happens when user clicks on LoadImage button.

private void LoadButton_Click(object sender, EventArgs e)
        {
          
            try
            {
                ImageRepository repository = new ImageRepository();
                //get the byte[] data from database using repository class.
                byte[] image = repository.LoadImage(LoadTextBox.Text);
                Image newImage;

        //Read image data into a memory stream

                using(MemoryStream memoryStream = new MemoryStream(image,0,image.Length))
                {
              
                    memoryStream.Write(image,0,image.Length);
                    //Set image variable value using memory stream.
                     newImage = Image.FromStream(memoryStream, true);
                }
                //Set picturebox image.
                pictureBox1.Image = newImage;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }


//get image using the repository class loadImage method.

public byte[] LoadImage(string movieName)
        {
            byte[] image = null;
            string connectionstring = @"Data Source=FARAZ-PC\FARAZ_K1;Initial Catalog=RentAMovieDB;Integrated Security=True";
            SqlConnection connection = new SqlConnection(connectionstring);
            connection.Open();
            SqlCommand command = new SqlCommand();
            command.CommandText = "Select image from Movie where Name = '" + movieName+"'";
            command.Connection = connection;
            SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
            DataSet dataset = new DataSet();
            dataAdapter.Fill(dataset);
            foreach (DataRow row in dataset.Tables[0].Rows)
            {
                image = (byte[])row["Image"];
            }
            return image;
        }

Here is the form after loading the image from the database.

Tuesday, March 15, 2011

Data Validation

Problem:
Data validation is perhaps the most used feature of any application, what should I do to validate my data.
Impact:
Program might not work properly because data is not be valid.
Solution:
We could create a class that we could use to validate data. I create a class named Validator. This class contains static methods, each method takes a textbox as an argument verifies specific data type, for example string is empty or null, or if the value is integer or not or greater than or less than etc.


public static class Validator
    {
        private static ToolTip _tooltip = new ToolTip();
        public static bool IsInteger(TextBox textBox)
        {
            int value;
            if(int.TryParse(textBox.Text,out value))
            {
                textBox.BackColor = Color.White;
                _tooltip.SetToolTip(textBox, "");
                return true;
            }
            else
            {
                textBox.BackColor = Color.Maroon;
                _tooltip.SetToolTip(textBox, "Please enter a number.");
                textBox.Focus();
                textBox.Clear();
            }
            return false;
        }

        public static bool IsValidPhoneNumber(TextBox textBox)
        {
            string strRegex = @"^[1-9]\d{2}-[1-9]\d{2}-\d{4}$";
            Regex regex = new Regex(strRegex);
            if(regex.IsMatch(textBox.Text))
            {
                textBox.BackColor = Color.White;
                _tooltip.SetToolTip(textBox, "");
                return true;
            }
            textBox.BackColor = Color.Maroon;
            _tooltip.SetToolTip(textBox, "Please enter a valid email address.");
            textBox.Focus();
            textBox.Clear();
            return false;
        }

        public static bool IsValidEmailAddress(TextBox textBox)
        {
            string strRegex = @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
                                @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
                                @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
            Regex regex = new Regex(strRegex);
            if(regex.IsMatch(textBox.Text))
            {
                textBox.BackColor = Color.White;
                _tooltip.SetToolTip(textBox, "");
                return true;
            }
            else
            {
                textBox.BackColor = Color.Maroon;
                _tooltip.SetToolTip(textBox, "Please enter a valid email address.");
                textBox.Focus();
                textBox.Clear();
            }
            return false;
        }

        public static bool IsDouble(TextBox textBox)
        {
            double value;
            if(double.TryParse(textBox.Text,out value))
            {
                textBox.BackColor = Color.White;
                _tooltip.SetToolTip(textBox, "");
                return true;
            }
            textBox.BackColor = Color.Maroon;
            _tooltip.SetToolTip(textBox, "Please enter a number.");
            textBox.Focus();
            textBox.Clear();
            return false;
        }

        internal static bool IsPresent(TextBox textBox)
        {
            if(!string.IsNullOrEmpty(textBox.Text))
            {
                textBox.BackColor = Color.White;
                _tooltip.SetToolTip(textBox,"");
                return true;
            }
            textBox.BackColor = Color.Maroon;
            textBox.Focus();
            _tooltip.SetToolTip(textBox,"This field is required.");
            textBox.Clear();
            return false;
        }
    }
now we could use this class as a dll library in any application and use it to validate data.

for example if we have a age text box that suppose to contain integer value, to check if text box contains we use the validator like this.

if(Validator.IsInteger(AgeTextBox))
{
    //perform some action.
}
else
{
     MessageBox.Show("Invalid integer value.");
}

Monday, March 14, 2011

Generics

Problem:
I wrote a program that store the student and course information in Dictionary. Both Course and Student uses the same methods to store or retrieve record, so there is a duplication of code here, how can I make this code more efficient?

Impact:
Code duplication

Solution:
In situation like this where we have we two object doing the same thing, generic comes to rescue. Generics allow us to define type-safe data structures, without committing to actual data types. Generics allow us to reuse the same code algorithms without writing type specific duplicate code.Generics allow us to define type-safe classes without compromising type safety, performance, or productivity. 
Here is the application that I was working on.


In this application I have Main form that let you Add new student record, search student, Add course and search course. Both student forms and course forms uses the same ServiceFactory class to add the record and display record.


                                                                         Main Form
when user click on Add New Student button it display another form that  is used to collect student information. This form contains one button "Save" and when user click on save button it class the StudentService class. Here is the detail of the application. First Main form.

namespace RegistrationSystem.App
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        private void btnAddRecord_Click(object sender, EventArgs e)
        {
            frmStudent frm = new frmStudent();
            frm.ShowDialog();
        }

        private void btnViewRecord_Click(object sender, EventArgs e)
        {
            frmDisplayStudent frm = new frmDisplayStudent();
            frm.ShowDialog();
        }

        private void AddCourseButton_Click(object sender, EventArgs e)
        {
            frmCourse frmCourse = new frmCourse();
            frmCourse.ShowDialog();
        }

        private void GetCourseButton_Click(object sender, EventArgs e)
        {
            frmDisplayCourse frmDisplayCourse = new frmDisplayCourse();
            frmDisplayCourse.ShowDialog();
        }
    }
}

now when user click on btnAddRecord, it displays student form.
user enter student record and click on Save button.


private void btnSave_Click(object sender, EventArgs e)
        {
            try
            {
                Student student = new Student();
                student.FirstName = txtFirstName.Text;
                student.LastName = txtLastName.Text;
                student.StudentId = txtStudentId.Text;

                StudentService.SaveStudent(student);
                MessageBox.Show("Record Saved Successfully");
                SetFormForNewRecord();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void SetFormForNewRecord()
        {
            txtFirstName.Text = "";
            txtLastName.Text = "";
            txtStudentId.Text = "";
        }

and here is the StudentService class.

public static class StudentService
    {
        public static void SaveStudent(Student student)
        {
            ServiceFactory<Student>.AddNewRecord(student.StudentId,student);
        }

        public static Student GetStudentById(string studentId)
        {
            return ServiceFactory<Student>.GetRecord(studentId);
        }
    }

StudentService uses ServiceFactory to save and get record. 

T is for type object.

public class ServiceFactory<T>
    {
        private static Dictionary<string, T> _data;

        static ServiceFactory()
        {
            _data = new Dictionary<string, T>();
        }

        public static void AddNewRecord(string Id,T record)
        {
            if(_data.ContainsKey(Id))
            {
                throw new Exception("Record already exist");
            }
            _data.Add(Id,record);
        }

        public static T GetRecord(string Id)
        {
            if (! _data.ContainsKey(Id))
            {
                throw new Exception("Record not found");
            }
            return _data[Id];
        }
    }

Monday, February 28, 2011

Model View Presenter Supervising Controller

Problem
 When I create windows application forms, I find it really hard to test it and if I want to change the form design or change the form altogether, I will have to rewrite my code again. So that make my application really rigid and reduce the scalability and testability.

Impact

  • Maintenance is really difficult and can't really test my code.
  • Its very hard to separate business logic from the view.


Solution
Model view Presenter pattern is the solution to this problem. First we need to understand what Model view Presenter is.

Model: Model is our class where we write our business logic.
View: View is user interface, in our case windows form.
Presenter: Presenter is where we write code to connect our view to our model.


Now the whole purpose of this pattern is to use our view for only the viewing, and all the code should go to presenter class.

suppose we have windows form, called StudentView, and have a model Student, and we are using StudentView to get the information about the student from the user.



this is what our model looks like.
namespace ModelViewPresenterExample
{
    public class Student
    {
        public Student(string name,string address, int age)
        {
            Name = name;
            Address = address;
            Age = age;
        }

        public string Name { get; set; }
        public string Address { get; set; }
        public int Age { get; set; }
    }
}

now that we have our model and view, we need our presenter. we need to create a class name StudentViewPresenter. StudentViewPresenter class implements IStudentViewPresenter interface. We also need to create another interface IStudentView and implement that interface on our Student form. for the time being IStudentViewPresenter has one method and one property. 

namespace ModelViewPresenterExample
{
    public interface IStudentViewPresenter
    {
        IStudentView View { get; set; }
        void AttachPresenter();
    }
}


as you can see we are exposing our form by using IStudentView property. Here is the code for our IStudentView interface.

namespace ModelViewPresenterExample
{
    public interface IStudentView
    {
        void Message(string message);
        void AddPresenter(IStudentViewPresenter presenter);
    }
}

this interface contains only two methos, one to pass our presenter and one to pass simple messages from our presenter. I know its alot to take in, it will make more sense when we write rest of our code.

so first lets write our presenter class.

namespace ModelViewPresenterExample
{
    public class StudentViewPresenter:IStudentViewPresenter
    {
        private IStudentView _view;

        //pass student view when user instantiate presenter.
        public StudentViewPresenter(IStudentView view)
        {
            _view = view;
        }

        public IStudentView View { get; set; }

        //here we are passing this presenter to our view.
        public void AttachPresenter()
        {
            _view.AddPresenter(this);
        }
    }
}



this purpose of all this is, that using this presenter we could easily switch our view, for example when we create our presenter, we pass the form, presenter does't care what kind of form it is as long as that form implements IStudentView, our presenter will happily accept it.

IStudentViewPresenter presenter = new StudentViewPresenter(new StudentView());

so as you can see, we are forcing the user to inject the view when we instantiate the presenter.

now that we have our presenter, I am going to show you what I have for our form. Here is the code that goes in StudentView.

namespace ModelViewPresenterExample
{
    public partial class StudentView : Form,IStudentView
    {
        private IStudentViewPresenter _presenter;
        public StudentView()
        {
            InitializeComponent();
        }

        public void Message(string message)
        {
            MessageBox.Show(message);
        }

        public void AddPresenter(IStudentViewPresenter presenter)
        {
            _presenter = presenter;
        }
    }
}

in student view we have IStudentViewPresenter, we then use AddPresenter method and pass our presenter to this local variable. as you can see that in our presenter class we had a method AttachPresernter and in that method we used our view to call AddPresenter method and passed the presenter to our view, this way presenter can now have connection with view.

now since this form is about saving the student information, when user click on Save button, so we need to write code for that and you will see how our presenter take care of all the code.

private void SaveButton_Click(object sender, EventArgs e)
{
      _presenter.Save(NameTextBox.Text, AddressTextBox.Text, AgeTextBox.Text);
 }

as you can see we simply created a method named Save and passed all the value to it, infect we just write the code in form and visual studio will create the method for us in the interface, since we are using interface to communicate. we might need to change the names of the parameters though. Now we go to presenter and implement that method. 

 public void Save(string name, string address, string age)
 {
        _student = new Student(name,address,Convert.ToInt16(age));
 }

as you can see that I am saving all the value to student class, assuming that all the values that were passed in are valid. or we could simply validate the values and then pass it to student class, if the values are not valid then return a message to student view. 

public bool Save(string name, string address, string age)
        {
            if(valid(name,address,age))
            {
                _student = new Student(name, address, Convert.ToInt16(age));
            }
            else
            {
                _view.Message("Invalid values, please enter correct values.");
            }
        }

as you can see once we have the basic model or MVP, we could add methods or properties to it as per requirements, we could easily test our code as well.

Example of test case using nunit testing.
[Test]
public void ShouldSaveValueToStudent()
{
     bool saved = false;
     string name = "faraz";
     string address = "12Alice road";
     string age = "29";
     saved = presenter.Save(name,address,age);
     Assert.IsTrue(Saved);
}

in this test when we save the data, our method should return true, to conform that every thing went smooth and there was no problem.




Address Access Denied Exception

Problem
I was developing WCF application where I had to use basic http binding, I was trying to host it in the console application and for some reason I was getting Address Access Denied Exception.

Impact
Application won't run.

Solution
After much of research I found out that since the release of vista, windows has implemented new security feature and because of that most people won't be running with Administrator privileges and since http protocol requires the Admin rights so application won't run. Now to solve this issue we need to do 2 things

1. Run netsh command on console.
Go to start, enter netsh, windows will find the netsh.exe file, right click and choose run as admin. Console will run the utility. and we will get the netsh>
now enter the following command

netsh>http add urlacl url=http://localhost:8080/test user=FARAZ-PC/faraz and enter.

now user name should be the name of your machine, in my case it was faraz-PC. after running the command you should get some message telling you that http has been added.

2. Restart visual studio and start it as Administrator.

and run your application again and it should now work.

Monday, February 14, 2011

Factory Pattern

Problem
I had a situation where I had to instantiate a class based on the condition, so I used if else if statements and was done with it, but after some time I had to add another condition to it, I had to go back and look for that code. What Should I do that in future I don't have to go through this process again.

Impact 
Code was hard to debug, and was less scalable.

Solution
I have alway been fascinated by Design patterns since I found out about them, but they are not easy to understand. There is a lot of material on the web about design patterns but I could't get my head around them, Most of the material that I found was too advance for my level so I start reading books, and believe me books are not that easy either. I found Headfirst design pattern, which seemed much better book than the other books, and in there I found the solution to my problem. Factory pattern. So when we have a situation where we need to instantiate a class based on a situation we should use factory pattern. Advantage of using factory pattern is that we know where to when we need to add another condition, plus we don't make any changes to our logic, all we have to do is ask the factory to create a class based on the situation.

IProduct  product  = ProductFactory.Create("Gucci Bag");

and factory should return the product.

I am going to create simple example so we could understand it better.

We understand the problem now and this is how we deal with it.
first of all alway try to work with the interface rather than concrete class. Coding to an interface is always better, you don't expose the whole class, only those parts that were implemented  by the interface.

public interface IProduct
    {
        string Name { get; set; }
    }

Now that we have an interface, we implement it to our classes.
Make sure the constructor of the class in always internal, otherwise client is free to instantiate concrete class then using factory.

    public class CalvinKlein:IProduct
    {
        public string Name { get; set; }

        internal CalvinKlein(string name)
        {
            Name = name;
        }

        public override string ToString()
        {
            return string.Format(Name);
        }
    }

public class GucciBag : IProduct
    {
        public string Name { get; set; }

        internal GucciBag(string name)
        {
            Name = name;
        }

        public override string ToString()
        {
            return Name;
        }
    }


In our store class we want to use our factory class to create our product, factory will produce item based on the product type that we are passing to the factory.

    public class Store
    {
        private IProduct _product;
        private IProductFactory _factory;

        public IProduct Buy(ProductType productType)
        {
            _factory = new ProductFactory();
            _product = _factory.Create(productType);
            return _product;
        }
    }

    public enum ProductType
    {
        GucciBag,
        CalvinKlein
    }

We use factory that will create the item for you. How does it work you say, well here first we create an interface name IFactory which contains one method called Create() that take one argument and return IProduct type. Now the argument that it takes will be enum type, and based on that type we will create our object. so here we go.

public interface IProductFactory
{
     IProduct Create(ProductType productType);
}

    public class ProductFactory:IProductFactory
    {
        private IProduct _product;

        public IProduct Create(ProductType productType)
        {
            if(ProductType.CalvinKlein == productType)
            {
                _product = new CalvinKlein("Calvin Klein");
            }
            else if(ProductType.GucciBag==productType)
            {
                _product = new GucciBag("Gucci Bag");
            }
            return _product;
        }
    }


Now finally we will use Main method to buy the items from the store and then display the name of the item we bought.

class Program
    {
        static void Main(string[] args)
        {
            Store myStore = new Store();
            IProduct product;
            product = myStore.Buy(ProductType.GucciBag);
            
            Console.WriteLine(product); // this will show we bought Gucci bag.
            product = myStore.Buy(ProductType.CalvinKlein);
            Console.WriteLine(product); // this will show that we bought Calvin klein product.
            Console.ReadLine();
        }
    }