Pages

Showing posts with label web development. Show all posts
Showing posts with label web development. Show all posts

Thursday, November 4, 2010

C# Email Helper for sending out HTML Emails with data

Summary


The following article contains code to send data via a dictionary to a Mail Helper which builds an html email based on an Email template defined by a user control.

Premise


At work, I have had to build websites which send out html emails. We already had some code which loaded a user control into an html writer, which gave a html string to be placed in the html body for sending .Net mail. I wanted to abstract the logic out so that I could reuse it in any of my projects without having to modify all the parameters etc.

Essentially the things that were different were the HTML template, and the data to be bound to the template. Everything else; the building, the sending all had the same logic.

The Code


First we have the MailHelper class, which will build and send the email. We pass in the path of the email template, and basic email parameters such as to, from and subject. The dictionary is a string object pair for convenience. Use the string as a key to reference your objects similar to a ViewState or ViewModel.

Then you will see the EmailControl class which extends UserControl. We want to place a method there for setting the key value pairs. And then we want all Email templates to extend from this class.


public static class MailHelper
    {

        public static void SendEmail(string controlPath, 
                                     string to, 
                                     string from, 
                                     string subject, 
                                     Dictionary<string, object> keyValuePairs)
        {
            var body = GenerateContactEmailBody(controlPath, keyValuePairs);
 
            var officeMessage = new MailMessage(from, to)
            {
                Subject = subject,
                IsBodyHtml = true,
                Body = body
            };
 
            var client = new SmtpClient();
 
            client.Send(officeMessage);
        }
 
        private static string GenerateContactEmailBody(string path, 
                                  Dictionary<string, object> keyValuePairs)
        {
            Page pageHolder = new Page();
            var emailControl = (EmailControl)pageHolder.LoadControl(path);
            emailControl.SetKeyValuePairs(keyValuePairs);
            var writer = new StringWriter(CultureInfo.CurrentCulture);
            emailControl.RenderControl(new Html32TextWriter(writer));
            return writer.ToString();
        }
    }
 
    public class EmailControl : System.Web.UI.UserControl
    {
        public virtual void SetKeyValuePairs(Dictionary<string,object> value)
        {
            throw new NotImplementedException();
        }
    }

So now we can create a new HTML Email template. Create a new UserControl, make this extend EmailControl instead of extending UserControl directly. Then override the SetKeyValuePairs method. In my example below, I have a ContactUs email template where I accept values for Name, Email, Telephone, and Question. These are all strings but could have been other objects.

Then in my ascx file, I create the html template as per a design, and bind the properties where they are needed. The override for RenderControl is needed when we generate the html in the MailHelper.

public partial class ContactUs : EmailControl
    {
 
        public override void SetKeyValuePairs(Dictionary<string, object> value)
        {
            Name = value["Name"].ToString();
            Email = value["Email"].ToString();
            Telephone = value["Telephone"].ToString();
            Question = value["Question"].ToString();
        }
 
 
        public string Name { get; set; }
 
        public string Email { get; set; }
 
        public string Telephone { get; set; }
 
        public string Question { get; set; }
 
        public override void RenderControl(HtmlTextWriter writer)
        {
            DataBind();
            base.RenderControl(writer);
        }
    }

Finally, the bit of code which I call on my page which actually calls the MailHelper and sends out the email.

var kvp = new Dictionary<string, object>();
            kvp.Add("Name", name);
            kvp.Add("Email", email);
            kvp.Add("Telephone", telephone);
            kvp.Add("Question", question);
 
            var to = ConfigurationManager.AppSettings["ContactTo"];
            var from = ConfigurationManager.AppSettings["ContactFrom"];
            var subject = ConfigurationManager.AppSettings["ContactSubject"];
 
            MailHelper.SendEmail("~/ContactUs.ascx", to, from, subject, kvp);

Thursday, August 5, 2010

Browser Testing in IE 5,6,7,8

I found a neat little tool for doing browser testing on all the IE browsers.

http://www.my-debugbar.com/wiki/IETester/HomePage

You can easily open sites in each of the browsers in individual tabs. I needed to use this after trying out the IE Collection and my computer wouldn't run it because of some malware. compatibility

Friday, July 2, 2010

Looking back on my time at Olympic

I'll be starting my new job at ICE Interactive next week, but first I'd like to look back at the last chapter of my life at Olympic Software.

Prologue

I applied for a position at Olympic after being told about it by a fellow Software Engineering graduate, Wendy, who was my Part 3 Project Partner. They wanted to offer her a position but she had already found another one, and so that opened an opportunity for me. And after an interview involving "the supermarket question" I got the job!

I then worked 2 weeks over the summer developing a neat little lottery application before starting officially in January 2009. I also introduced my good friend Alex to Olympic, and so I was really excited to have a fellow classmate on board.

