Wednesday, July 18, 2012

Upload Profile Picture Using AsyncFileUpload Control in ASP.NET

This article shows how to preview the image before uploading the image to the server so that it can be saved into the database later. User will always like to see the image which has to be uploaded. This has been done using AsyncFileUpload(Ajax Control Toolkit) and HTTPHandler.

Here I am not interested to display the file upload control below the image control. Just these should be an image where user has to click on that to change/upload profile picture.

Below is the css for the desired UI

1. Write the below style under <head> section of asp.net page

<style type="text/css">
.FileUploadClass
{
font-size: 5px;
z-index: 500;
position: relative;
z-index: 10;
}
.FileUploadClass input[type=file]
{
background: transparent;
border: Dashed 2px #000000;
opacity: 0;
filter: alpha(opacity = 0);
width: 150px;
height: 150px;
}
.FakeFileUpload
{
position: relative;
border: Solid 1px #000000;
width: 150px;
height: 150px;
z-index: 1;
}
.FakeFileUploadDiv
{
width: 150px;
height: 150px;
position: absolute;
opacity: 1.0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
filter: alpha(opacity=100);
z-index: 5;
}
</style>


2. Below code should be placed under <body> section of asp.net page


<asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Always" runat="server">
<ContentTemplate>
<div class="FakeFileUpload">
<div class="FakeFileUploadDiv">
<asp:Image ID="imgPhoto" runat="server" ImageUrl="~/images/Employee.png" alt="Employee Photo"
Height="150px" Width="150px" />
</div>
<ajaxToolkit:AsyncFileUpload ID="AsyncFileUpload1" runat="server" ThrobberID="loader"
CssClass="FileUploadClass" OnClientUploadComplete="OnClientAsyncFileUploadComplete"
OnUploadedComplete="AsyncFileUpload1_UploadedComplete" Width="150" />
<asp:Image ID="loader" runat="server" ImageUrl="~/images/loading.gif" />
</div>
</ContentTemplate>
<asp:UpdatePanel>



3. So this is UI part. Next we need to write some server side code for “OnUploadComplete” event of AsyncFileUpload control to save the uploaded file in a “temp” folder.



   1: protected void AsyncFileUpload1_UploadedComplete(object sender, AjaxControlToolkit.AsyncFileUploadEventArgs e)
   2:     {
   3:         if (AsyncFileUpload1.PostedFile != null)
   4:         {
   5:             string uploadedFileName = Path.GetFileName(AsyncFileUpload1.FileName);
   6:             AsyncFileUpload1.SaveAs(Server.MapPath("~/temp/") + uploadedFileName);
   7:             imgPhoto.ImageUrl = "~/temp/" + uploadedFileName;
   8:             HttpPostedFile file = AsyncFileUpload1.PostedFile;
   9:  
  10:             byte[] data = ReadFile(file);
  11:             //Store the image in the session.
  12:             Session["STORED_IMAGE"] = data;
  13:         }
  14:     }


In the above code, the user selected file will be stored in server temp folder and also image control’s “IamgeUrl” is also set to the uploaded file.


Problem: Here there is no problem with file uploading, but the uploaded image will not be displayed to the user even image control’s path is changed. This is because of AJAX AsyncFileUpload control.


Solution: Image Preview before uploading


After the file is uploaded instead of saving it in the location in the server instead HttpHandler can be used which can write the uploaded image directly into the response. so no storage and less headaches.


So we don’t need lines from 5 to 8 in the above snippet. We need to have only lines 10 to 12.


i. Store the uploaded image into Session in binary format.


if (asyncFileUpload.PostedFile != null)
{
HttpPostedFile file = asyncFileUpload.PostedFile;

byte[] data = ReadFile(file);
//Store the image in the session.
Session["STORED_IMAGE"] = data;
}


Below is the code for converting image into binary format.


private byte[] ReadFile(HttpPostedFile file)
{
byte[] data = new Byte[file.ContentLength];
file.InputStream.Read(data, 0, file.ContentLength);
return data;
}



ii. After image is uploaded need to call an image handler to generate image preview. For this I am using client side event “OnClientUploadComplete” of AsyncFileUpload control.


Below is the javascript


<script language="javascript" type="text/javascript">
function getRandomNumber() {
var randomnumber = Math.random(10000);
return randomnumber;
}

function OnClientAsyncFileUploadComplete(sender, args) {
var handlerPage = '<%= Page.ResolveClientUrl("~/ImageHandler.ashx")%>';
var queryString = '?randomno=' + getRandomNumber();
var src = handlerPage + queryString;

var clientId = '<%=imgPhoto.ClientID %>';
document.getElementById(clientId).setAttribute("src", src);
}
</script>


Note: Use the randomnumber in the querystring of the handler otherwise, browser caches the first image and returns the same image again and again.


iii. Create the HttpHandler which is using (ImageHandler.ashx) in the above javascript


public class ImageRequestHandler : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
context.Response.Clear();

if (context.Request.QueryString.Count != 0)
{
//Get the stored image and write in the response.
var storedImage = context.Session["STORED_IMAGE"] as byte[];
if (storedImage != null)
{
Image image = GetImage(storedImage);
if (image != null)
{
context.Response.ContentType = "image/jpeg";
image.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
}
}
}

private Image GetImage(byte[] storedImage)
{
var stream = new MemoryStream(storedImage);
return Image.FromStream(stream);
}

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


Note: Use the IRequiresSessionState to access the session variables in the Handler.

In the above code image preview will be generated based on the binary data stored in Session variable (step 3).

Happy coding…

Tuesday, July 17, 2012

Using REPLACE in an UPDATE statement

The REPLACE function is easy to use and very handy with an UPDATE statment.

Replace searches for certain characters in a string and replaces them with other characters.

Syntax:

UPDATE <table name> SET <column name> = REPLACE(<COLUMN Name>, 'oldstring', 'newstring') WHERE <Condition>
Happy Coding…

Friday, July 13, 2012

Sending Email from GoDaddy Windows Shared Hosting using asp.net 3.5

 

The server "relay-hosting.secureserver.net" is used to send email from your hosted domain on GoDaddy.com servers. You must populate the SmtpMail object's SmtpServer property with this value.

 

// import namespace
using System.Web.Mail;
private void SendEmail()
{
   const string SERVER = "relay-hosting.secureserver.net";
   MailMessage oMail = new System.Web.Mail.MailMessage();
   oMail.From = "emailaddress@domainname";
   oMail.To = "emailaddress@domainname";
   oMail.Subject = "Test email subject";
   oMail.BodyFormat = MailFormat.Html; // enumeration
   oMail.Priority = MailPriority.High; // enumeration
   oMail.Body = "Sent at: " + DateTime.Now;
   SmtpMail.SmtpServer = SERVER;
   SmtpMail.Send(oMail);
   oMail = null; // free up resources
}



Note: GoDaddy servers will not send email containing a “From:” header entry of gmail, yahoo, hotmail, live, aim, aol or msn.

Happy Coding…