Monday, June 6, 2011

Saturday, May 29, 2010

Extreme Programming

Similar to Scrum, XP starts the process by creating a backlog of work to perform during
a sprint/iteration. XP creates the backlog by working with customers and creating
user stories. In parallel with this work, the team performs an architectural spike, during which they experiment with the features to envision the initial architecture. XP
classifies this work as the exploration phase.

The planning phase follows exploration. This phase focuses on identifying the most
critical user stories and estimating when they can be implemented. Tasks are defined
for each feature, to aid with estimating complexity. The team outlines an overall
release schedule, with an understanding that a high level of uncertainty exists until
the work begins. A release will have one to many iterations, which are typically 2- to 4-
week construction windows.
When an iteration begins, the specific plan for the iteration is revisited. The team
adds any new user stories and tasks that have been discovered since the overall release
was outlined.
XP integrates customer testing into the development iteration. The customer is
asked to identify the acceptance tests, and the team works to automate these tests so
they can be run throughout the iteration.

The planning phase is followed by the productionizing phase, during which the code
is certified for release. Certified means the code passes all customer tests plus nonfunctional requirements such as load testing, service-level requirements, and response time requirements. You can see an overview of XP in below image:



XP's characteristics:

• Specific practice —Unlike Scrum, XP is specific about the practices that should be
used during a software project. These practices include pair programming,
TDD, continuous integration, refactoring, and collective code ownership.
• Simplicity —Teams perform the minimum work needed to meet requirements.
• Automation —Unit and functional tests are automated.
• Quality through testing —Features are tested constantly, and developers check
each other’s code via pair programming.

XP’s strengths :

• Customer-focused (it’s all about user stories)
• Quality via frequent testing
• Constant focus on identifying and delivering the critical user stories
• High visibility on project status
• Great support for volatile requirements

XP's weaknesses:

• Need for team maturity —Practices such as pair programming and TDD require
responsible developers, and they aren’t always easy to obtain.
• Dependency on testing —If developers know that significant testing will take place
downstream, they may be less than diligent when they’re creating designs.
• Scalability —XP may not work well for large projects.
• Dependency on team member co-location —The team usually has a team room.


XP supports many of the critical goals of an agile process, such as dealing with volatile
requirements and delivering prioritized, working software as soon as possible. XP also
supports the principle of just enough, keeping with the lean philosophy of minimizing
waste.

XP has sometimes been criticized for its lack of formality in system documentation
and system design. In recent years this has changed, and XP teams now create the documentation needed to support a project’s customers.

Friday, May 28, 2010

Salesforce Web-to-Lead (W2L) implementation

A web-to-Lead forms is an essential component of marketing and sales automation. Its purpose is to capture data submitted by website visitors, such as contact information and product interest, and store it as a “Lead” record in a CRM product, in this case Salesforce.com.

Here in this article I will more talk about coding part of web to lead and not on how to setup your account in salesforce. This help you can get on salesforce site only.

Over here I am assuming that, you or your company already has your personal organization ID and you have also done setup in salesforce for web to lead. Setup will include
creating lead template form too. Once you are having your lead form ready you can use that generated html to post contacts to Salesforce CRM.

But over here the concern is how you can do that programmatically. Let’s check this out step by step.

1) You will be having the salesforce auto generated lead form template, copy html part of it and paste it in your applications lead.aspx page.

2) Style it well and remove org. id and return URL from the html and keep it to config file. Also keep method post of from but remove the action URL and kept that salesforce URL to config too.

3) Add validation as per need.

4) Now once you click submit button your lead.aspx.cs will get executed and in that have a method for form post. i.e.
private void FormPost(NameValueCollection collection)
{
NameValueCollection form = new NameValueCollection();
form.Add("oid", appConfig["OID"]);
for (int count = 0; count < collection.Count; count++)
{
if (collection.Keys[count].ToLower() == "returl")
{
// Update "Return URL" dynamically with 'http://' & servername
form.Add(collection.Keys[count], Request.Url.ToString().Substring(0, Request.Url.ToString().IndexOf(Request.Url.PathAndQuery)) + collection["retURL"]);
}
else
{
form.Add(collection.Keys[count], collection[count]);
}

}
WebClient wc = new WebClient();
// Posts form collection to Salesforce and get the response
byte[] res = wc.UploadValues(appConfig["SFURL"], "POST", form);
// Convert response from byte array to string
string result = System.Text.ASCIIEncoding.UTF8.GetString(res);
Response.Write(result);
}

Call this method on page load and pass Request.Form as param. That’s all you are done. Using this code, if you want to load different type of leads form dynamically then also you can do that, as the method post the form dynamically no hard coded ids are there.

Exception/Error Handling and Logging

