Showing posts with label Tips. Show all posts
Showing posts with label Tips. Show all posts

Saturday, March 28, 2009

Resolution: The Underlying Connection Was Closed

You usually got this exception when trying to use System.Net.HttpWebRequest class in .NET 1.1 for creating internal URL calls from your ASP.NET code. The exception is also reproducible when trying to invoke webservices using the proxy class.

By default, there is two concurrent connections in every ASP.NET application. As ASP.NET is a service it may require more than two concurrent connections to handle the requests. When you try to request URL from your ASP.NET code, ASP.NET may not be able to handle it. The solution is to increase the number of the concurrent connections which ASP.NET can handle. You can do so by modifying the "connectionManagement" element in the configuration file. For more information about the problem and its resolution, check this post.


Wednesday, March 18, 2009

Blocking IP Addresses Using MMC

I was searching for a solution to block any communication with specific IP addresses. I have come to this solution using MMC (Microsoft Management Console). The following steps will allow you to block any communication - whatever the protocol is - with specific IP addresses or subnet:

1. Open Start Manu > Run > Write "MMC". Then press Enter.
2. In the Management Console > File > Add/Remove Snap-in...
3. In the opened dialog, leave "Local Computer" as it's and click "Finish".



4. You will have a new node in the left tree called: "IP Secuirty Policies in Local Computer".
5. Right click on this node and select "Create IP Security Policy".
6. In the opened dialog, write "Block IP".
7. Click Next till the end of the wizard and then "Finish".
8. You will have an item in the left pane called: "Block IP". Right click on it and select "Properties".



9. In the opened dialog, click "Add".
10. Go through the wizard, till you reach a step called: "IP Filter List".
11. Click "Add". IP Filter Dialog will open.



12. Modify the name of your IP Filter and click "Add" to add an IP filter policy.
13. Click "Next. Leave "Source Address" as "My IP Address".
14. In the destination address, you can select "A specific IP Address". You can also filter by DNS or subnet. Enter the IP address to block. Then click Next.



15. Leave the protocol to be "Any" and click "Next".
16. Then click "Finish".
17. Apply all changes, and close all the opened windows. You may have to add "Block" action if it doesn't exist.
18. After you finish, don't forget to write click on "Block IP" policy and select "Assign".



Now try to ping the blocked IP addresses. You should get "Destination Unreachable" message.


Tuesday, March 17, 2009

Maintenance Plans in SQL Server

Creating backups for your database is an essential task in every environment especially for critical data storage. But have you ever ask yourself how to create your backups in a periodic manner - say every week or so? If you was able to do so, how will you manage the space in your disk? Maybe you don't want to keep any backup files older than one month.

The first solution you may think about is to create a SQL script and execute it in a custom job. But wait, SQL Server can do it for you and save alot of this implementation hassle. In the SQL Server, you have the option to create "Maintenance Plan" for your database. This plan provides you with more advanced options for creating backups for the data and the transactions logs.

When you create a new plan, you will have to go through a configuration wizard. The interesting part is in the backup configurations. You can provide how often you want to backup your database (i.e every week, month or so). You also specify how long you want to keep the backup files and when to remove it (i.e You may remove any backups older than one month) so that you save your storage space. Another interesting point, you can create only one plan for more than one database. The plan can be configured also to create a separate backup folder for each database.

The maintenance plan is a periodic task which needs a running job. This is why it requires a running SQL Server Agent in your database server.


Sunday, March 08, 2009

Resident Evil

Do you know about the time-bomb viruses? Those ones which start execution in a certain time frame. Today, I have a similar behavior but this time not a virus. It's an evil code.

We have an application on the production environment which has been created seven years ago. The project seems to be working properly for a long time with no massive problems. However, an exception suddenly encountered when any user try to edit some data items.

Microsoft VBScript runtime error '800a0006'
Overflow: 'CInt'
/newsline/newsline/dbshell.asp, line 641
The project was implemented in classic ASP and VB script. If you had the opportunity to work with this crappy-style languages, you can imagine how debugging in this kind of code is missy. So I had no way except to analyze the exception getting the most out of it.

