Archive for the ‘Sandbox’ Category

Asp.Net and Aweber

June 30th, 2009 by Mark Wiseman

ALFitness recently wanted to change their users email marketing tool and decided to use aweber. This looked like it would be a simple process ended up being a nightmare.

When a user joined ALFitness we would subscribe them to an email list in aweber by sending an email. This was not a problem. The problems started when we wanted to parse information from that email so it could be used in the marketing campaign.

i.e. Saving current exercise frequency and activities they enjoyed.

We would receive an email from MAILER-DAEMON@mail1.aweber.com saying:
Hi. This is the qmail-send program at mail1.aweber.com. I’m afraid I wasn’t able to deliver your message to the following addresses. This is a permanent error; I’ve given up. Sorry it didn’t work out.

It would then attach a copy of our email with the body formatted strangley:
Exercise Regularity: 1-3 times per week=0D=0AActivities Enjoyed: Home gym=0D=0A

The problem is instead of Carriage Return Line Feeds it was recieving =0D=0A. After a lot time on the phone with aweber and a lot of searching i found out that we were sending our emails with: Content-Transfer-Encoding: quoted-printable. Apparantly there are some systems that cannot recognize this and we would need to change this to 7bit. It isn’t obvious how to do this but this is how we achieved it:

Dim message As MailMessage = New MailMessage
message.From = New MailAddress(from)
message.To.Add(pTo)
message.Subject = subject

message.BodyEncoding = Encoding.GetEncoding("iso-8859-1")

Dim plainView As AlternateView = AlternateView.CreateAlternateViewFromString(body, Encoding.GetEncoding("iso-8859-1"), "text/plain")
plainView.TransferEncoding = Net.Mime.TransferEncoding.SevenBit	'VERY IMPORTANT
message.AlternateViews.Add(plainView)

Dim smtpClient As SmtpClient = New SmtpClient
smtpClient.Send(message)

Linq to SQL select and update oddity

April 24th, 2009 by Mark Wiseman

Today i came across some very odd behaviour using Linq to SQL.
I was trying to retrieve a record from the database to update one column then save the change to the database. The problem was happening when i tried to save the change. I was getting foreign constraint errors on related records that didn’t even exist! (more…)

ASP.NET Button - prevent double clicks

March 26th, 2009 by Evgeny Petrov

Virtually every asp.net developer has met the situation when a page postback takes quite some time (this is often related to web service calls at back end) and it is required to prevent user from submitting the form twice. The task sounds easy, doesn’t it? Unfortunately there is no easy and straighforward way in ASP.NET to accomplish this.  

The main problem is a default ASP.NET postback behaviour when a disabled html button (the techique is - to disable button straight after clicking) cannot submit the form. Other techiques like using html buttons, hidden fields to pass value to the server side and javascript calls to __DoPostback() are pretty cumbersome and far from being elegant.

Luckily I’ve come across the following method which is both elegant and simple:

Code behind:

protected override void OnInit (EventArgs e)
{
	// We need this to disable our button when submitting
	Form.SubmitDisabledControls = true;
	btnSubmit.UseSubmitBehavior = false;

	base.OnInit(e);
}

Page source code:





Enjoy!

CSV parsing - the easy way!

March 19th, 2009 by Mark Wiseman

Every now and then we have a client that needs to, on a regular basis, import data from one system to another and a lot of the time we go for the good old csv file. In the past i have always just written a simple function that reads each line of the file, splits it into cells and import it into the database. But this simple code never fully handles csv’s correctly. I kept thinking “there has to be a simpler way“.

So i got thinking…

Csv files are just like data tables, data tables can be queried… surely there must be a way to just treat this file as a datasource. After a bit of playing around and reading i can up with the following solution.

It requires that the csv data be saved to a file and then we can just use an OleDataAdapter to perform almost any simple SQL statment against it!

using System;
using System.Data;
using System.Data.OleDb;
using System.IO;

public static DataTable ReadCSVFileIntoDataTable(string pFilePath)
{
    string fullPath = Path.GetFullPath(pFilePath);
    string file = Path.GetFileName(fullPath);
    string dir = Path.GetDirectoryName(fullPath);

    string connString = "Provider=Microsoft.Jet.OLEDB.4.0;"
        + "Data Source=\"" + dir + "\\\";"
        + "Extended Properties=\"text;HDR=No;FMT=Delimited\"";

    string query = "SELECT * FROM " + file;

    DataTable dt = new System.Data.DataTable();
    OleDbDataAdapter da = new OleDbDataAdapter(query, connString);

    try
    {
        da.Fill(dt );
    }
    catch (InvalidOperationException /*e*/)
    { }

    dAdapter.Dispose();

    return dt;
    }