How difficult it is to implement a good logging and error handling in your web application. Sometimes it’s hard to decide on which is the best way to implement error handling in the application. In this article I have throw light on one of third party component (dll) which provides you lots of good feature and makes error handling easy to implement.

I am talking about Log4Net dll, which is free to download and plug into your application.
Lets look into step by step implementation.


1) Create your website application or you can use your any existing site. Download the DLL file from Apache web site (http://logging.apache.org/log4net/download.html) After downloading extract the file. Now, you need to add Log4net DLL reference to your web site, right click in your application and choose add reference...


2) Now let's configure our application by adding some tags to web.config file: Inside <configSections> tag, add this tag:
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
And also add log4net tag below </configSections> i.e.
<log4net>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
<file value="C:\Temp\Log"/> <!-- path + file name -->
<staticLogFileName value="false"/>
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="_yyyy_MM_dd".html"" /> <!-- suffix of filename & extention -->
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%m" />
</layout>
</appender>
<!-- Add below appender only if you want to sent error mail too -->
<appender name="SmtpAppender" type="StoreManager.Utilities.EmailService"><!—- namespace of wrapper class -->
<to value="abc@xyz.com,efg@xyz.com" />
<from value="StoreManager@xyz.com" />
<subject value="Unhandled Exception: Store Manager" />
<smtpHost value="smtpHostName"/>
<lossy value="false"/>
<evaluator type="log4net.Core.LevelEvaluator">
<threshold value="ERROR"/>
</evaluator>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%m" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingFile" />
<appender-ref ref="SmtpAppender" />
</root>
</log4net>


3) Create a Enum for log level

namespace StoreManager.DataModels
{
public class Constants
{
public enum LogLevel
{
DEBUG = 1,
ERROR,
FATAL,
INFO,
WARN
}
}
}


4) Create a logger class

using System;
using log4net;
using log4net.Config;
using System.Web;
using System.Text;
using System.Diagnostics;

namespace StoreManager.Utilities
{
public static class Logger
{
#region Members
private static readonly ILog logger = LogManager.GetLogger(typeof(Logger));
#endregion

#region Constructors
static Logger()
{
XmlConfigurator.Configure();
}
#endregion

#region Methods
public static void WriteLog(Constants.LogLevel logLevel, String log)
{
switch (logLevel)
{
case Constants.LogLevel.DEBUG:
default:
logger.Debug(log);
break;
case Constants.LogLevel.ERROR:
logger.Error(log);
break;
case Constants.LogLevel.FATAL:
logger.Fatal(log);
break;
case Constants.LogLevel.INFO:
logger.Info(log);
break;
case Constants.LogLevel.WARN:
logger.Warn(log);
break;
}
}

public static string GenerateLogInfo(Exception ex)
{
StringBuilder sbBody = new StringBuilder();
string sURL = HttpContext.Current.Request.Url.ToString();
if (sURL.IndexOf("error.aspx") < 0)
{
string Stack = "";
StackTrace Trace = new StackTrace();
int FrameCount = Trace.FrameCount;
// We skip frame 1 on the stack since that is always the current method //
for (int index = 1; index < FrameCount; index++)
{
if (index > 1)
{
Stack += " --> ";
}
Stack += Trace.GetFrame(index).GetMethod().ToString();
}
Stack = (Stack != "" ? Stack : ex.StackTrace);
Stack = (ex.InnerException != null ? ex.InnerException.StackTrace + "\n" : "") + Stack;
if (Stack == "")
{
Stack = "Stack trace not available.";
}
string exceptionMessage = ex.InnerException != null ? ex.InnerException.Message : ex.Message;
sbBody.Append("<br><table border='1'><tr><td>Time: " + System.DateTime.Now.ToString() + "</tr></td>");
sbBody.Append("<tr><td>URL: " + HttpContext.Current.Request.Url + "</tr></td>");
sbBody.Append("<tr><td>User IP: " + HttpContext.Current.Request.UserHostAddress + "</tr></td>");
sbBody.Append("<tr><td>Error Message: " + exceptionMessage + "</tr></td>");
sbBody.Append("<tr><td>Stack: \n" + Stack.Replace(" ", " ") + "</tr></td></table>");
}
return sbBody.ToString();
}
#endregion
}
}


5) Smtp appender wrapper – Use this class if required

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using log4net.Appender;
using System.Net;
using System.Net.Mail;

namespace StoreManager.Utilities
{
/// <summary>Sends an HTML email when logging event occurs</summary>
public class EmailService : SmtpAppender
{
/// <summary>Sends an email message</summary>
protected override void SendEmail(string body)
{
SmtpClient smtpClient = new SmtpClient();
MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress(From);
mailMessage.To.Add(To);
mailMessage.Subject = Subject;
mailMessage.Body = body;
mailMessage.Priority = Priority;
mailMessage.IsBodyHtml = true;

smtpClient.Host = SmtpHost;
smtpClient.Send(mailMessage);
}
}

}