If you notice, it's an overflow exception. This means that CInt has got some large integer number to convert and failed to. After googling, I have found that there is a maximum limit for this method input and it's 32768. From a second look in the exception, you can see that it happens in a file called: "dbshell.asp". This leads to conclude that the number this method is trying to convert is retrieved from the database.

This was actually a good guessing. In the production environment and after seven years, some data table in the database reached to have more than 33974 records. The method couldn't convert any sequence ID for any items with ID larger than 32768. The issue couldn't be captured in the quality test as this low level test case couldn't be considered or even thought to be problematic.

The developer who wrote this code from seven years ago didn't imagine that some day the number of the records will reach this limit. The exception was resident to blow up after these long period. These lead us to an old lesson. At the time of building your application, you don't think that your application will last for long. You need to consider which data you think will go large and which is not. Hence you follow the appropriate guidance in the implementation.


Saturday, November 08, 2008

PRG Pattern - You're Already Doing it

Have you ever had this message dialog asking about resubmiting the data when you try to refresh a web page? This actually happen after submitting a form or enter your login information.

One of the good practices when developing web application is to redirect the user after a successful posting request. This practice is refereed as PRG pattern (Post/Redirect/Get). The target is to avoid duplicate post requests from the client and providing a smooth navigation through the web application.

What actually happen in PRG is that the browser try to send an HTTP 303 redirect request along with HTTP "Location" header. It's nice to know that something you're used to make as a default practice is actually a pattern. The following is a sample code in ASP.NET MVC illustrating the usage of the pattern:

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ChangePassword(string currentPassword, string newPassword, string confirmPassword)
{
    if (ModelState.IsValid)
    {
        MembershipUser currentUser = Provider.GetUser(User.Identity.Name, true /* userIsOnline */);

        // Attempt to change password
        bool changeSuccessful = currentUser.ChangePassword(currentPassword, newPassword);

        if (changeSuccessful)
           return RedirectToAction("ChangePasswordSuccess"); //PRG Pattern recommendation
    }

    return View();
}


Wednesday, October 01, 2008

Javascript - Access Denied When Calling Window Opener

We usually use the "open" method in the window object to open a new window in Javascript. However, sometimes you need to change some values in the parent window depending on the changes of the new window elements values or you may need to call a method in the parent window from the child one. To do so, you can use the "opener" property in the window object to access the parent page elements. The following Javascript statement access an input element in the parent window with "txtEmail" ID and update its value:

window.opener.document.getElementById("txtEmail").value = "mohammedn@mailhost.com";
You can even call a method direct in the parent window from the new opened one:
window.opener.SomeMethodInTheParentWindow();
However, you may get "Access Denied" or "Permission Denied" message when trying to access the "opener" property in the popup window. This usually because you call the window.open with the full path of the pop window:
window.open('http://www.domain.com/accounts/register_popup.aspx');
To resolve this issue, use the relative path of the popup page instead of the full path when opening it and you will be able to safely access the opener property of the window.
window.open('accounts/register_popup.aspx');


Thursday, June 12, 2008

MbUnit 2.4 - Avoiding Crappy Data Resulted From The Test

One of the nice features in MBUnit 2.4, is the ability to rollback the crappy data in the database resulted from running subsequent test methods. This is really interesting because this crappy data can become a nightmare during the application development or even after the deployment. You will spend pretty much time exploring your data to filter the dirty ones which can lead sometimes to some mistakes.

MbUnit give you the ability to rollback any changes made in the database during the test. Using MbUnit 2.4, this can be done by referring MBUnit.Framework.2.0 in the project references and using RollBack2 attribute for each test method.

[Test]
[RollBack2]
public void InsertNewProductTest()
{
      Product product = Product.CreateNew('Nokia 800', 2300, true);

      Assert.AreEqual('Nokia 800', product.Name);
      Assert.AreEqual(2300, product.Price);
      Assert.AreEqual(true, product.InStock)

      ProductRepository.Persist(product);
}

In the later example, any changes made in the database by persisting the Product object will be rolled back after the test execution. This will keep your tables clean containing only your application live data.

MBUnit uses TransactionScope in System.Transactions to provide the rollback functionality. However, you will need to set some security configurations for the DTC settings in order to make the TransactionScope properly work. To set these settings, open the Component Services in the Administrative tools. Then, show the properties of your computer and select MSDTC tab. Open the Security configurations and setup the needed settings for the remote and local authorization of the transactions on your machine.

As a side note, you are able to track the operating transactions by putting some break points inside your test method. Then, in the Component Services under the Transaction list you will find your active transactions listed there. More so you can check the Transaction Statistics to track the committed and aborted transactions of your test operations.


Monday, March 24, 2008

jQuery Validation Plugin

We start to see several plugins in the web based on the jQuery library. I have the chance today to work a bit with a plugin called: jQuery Validation Plugin by Jörn Zaefferer - which enable you to apply client validation to your web forms using jQuery.

To get started, you have to download the plugin files from this link. And sure the jQuery library as well: jQuery 1.2.2. Then, you should have: jquery.validate.js and jquery.js files reside on your project somewhere and linked in your markup.

IMPORTANT NOTE: I had a problem when using jquery.validate with the new vesrions - higher than 1.2.2 - of jQuery library. jquery.validate uses functions in jQuery library which no longer exist.

The following sample is the simplest one. You use the selector to get the form element. Then, you call the validate function.

<script language="text/javascript">
    $(document).ready( function() {
         $("#simpleSignUp").validate();
    }
</script>


In this case, you will have to set some predefined metadata in the class attribute of the elements telling the library the required rules to apply for the form inputs.
<form id="simpleSignUpForm" action="" method="get">
        <input type="text" id="firstname" class="required" minlength="2"/>
        <input type="text" id="lastname" class="required" minlength="2"/>
        <input type="text" id="username" class="required" minlength="2"/>
        <input type="text" id="email" class="required email" minlength="2"/>
        <input type="text" id="password" class="required" minlength="8" />
        <input type="text" id="website" class="url" />
        <input type="submit" value="Submit" />
</form>


In this case, the plugin will use some defaults error messages for validating the inputs. However, you can have more controls on the errors and rules. The following sample show in details how you can validate a full sign up form elements by specifying the rules with the associated error messages. In this sample, you won't have to apply any CSS styles as you already defines explicitly your rules.
<script type="text/javascript">
        $(document).ready( function() {
               $("#signupForm").validate({
                           rules:{
                                           username:{
                                                               required:true,
                                                               minlength:2
                                           },
                                           password:{
                                                               required:true,
                                                               minLength:5
                                           },
                                           confirm_password:{
                                                               required:true,
                                                               minlength:5,
                                                               equalTo:"#password"
                                           },
                                           email:{
                                                               required:true,
                                                               email:true
                                           },
                                           topic:{
                                                               required:"#newsletter:checked",
                                                               minLength:2
                                           },
                                           agree:"required"
                            },
                            messages:{
                                           username:{
                                                               required:"Please enter a username",
                                                               minLength:"Your username must consist of at least 2 characters"
                                           },
                                           password:{
                                                               required:"Please provide a password"                                                                minLength:"Your password must be at least 5 characters long"
                                           },
                                           confirm_password:{
                                                               required:"Please provide a password",
                                                               minLength:"Your password must be at least 5 characters long",
                                                               equalTo: "Please enter the same password as above"
                                           },
                                           email: "Please enter a valid email address",
                                           agree: "Please accept our policy"
                            }
               });
        }
</script>






For more information about the methods you can use for the validation, check it here.

The way you define your rules and messages are unified and configurable. You define a message per rule which is extremely a need in any web project. It's common to have several validation rules with different error messages in the same web form. When I see this style, I just remember the Design by Contract style in which your requirements (contract) are easily mapped to rules (benefits and obligations). It's similar as you put all your quality matrix in one place. Besides, it's easy to modify as like as you set some configurations to your web form!

Another point to mention is the different scenarios you can have and how this library fit it. In the last sample, you can see how you check for password confirmation, input formats (emails, URLs ... etc.) and user selections.

You can modify the CSS style of your validation errors - i.e how the input controls will look like in case of a validation error occurred. You simply modify the following snippet to have different look for the validated inputs.

div.error { display: none; }
input { border: 1px solid black; }
input:focus { border: 1px dotted black; }
input.error { border: 1px dotted red; }




This plugin is perfect for ASP.NET MVC. Actually, there is already some tries like Validator Toolkit for ASP.NET MVC which enable client and server side validation for MVC. It uses jQuery as well for the client validation. I don't think jQuery Validation is easy to be used in ASP.NET web forms as the page structure actually differs. However, we may find some other versions suitable for ASP.NET Web Forms in the future.

Unlike the ASP.NET validation controls which you need to inject inside your markup, jQuery Validation Plugin puts all the validation rules in one place. I think this really a benefit. In fact, this is one of the benefits of using jQuery itself - thanks for the nice selectors. This style definitely enhance your code readability by separating the validation stuff away from the markup giving the designers - and even the devs - more clean markup to work in.


Saturday, March 01, 2008

Get the Last Run Query in SQL Server 2005

Have you ever run an update or delete query by mistake and you need to roll back or at least want to know the last run query to fix the problem? The following SQL statement can help in that.

SELECT deqs.last_execution_time AS [Time], dest.text AS [Query]
FROM sys.dm_exec_query_stats AS deqs
CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) AS dest
ORDER BY deqs.last_execution_time DESC
This will retrieve the last run queries with its execution time.


Saturday, February 16, 2008

Securing Configurations

Have you ever wanted to provide a level of protection to your values in the configuration files? aspnet_regiis will help you in encrypting the configuration section(s) in your config files. The executable resides in: "<windows_root>\Microsoft.NET\Framework\<framework_version>" and it was common to be used in installing ASP.NET on IIS. However, you can use it as well in encrypting/decrypting the configuration files.

Here is the command line used for encrypting a section in the web.config of SecureWebProj application:

aspnet_regiis.exe -pe connectionStrings -app /SecureWebProj

-pe attribute is used to tell the executable to encrypt the specified section. You can also use -pd attribute instead of -pe if you want to restore or decrypt the section to its original values. -app attribute is for specifying the application virtual path.

After encrypting the connectionStrings section, the web.config will look like that:

<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
<EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<KeyName>Rsa Key</KeyName>
</KeyInfo>
<CipherData>
<CipherValue>j2E3lO/bMp8ljiDFKhRJu33zVD0mrXD7k5WV4nQ5uNJEav7cKcjhtO1ztCfxJw7ZE5uNdj+THVwJroZBoPEhtPAISPH75Zq
5C1G+5WOLcBwBBzbcp7C6i6U7+/IWmThTNFRAEdQp/lHryDkapep4MNUCGNZlcVLlmX0n/bqZEoE=</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>
<CipherValue>D/Z9ZyH7P+9e3kDi5gLevpdqbjwia0uQ/cOB0gHVXc8=</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20


Sometimes you just need to map the operation direct to the application physical path. This would be useful if you are using ASP.NET Development Server instead of IIS.
aspnet_regiis.exe -pef connectionStrings E:\Projects\SecureWebProj

Encrypting the configuration sections won't prevent you to access the configuration values from your code. If you have already completed the project and you need to encrypt some sections inside the configuration files, you don't have to modify your application code anymore. The code will still run properly and won't be affected by the encryption changes.

The nice part is that you can encrypt the web.config sections even within your code. The following sample encrypts the connectionStrings section in the web.config of SecureWebProj:

Configuration cfg = WebConfigurationManager.OpenWebConfiguration("/SecureWebProj");
ConnectionStringsSection section = (ConnectionStringsSection)(cfg.GetSection("connectionStrings"));
section.SectionInformation.ProtectSection("RsaProtectedConfigurationProvider");
cfg.Save();
1
2
3
4


You may ask: This is an encryption operation, so where the encryption keys? Actually, each .NET installation will create by default a new key container in your machine formally called: NetFrameworkConfiguarationKey. This will contains the needed keys for the providers to work. However, you can create a new key container using aspnet_regiis as well.
aspnet_regiis.exe -pc SecureKeyContainerName -exp

You may find more about securing your key containers in this MSDN entry: Securing ASP.NET Configuration. In the later command line, -exp attribute means that the key container is exportable. You can export this container to XML file and use it in any other machine. This would be useful if your application is running in a web farm and you want to share the encrypted configurations across the farm machines.

DZone


Saturday, December 22, 2007

Image Resizing

Sometimes you need to process the users' uploaded images in your web application so that it doesn't take too much space. This can be done either by resizing the uploaded image, saving it in a specific format or may be both.

The following is a code snippet for resizing images and saving it in *.jpeg format. The method take the image file to be resized as a stream, the destination path, the file name to save the image as and the maximum side size of the image (i.e the output image should fit a square of this maximum side size).


public static void ResizeImage(Stream originalImageStream, string destinationFilePath,
string destinationFileName, ImageEncoding saveEncoding, int maxSideSize)
{
int intNewWidth;
int intNewHeight;

Bitmap original = new Bitmap(originalImageStream); // your original image

//Set the image format
ImageFormat fmtImageFormat = original.RawFormat;

//Get the image original width and height
int intOldWidth = original.Width;
int intOldHeight = original.Height;

//Determine if Landscape or Portrait
int intMaxSide;

if (intOldWidth >= intOldHeight)
{
intMaxSide = intOldWidth;
}
else
{
intMaxSide = intOldHeight;
}


if (intMaxSide > maxSideSize)
{
//set new width and height
double dblCoef = maxSideSize / (double)intMaxSide;

intNewWidth = Convert.ToInt32(dblCoef * intOldWidth);
intNewHeight = Convert.ToInt32(dblCoef * intOldHeight);
}
else
{
intNewWidth = intOldWidth;
intNewHeight = intOldHeight;
}


Size resolution = new Size(intNewWidth, intNewHeight); // size of your thumbnail

Image thumbnail = new Bitmap(original, resolution);

Graphics g = Graphics.FromImage(thumbnail);

// The InterpolationMode was the catalyst to eliminate pixelation.
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;

g.DrawImage(original, new Rectangle(0, 0, thumbnail.Size.Width, thumbnail.Size.Height));


// Prepare for a controlled-quality JPEG export
ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
Encoder jpegEncoder = Encoder.Quality;
EncoderParameters jpegEncoderParameters = new EncoderParameters(1);
EncoderParameter jpegEncoderQuality = new EncoderParameter(jpegEncoder, 100L /*jpegQuality*/);

jpegEncoderParameters.Param[0] = jpegEncoderQuality;

thumbnail.Save(destinationFilePath + destinationFileName + ".jpg", jpegCodec, jpegEncoderParameters);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

You will have to get the appropriate codec information to save the image.

ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
1

The following is the implementation of GetEncoderInfo.
private static ImageCodecInfo GetEncoderInfo(string encoderString)
{
foreach (ImageCodecInfo info in ImageCodecInfo.GetImageEncoders())
{
if (info.MimeType == encoderString)
return info;
}

return null;
}
1
2
3
4
5
6
7
8
9
10


Simply you loop through all the encoders in ImageCodecInfo to find JPEG codec info. Other codecs info can also be retrieved for other image types like PNG, JIF and BMP.

The interesting point is in specifying the quality of your output image so that you avoid the pixelation problem and make your output image looks smooth. You declare a new Encoder Parameter with the required quality of your output image. Then you pass the encoding parameters when saving the final resized image.

// Prepare for a controlled-quality JPEG export
ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
Encoder jpegEncoder = Encoder.Quality;
EncoderParameters jpegEncoderParameters = new EncoderParameters(1);
EncoderParameter jpegEncoderQuality = new EncoderParameter(jpegEncoder, 100L /*jpegQuality*/);

jpegEncoderParameters.Param[0] = jpegEncoderQuality;
1
2
3
4
5
6
7

The quality encoder parameter may have varying values (i.e. 25L, 50L, 75L and 100L). You will have to tune it to balance the quality with the output image size.

Another point to mention that there are many other interesting encoders you can make use of like Encoder.Transformation - which allowing you to rotate or swap your images. You can find more information here.


Thursday, December 20, 2007

Language-specific Code Compilation in App_Code

App_Code folder is the default location to add your code files for your ASP.NET project. You may have the situation when you want to add mixed code files written in different languages i.e C# or VB.Net and you need to include these mixed files in the project compilation. The question: Can I have mixed files some written in C# and others in VB.NET in the App_Code folder? Yes, you can but in limitation. First, you will have to add different folders for each language-specific code. Then, in web.config add an entry for each folder inside CodeSubDirectories tag.

<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true">
<codeSubDirectories>
<add directoryName="CSharpFolder"/>
<add directoryName="VBFolder"/>
</codeSubDirectories>
</compilation>
</system.web>
</configuration>
If the folder you added to codeSubDirectories tag doesn't physically exist, you will have a compilation error.
The code subdirectory '/MyProject/App_Code/CSharpFolder/' does not exist. E:\Projects\MyProject\web.config 


Saturday, October 20, 2007

Scrum in Action

We are now working in a project which have taken more than 6+ months and still in progress. 159078+ lines of code, 80+ page, 120+ user controls, 100+ tables and counting. In projects with such scale, you need to manage and control your development life cycle. You want to decrease all risks and possibilities of failure. Working with Scrum methodology helps a lot in making developers time management more efficient.

I'll try to state some points which helps us during the development of the project. My recommendation points maybe a part of the scrum definition and maybe not. But sometimes practice is more trivial than science. The following are the concluded results.

Design meetings: In each project you have to design. But as a fact, the design will change. So all what you need is to put the outlines. You don't have to state all the details. Try to make the design meetings for things which is really need a heavy mind storming and architecture. This includes frameworks, libraries and infrastructures. Discussing the design of each part in the project is a time consuming and won't help you that much.

Time Estimation: When estimating the time of the tasks, it should be in the presence of your team members as it's a part of the sprint planning. The sprint planning is usually a long boring meeting. For each task, each member will make an estimate. Then the average will be the final estimate of the task. If some member give an estimation which isn't reasonable or far away of the others estimations average, you start to ask him why? He may know something in the task which is mysterious, may take more time or may need more resources. Depending on all these discussions you will get a better estimation and better time management.

Another point, if a task will take more than 2 days, you should start to think about dividing it. Most of the uncompleted and bottlenecks in the projects are the long estimated tasks. The estimation of the long tasks are usually not accurate. Even the scrum master won't be able to know your progress each day if you just telling him "I am still working on it". Try to divide your task to smaller parts so that you can give it a better estimation.

Daily meetings: The essence of the scrum is the daily scrum meetings. If you didn't do it daily you will lose process monitoring. The team activity will be degraded. You won't be able to finish the work on the estimated time. Try to keep on this 15 min. meeting every day. Try to keep these meetings physical as much as you can. I mean here to avoid instant messaging meetings or such stuff. Instant messaging meetings takes much time than the physical ones. People don't take care about the time while messaging and the scrum master won't be able to control it. Try to determine a fixed time for the meeting each day - ideally - 15-30 min. maximum - and make sure it doesn't exceed the time limit.

Code Review: Usually you will need to refactor some parts of your code with your teammates. Code Review Meeting is your way to do that. Problems exists when you try to make "code reviews" as a rule in each sprint. It doesn't work like that. From my experience don't do any code review if you don't have a predefined list of your targets and you really have a problem you want to solve. If you have nothing to review in these meetings, then it will be a hassle and it will be something other than a technical meeting! It will be time consuming and the meeting will end up with nothing. Specify the targets of the meeting before scheduling it. Team members may inform the scrum master if they think there is a part in their code should be refactored in attendance of the other team members.

Design Changes Reporting: Keep all design documents on your source control or repository folder. Make sure that any updates on the designs, flow, sequence diagrams or even requirements modifications are accessible for all the team members. Problems occurred if one of the team members changes something in the design or the flow and didn't inform the others about it. The best practice is to update your documents with any modifications and commit it in your repository. Not only that but you should inform the others about your modifications and the member you think his work will be affected with your changes.

Bug Fixing: During the sprint, testers may start to test your work of the previous ones. Bugs will be accumulated and it's not considered as a part of the sprint estimation. You have 2 choices, either allocate a member in your team to fix all these stuff or assign the bugs to their owners. The later option - if not well controlled - will contradict with the scrum rules. The developers will have an increasing bug list and will feel that they don't make any progress. The solution is to postpone any generated bugs through the sprint to the next one. Testing the work during the development is really a mess . Testers may report some bugs which are features to be implemented on the sprint. Still the bugs should be reported but not assigned to the developers during the sprint. It should be postponed. In the next sprint meeting it will be considered in the developers estimation.

Injecting Members to the Team: You have time constraints and you want your developers to take care of the new features. But in the same time, you have a list of bugs to be fixed. Don't inject external developers to fix these bugs. Especially if they don't have enough idea about the project and the requirements. You will end up with a longer bug list!

This is my review about the best practice which makes the scrum process more efficient. Still it's not that perfect on all the time. Try to modify the process to fit your needs. Although learning and reading is so important to improve your process, but still nothing better than practice.

Dzone - Vote for for this article!
Stumbleupon - Add Your Review


Monday, March 19, 2007

IP-To-Country Mapping

I have just found this interesting IP-To-Country mapping database which enables you to map a certain IP Number to Country. The problem is that this database is not alwayes up-to-date. So, you may take care of this point when you using it. Also, you should check the copyrights section if you want to use it in a commercial applications. The database uses IP Number ranges for identifying the addressed country.


Friday, February 23, 2007

Filtering Procedures.. Do you make it right?

All of us do filtering in their project. It's one of the most repeated functionalities. But do we make it well? How do you make your filtering procedures? Ok.. Have a look on the following one:

CREATE PROCEDURE std_GetFiles
@fileCategory varchar(50),
@tag varchar(50)
AS
declare @SQL as nvarchar(200)

SET @sql = 'SELECT * FROM tscoFileIndex WHERE '

if @fileCategory <> null
set @sql = @sql + ' FileCategory = ' + @fileCategory + ' and '

if @tag <> null
set @sql = @sql + ' tag = ' + @tag + ' and '

SET @SQL= LEFT(@SQL, LEN(@SQL) -4)

GO


This is the first way come to your mind when you trying to do filtering. But take care. Actually, all the string concatenation in this procedure make your data under threaten. As this allow procedure users to inject sql statements inside your concatenated query by passing unexpected paramaters through "fileName" and "tag" inputs. Also the many if conditions here affects your procedure performance.

The alternative, which is better than this, would be something like that:

CREATE PROCEDURE std_GetFiles
@fileCategory varchar(50),
@tag varchar(50)
AS

SELECT *
FROM tscoFileIndex
WHERE (@fileCategory is null OR FileCategory = @fileCategory ) AND (@tag is null OR tag = @tag)

GO


So, you match all rows if the parameter is null, and use the
condition when the parameter is not null.

kick it on DotNetKicks.com


Friday, September 29, 2006

RSS Feed Available Now!

You can keep uptodate with any post sent on this blog through the blog RSS feed. This is an XML-based file that you can use to display the blog posts in any RSS feed enabled softwares. Simply you add the blog RSS Feed to your software feeds and any new post will be displayed there.

For example, if you use Gmail, you will find a "Web Clip" bar in the top of your mail client, showing your favorites feeds. You can add all favorite feeds from different URLs and all will be dispayed in this web clip.



My Weblog RSS Feed is: http://mnour.blogspot.com/rss.xml


Thursday, July 27, 2006

Port Forwarding

If you have a server inside your LAN and you hope to access this server from WAN (ex: internet), unfortunatlly, you will not be able to access this server with out making some changes to your router configurations. So that, any requests comes from port 80 will be forwarded to the server LAN IP address.

For example, suppose you server local IP address is 198.65.1.144, and WAN address: 81.44.1.70. In your router configuration, forward any request comes on port 80 to 198.65.1.144. In this way, you will be able to access the server from the internet by addressing: http://81.44.1.70

Of course this not just for port 80, for example, you server may receives the HTTP requests on another port, say 8080. So, you do the previous steps as it is but with this port number. And you will be able to connect to server from the internet by addressing: http://81.44.1.70:8080


ASP Problem in IIS6 and Windows Server 2003

You may encounter a problem in running classic ASP in IIS6/Windows Server 2003. So you may try to test an ASP page on IIS6 and you get "Page Not Found" error. This is beacuase IIS6 by default doesn't enable any Scripting language. HTML is the only script enabled by default

To enable ASP Scripting, just open your IIS6 and on the left tree view. Click on "Web Service Extensions". The exiting extensions on the server will be listed. Click on “Active Server Pages” extension and enable it by clicking on “Allow” button. Then make a test ASP page and make sure that ASP scripting is working well.


Friday, July 21, 2006

Using SOAP Tool Kit 3.0 with VB Programs

Connecting to a webservice from a .NET desktop application is a piece of cake. But what about connecting to a webservice within unmanaged code - VB6/C++ programs? Actually SAOP Tool kit is the soultion. It is a Microsoft Tool used for calling webservices from unmanaged code.
You can download the kit from the Microsoft Official website:

http://www.microsoft.com/downloads/details.aspx?familyid=c943c0dd-ceec-4088-9753-86f052ec8450&displaylang=en

Here is a code snippt to call a webservice form inside VB6 program:



Dim soap As New SoapClient30
Dim serverURL as String
Dim hashCode as string

On Error GoTo ConnectionError

Public Sub WebServiceConnect

'Set Server URL
serverURL = "http://localhost/MyServiceName/Service.asmx?wsdl"

'Client is initialized
soap.MSSoapInit serverURL

'Calling the webservice
hashCode = soap.wsAuthenticate(txtUsername.Text, txtPassword.Text)

Exit Sub

ConnectionError:

MsgBox "Connection Error Encountered"

Exit Sub

The tool now is in its third version. Micorsoft declared that the SOAP tool kit 3.0 will not be supported after 31st March, 2008 because of the next generation of the Microsoft softwares will be .NET based. There will be no need to use SAOP tool kit as VS.NET gives already the ability to connect easily to webservices from the .NET desktop programs.


Wednesday, May 03, 2006

Spiders & Google Sitemaps

Internet Searching became one of the most popular services provided on the internet. Google, Yahoo, Altavista and AllTheWeb are all examples of search engines. Although, the simplicity of the searching, the inner technique used in searching is not easy as we think. Searh engines have to update their index regularlly and infiniatly.

Such engines use a special kind of softwares called “Spiders” or “Robots”. These softwares try to scan the whole internet to update their index with the new – or modified – locations, urls and contents. Depending on whatever algorithm or technqiue, “Spiders” will try extracts the keywords of the webpages content and restore the results on huge databases.

To comprehense its service, Google had provide an effective service for webmasters so that they can increase the traffic of their website. The idea is that each website will have an XML file called “sitemap.xml”, this file should be uploaded in the highest root of the FTP space of the web application. This file will include the informaton about the site pages and how they frequently changed. Here is a sample file for a small website:


<?xml version="1.0" encoding="UTF-8"?>

<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">

<url>
<loc>http://mnour.blogspot.com</loc>
<lastmod>2006-05-01</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>

<url>
<loc>http://mnour.blogspot.com/2006/04/sql-injection-part-1.html</loc>
<lastmod>2006-05-01</lastmod>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>

<url>
<loc>http://mnour.blogspot.com/2006/04/sql-injection-part-2.html</loc>
<lastmod>2006-05-01</lastmod>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>

<url>
<loc>http://mnour.blogspot.com/2006/04/ajax-new-giant.html</loc>
<lastmod>2006-05-01</lastmod>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>

</urlset>

While Google spiders scans the network, they will try to read this file – “sitemap.xml” – from a scanned domain. Then, it will check if any pages were modified after last time scanning this domain.

As you can notice, each “url” tag in the file contains how frequently the content of this URL will be updated. Actually, all of the webmasters will make there pages as updated hourly! thinking that this will increase there chances for being in the first results of Google. Actually, Google declared that this parameter is not taken as it’s. Maybe a URL declared as updated Montly, be indexed by Google Spiders more than another one declared as updated hourly!

This technqiue gives the benefits for the both sides: Webmasters and Google. Webmasters will be able to add their site to the serach results of most popular search engine on the net. On the other side, the technique will decrease the time needed for Google spiders to update their index.
The main drawback for this technique is for webmasters. They will have to update this file frequently after each update of their site content.