Asp.Net MVC convert View to Word Document

March 13th, 2009 by Mark Wiseman

One request we always seem to come across as developers is “Can we have a version of the page avaliable as a Word Document?”. With traditional ASP.Net this is easy. Simply place something similar to the following code block in your Page_Load.

Response.Clear();
Response.Buffer = true;
Response.ContentType = "application/ms-word";
StringWriter stringWriter = new StringWriter();
HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter);
this.RenderControl(htmlTextWriter);
Response.Write(stringWriter.ToString());
Response.End();

And that was it. Now using Asp.Net MVC it isn’t that simple. We somehow need to return this data in the form of an ActionResult. I did this by creating: 2 Controllers 1 View and 1 new ActionResult Class.

First the 2 Views: DetailedReport and DetailedReportWord.

/// <summary>
/// This view is used to display the web version of the report as a web page in the users browser
/// This Controller has a View named DetailedReport
/// </summary>
public ActionResult DetailedReport()
{
    //[...]
    return View();
}

/// <summary>
/// This view is used convert the DetailedReport view into a Word Document and send it to the user
/// This Controller does not have an associated View
/// </summary>
public ActionResult DetailedReportWord()
{
    string url = "http://localhost/Reports/DetailedReport";
    return WordActionResult.Word(url, "detailed-report.doc");
}

Now for the new ActionResult Class: WordActionResult. This class will take a URL and execute a HttpRequest. The resulting content is then streamed to the users as a Word Document

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;

namespace Revium.Utilities.MVC
{
    public class WordActionResult : ActionResult
    {
        private string _url;
        public string url
        {
            get { return _url; }
        }

        private string _filename;
        public string fileName
        {
            get { return _filename; }
        }

        public WordActionResult(string pUrl, string pFileName)
        {
            _url = pUrl;
            _filename = pFileName;
        }

        public override void ExecuteResult(ControllerContext context)
        {
            HttpContext curContext = HttpContext.Current;
            curContext.Response.Clear();
            curContext.Response.AddHeader("content-disposition", "attachment;filename=" + _filename);
            curContext.Response.Charset = "";
            curContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            curContext.Response.ContentType = "application/ms-word";

            HttpWebRequest wreq = (HttpWebRequest)HttpWebRequest.Create(_url);
            HttpWebResponse wres = (HttpWebResponse)wreq.GetResponse();
            Stream s = wres.GetResponseStream();
            StreamReader sr = new StreamReader(s, Encoding.ASCII);

            curContext.Response.Write(sr.ReadToEnd());
            curContext.Response.End();
        }
    }
}

Now you may notice that ExecuteResult is a little different to the example i gave right at the start. This is because we are not converting the current view to a Word document. We are using the DetailedResultWord Controller to convert DetaileResult to a Word document.

This is just a very simple implementation but it has certainly given us the stepping stones required to convert MVC Views to Word and Excel documents.

jQuery image captions

March 4th, 2009 by Alex Kondys

After seeing the work Adrian has done with jQuery over the past year or so, I figured it was time I started to get my head around it.

I wanted a way that the client could easily add image captions to the images they insert in their website without having to copy and paste a large amount of code just to get the effect required.

You can download the code here.

Of course, it could be neatened up a little, so feel free to grab the code and play with it as you like and post any revisions in the comments.

The jQuery function

This is the jQuery function that creates the required div’s and span’s to create the HTML output.

jQuery.fn.captions = function(value){
this.wrap("<div class='figure' style='width:"+this.attr("width");+"px;'></div>");
this.after("<span>"+this.attr("alt");+"</span>");
};

The breakdown

The following code creats a div around the image and sets the width if the image to the div so that when you float the div through CSS it floats correctly.

this.wrap("<div class='figure' style='width:"+this.attr("width");+"px;'></div>");

The following code then places a span after the image tag and inserts the value of the alt tag of the image.

this.after("<span>"+this.attr("alt");+"</span>");

The output

The following is an example of what is outputted.

<div class="figure">
<img class="figure" width="400" height="200" alt="Image caption" title="Image title" src="image.jpg"/>
<span>Image caption</span>
</div>

Using the plugin

To use the plugin, download the script and insert the following into the head area of your HTML document

<script type="text/javascript" src="jquery.captions.js"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
$("img.captions").captions();
});
</script>

Then for the images you want to add captions too, just include the following class in your image.

class="captions"

Your image tag should look something like this

<img src="test.jpg" width="400" height="200" title="Batman logo" alt="Lorem ipsum dolor sit amet, consectetur adipisicing elit." class="captions" />

Dependencies

The plugin has been tested only with version 1.3 of jQuery.

Download the plugin

Download Captions v1.