Day 1

My desk on my first day, you can see the beginning of the gadgets.


I went through a Helping Clients Succeed course, which is about "Peeling the Onion" and getting to the root of the problem, not just accepting what the customer is saying.

Also in my first week, Dinuka was leaving for Australia and André had already left for Europe.

BrainDump

Worked for a few months on BrainDump with Alex. There were a few late nights just chugging along with the never-ending stream of issues. Was a fun first project though!

Pedro showed up as Darth Vader. Apparently coding with the Force was quite productive.


SharePoint and OlympicCare

Started working with Stephen (the SharePoint Guru I might add) on Oly-Care, Olympic's client portal for communicating and sharing knowledge with our customers, including the support process. Went through most of what WSS 3 had to offer from setup and installation to developing web parts (mostly using the Smart part though) and administering pages and users.

Round the Bays

There was a big push to get everyone in the office ready for Round the Bays. In 2009 we had a fair turnout of around 10. But in 2010 we had a whopping 20! We went for Running Bunch twice a week, even though there weren't too many most of the time.



ITM and QV

My last projects were Projects for the above clients. Gained lots more experience in development :) Got experience with Test Driven Development, learnt some MVC.NET, some .NET forms web development, played around with JQuery, Javascript, CSS, and did some Win Forms development.

Joseph's Great Wall of Coke

Joseph drinks some 3-4 cans of coke a day, and after 3 odd years had accumulated quite a collection. He took them down to build a wall on his last day. Then proceeded to bust it down.



Final Words

I really hope that I have had some impact on the company or the team I worked with. Perhaps brought up morale when it was low, or just made people laugh when there was nothing to smile about. If nothing else, I have left my CubeeCraft guys there :D

Tuesday, September 8, 2009

If Architects Had to Work Like Web Designers

An article I found here... http://www.digitalsurvivors.com/archives/000455.php

January 10, 2002

Please design and build me a house. I am not quite sure of what I need, so you should use your discretion. My house should have somewhere between two and forty-five bedrooms. Just make sure the plans are such that the bedrooms can be easily added or deleted. When you bring the blueprints to me, I will make the final decision of what I want. Also, bring me the cost breakdown for each configuration so that I can arbitrarily pick one.

Keep in mind that the house I ultimately choose must cost less than the one I am currently living in. Make sure, however, that you correct all the deficiencies that exist in my current house (the floor of my kitchen vibrates when I walk across it, and the walls don't have nearly enough insulation in them).

As you design, also keep in mind that I want to keep yearly maintenance costs as low as possible. This should mean the incorporation of extra-cost features like aluminum, vinyl, or composite siding. (If you choose not to specify aluminum, be prepared to explain your decision in detail.)

Please take care that modern design practices and the latest materials are used in construction of the house, as I want it to be a showplace for the most up-to-date ideas and methods. Be alerted, however, that kitchen should be designed to accommodate, among other things, my 1952 Gibson refrigerator.

To insure that you are building the correct house for our entire family, make certain that you contact each of our children, and also our in-laws. My mother-in-law will have very strong feelings about how the house should be designed, since she visits us at least once a year.

Make sure that you weigh all of these options carefully and come to the right decision. I, however, retain the right to overrule any choices that you make.

Please don't bother me with small details right now. Your job is to develop the overall plans for the house: Get the big picture. At this time, for example, it is not appropriate to be choosing the color of the carpet. However, keep in mind that my wife likes blue.

Also, do not worry at this time about acquiring the resources to build the house itself. Your first priority is to develop detailed plans and specifications. Once I approve these plans, however, I would expect the house to be under roof within 48 hours.

While you are designing this house specifically for me, keep in mind that sooner or later I will have to sell it to someone else. It therefore should have appeal to a wide variety of potential buyers.

Please make sure before you finalize the plans that there is a consensus of the population in my area that they like the features this house has. I advise you to run up and look at my neighbor's house that he constructed last year. We like it a great deal. It has many features that we would also like in our new home, particularly the 75-foot swimming pool. With careful engineering, I believe that you can design this into our new house without impacting the final cost.

Please prepare a complete set of blueprints. It is not necessary at this time to do the real design, since they will be used only for construction bids. Be advised, however, that you will be held accountable for any increase of construction costs as a result of later design changes.

You must be thrilled to be working on as an interesting project as this! To be able to use the latest techniques and materials and to be given such freedom in your designs is something that can't happen very often.

Contact me as soon as possible with your complete ideas and plans.

PS: My wife has just told me that she disagrees with many of the instructions I've given you in this letter. As architect, it is your responsibility to resolve these differences. I have tried in the past and have been unable to accomplish this. If you can't handle this responsibility, I will have to find another architect.

PPS: Perhaps what I need is not a house at all, but a travel trailer. Please advise me as soon as possible if this is the case.