6) Add below code in Global.asax.cs for global error handling.

protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
HttpException httpException = exception as HttpException;
Response.Clear();

if (httpException != null)
{
Logger.WriteLog(Constants.LogLevel.ERROR, Logger.GenerateLogInfo(exception));
Server.ClearError();
Response.Redirect("~/error.aspx");
}

}

Now we are done with all and this will generate day wise log of errors in html, and also same log will be mailed to listed persons in html format.

This will generate email and log somewhat as below:

Thursday, May 27, 2010

Convert a column with comma saperated row/string in sql

Here we go, to convert a column into row or string separated by a delimiter, we can use coalesce. Just create below function and call it for your SP. Avoid where condition and parameter if not required.

create FUNCTION ConvertColumnToRow (@id int)
RETURNS varchar(100)
AS
BEGIN
DECLARE @List varchar(100)
SELECT @List = COALESCE(@List + ', ', '') + CAST(Name AS varchar(10))
FROM Employee
WHERE ID = @id
RETURN(@list)
END;
go

CSS based lightbox takes seconds to implement

If you want to implement lightbox in short time with less effort and compatible with FF and IE here you go. Copy-paste below html in your page replaces the content and you are done.

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Untitled Page</title>
<style type="text/css">
.black_overlay{
display: none;
position: fixed;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
background-color: black;
z-index:1001;
-moz-opacity: 0.8;
opacity:.80;
filter: alpha(opacity=80);
}
.white_content {
display: none;
position: absolute;
font-family: Verdana;
top: 25%;
left: 25%;
width: 50%;
height: 50%;
padding: 16px;
border: 16px solid orange;
background-color: white;
z-index:1002;
overflow: auto;
font-size:small;
}
#screenshot {
BORDER-BOTTOM: #ccc 1px solid;
POSITION: absolute;
BORDER-LEFT: #ccc 1px solid;
PADDING-BOTTOM: 5px;
PADDING-LEFT: 5px;
PADDING-RIGHT: 5px;
DISPLAY: none;
BACKGROUND: #333;
COLOR: #fff;
BORDER-TOP: #ccc 1px solid;
BORDER-RIGHT: #ccc 1px solid;
PADDING-TOP: 5px
}
</style>
</head>
<body>
<div>
this is body content

<input type="button" value="Click here to load lightbox" onclick="document.getElementById('light').style.display='block';document.getElementById('fade').style.display='block'" />
</div>
<div id="light" class="white_content">
<a href="javascript:void(0)" onclick="document.getElementById('light').style.display='none';document.getElementById('fade').style.display='none'">
Close</a><br />
<br />
<br />
<div id="container" runat="server">
Put your lightbox content over here
</div>
</div>
<div id="fade" runat="server" class="black_overlay">
</div>
</body>
</html>

This will look something like below:

Global, Generic & Custom JQuery tooltip

Using script and styling generate custom tooltip.

Code:

<html>
<head>
<title>jQuery Tooltip</title>
<style type="text/css">
body { font-family: verdana, arial, sans-serif; font-size: 0.8em; background-color: black; color: white; }
a { color: white; } #example a:hover { text-decoration: none; }
span.show-tooltip-text { display: none; position: absolute; font-size: 0.9em; background-image: url(bg.gif); background-repeat: repeat-x; padding: 6px; padding-left: 12px; padding-right: 12px; color: white; }
</style>
<script language="JavaScript" src="JQuery.js"></script>
<script language="JavaScript">
ShowTooltip = function(e)
{
var text = $(this).next('.show-tooltip-text');
if (text.attr('class') != 'show-tooltip-text')
return false;

text.fadeIn()
.css('top', e.pageY)
.css('left', e.pageX+10);

return false;
}
HideTooltip = function(e)
{
var text = $(this).next('.show-tooltip-text');
if (text.attr('class') != 'show-tooltip-text')
return false;

text.fadeOut();
}

SetupTooltips = function()
{
$('.show-tooltip')
.each(function(){
$(this)
.after($('<span/>')
.attr('class', 'show-tooltip-text')
.html($(this).attr('title')))
.attr('title', '');
})
.hover(ShowTooltip, HideTooltip);
}

$(document).ready(function() {
SetupTooltips();
});
</script>
</head>
<body>
<input type="submit" value="Example Button" class="show-tooltip" title="<strong>HTML</strong> works as normal inside the tooltip.<br/>Multi-line tooltips look and function perfectly fine, as well!"/>
</body>
</html>

This will end up something like below: