:::: MENU ::::

Thursday, February 26, 2009

Just released LinqExtender 2.0. Over previous release , it contains generally bugs fixes. Overall, I have focused on striping out complexity as much as possible to keep you focused on your business logic. You can see the full list of features in the documentation that comes with it.

Now, while creating the LinqToTwitter example, I have shown that creating custom providers with LinqExtender requires two steps, first you have to define a query object by implementing IQueryObject and then you have made a Query<T> successor and override few methods. In LinqExtender, object/ entity equivalent is Bucket. Starting from 2.0, there is a Fluent interface implementation of it that works as an internal DSL and gives you a single entry point for all query and update , inserts and delete, thus making things more declarative and one way.

In this post, I will show you how to generate SQL statement from LINQ query with nested where clause, using the fluent interface implementation. To start, let's consider the following query

var query = from book in bookContext
where ((book.Author == "Mehfuz" && book.ISBN == "2") || book.Id == books[2].Id) || 
(book.Author == "Paolo Pialorsi" && (book.ISBN == "100-11-777" || book.ISBN == "1"))
select book;

It's taken from the Entrypoint.cs test class that comes with LinqExtender project along with OpenLinqToSql sample ORM. Now, to do things in a very basic way. Let's first create a string builder and append the initial select.

StringBuilder builder = new StringBuilder("SELECT * FROM [" + Bucket.Instance.Entity.Name + "]");

To be precise, Bucket.Instance is the entry point for all query and object details. Moving to where statement , LinqExtender uses simplified expression tree that is exposed by Bucket.Instance.ExpressionTree. All we need to setup how the output will look like and the rest will be covered by the toolkit.

builder.Append("WHERE");
builder.Append("\r\n");
 
Bucket.Instance.ExpressionTree.Setup
.Begin(delegate
{
    builder.Append("(");
})
.Root(delegate(OperatorType operatorType)
{
    builder.Append(" " + operatorType + " ");
})
.EachLeaf(delegate(BucketItem item)
{
    string value = GetValue(item.Value);
    builder.Append(item.Name + RelationalOperators[item.RelationType] + value);
})
.End(delegate
{
    builder.Append(")");
})
.Execute();

Here, let assume that GetValue(..) will return a formatted SQL string and ReleationalOperators is a dictionary that has mappings for item.RealtionType ( GreaterThan -> ">" , LessThan => "<", etc). Basically, as the implementation shows, we are defining how the tree output will take place.All these code should be placed in Query<T>.Process(IModify<T> items) method and on execute it will just return the following SQL

Select * from book 
 WHERE
(((Author='Mehfuz' AND ISBN='2') OR Bk_Id='1734') 
OR (Author='Paolo Pialorsi' AND (ISBN='100-11-777' OR ISBN='1'))) 

Extender basically knows how to get though this nested where clause. From basic computer science, it builds linked objects based on a Syntax Tree, with each parenthesis adding diversion to the tree like shown below

So far, this is a very rudimentary example. With 2.0 it is also possible to build your own reusable format provider for building literals that saves repetitive code blocks for same kind of task (updating a database). This is actually just a schema builder that defines how the output will look like using the same Bucket.Instance calls. Out of the box, TSqlFormatProvider is provided.Depending under which Query<T> method it is used; it will generate insert, update, delete or select statement where all you have to call Bucket.Instance.Translate(...).

string sql = Bucket.Instance.Translate(new TSqlFormatProvider());

This enables you to build not only your own LINQ to Anything format providers but also share it with the community to reuse what is already out there. More information on how to get started can be found at the project documentation.

In a word, Bucket.Instance is all you need to go through and build your own LINQ provider. Optionally, you can override the following methods (under Query<T>) to give your provider various OTS (Object tracking service) support .

1. AddItem () - called during SubmitChanges() call for new object.
2. RemoveItem () - called during SubmitChanges() call for Delete.
3. UpdateItem () – called during SubmitChanges() call for update.

I have updated Creating LinqToTwitter using LinqExtender post with the latest release. You can get a copy of the latest 2.0 release from www.codeplex.com/linqextender,  and of course as usual all your feedbacks are really helping to shape the toolkit.

More

Tuesday, February 24, 2009

OutOfMemory exceptions are often caused by address space fragmentation in Visual Studio process. For users experiencing excessive OutOfMemory exceptions we provide a tool which overrides Visual Studio's memory allocation policy to ensure more continuous address space for Common Language Runtime.

To use the tool download wrappers.zip file, unpack it and run devenv2005_wrap and devenv2008_wrap instead of devenv.exe for Visual Studio 2005 and 2008 correspondingly.

In some cases Visual Studio fails to start under wrappers. Check AppInit_DLLs. Rogue DLLs activated from there can interfere with wrappers. Example: wxvault.dll preinstalled with Dell laptops.

Sometimes wrappers won't help (because it's simply not enough memory), see http://stevenharman.net/blog/archive/2008/04/29/hacking-visual-studio-to-use-more-than-2gigabytes-of-memory.aspx for other solutions and explanations.

Thanks,

JetBrains

It's a common problem: you have a registration form, but you want to prevent user names or other values from being used more than once. You need a user-friendly way to prevent duplicate values being submitted. This is where the simplicity of jQuery excels.

User names and passwords are normally stored within a database. Commonly, developers wait until the form has been submitted before they perform any duplicate checking. This means that the user has to wait for a postback to complete before being informed that the user name they chose is already in use, and that they need to choose another one. Ajax tidies this up by allowing asynchronous querying of databases.

This example shows a very simple form:

 

<form id="form1" runat="server"> 

<div id="register"> 

  <fieldset>

    <legend>Register</legend>

    <div class="row">

      <span class="label">User Name:</span>

      <asp:TextBox ID="UserName" runat="server"></asp:TextBox><span id="duplicate"></span>

    </div>

    <div class="row">

      <span class="label">Password:</span>

      <asp:TextBox ID="Password" runat="server"></asp:TextBox>

    </div>

    <div class="row">

      <span class="label">&nbsp;</span>

      <asp:Button ID="btnRegister" runat="server" Text="Register" />

    </div>

  </fieldset>

</div> 

</form> 

 

A web service will be used to house the method that checks the database for possible duplicates:

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Services;

using System.Web.Script.Services;

using System.Data.SqlClient;

 

/// <summary>

/// Summary description for UserService

/// </summary>

[WebService(Namespace = "http://tempuri.org/")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

 

// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.

[ScriptService]

public class UserService : WebService {

 

    public UserService () {

    }

 

    [WebMethod]

    public int CheckUser(string username)

    {

      string connect = @"Server=SERVER;Database=Database;Trusted_Connection=True;";

      string query = "SELECT COUNT(*) FROM Users WHERE UserName = @UserName";

      using(SqlConnection conn = new SqlConnection(connect))

      {

        using(SqlCommand cmd = new SqlCommand(query, conn))

        {

          cmd.Parameters.AddWithValue("UserName", username);

          conn.Open();

          return (int)cmd.ExecuteScalar();

        }

      }

    }

}

 

There's nothing clever about this code. One (Web) method - CheckUser() - accepts a string as an argument and then returns the number of rows in the database where that name is found. The [ScriptService] attribute is uncommented, so that the service is availabe to AJAX calls (not just ASP.NET AJAX, incidentally).

Now we'll look at the Javascript that uses jQuery to effect the call:

 

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script> 

<script type="text/javascript"> 

  $(function() {

    $("#UserName").change(checkUser);

  });

 

  function checkUser() {

    $.ajax({

      type: "POST",

      url: "UserService.asmx/CheckUser",

      data: "{username: '" + $('#UserName').val() + "'}",

      contentType: "application/json; charset=utf-8",

      dataType: "json",

      success: function(response) {

        var retval = (typeof response.d) == 'string' ? eval('(' + response.d + ')') : response.d;

        $("#duplicate").empty();

        if (response.d != "0") {

          $("#duplicate").html('That user name has alrady been taken');

        }

      }

    });

  }

 

</script> 

 

The first <script> tag brings in the jQuery library from Google's public code repository. Then an event handler is added to the element with the ID of UserName, which is the TextBox waiting for the user to put their chosen User Name in. The handler is wired up to the TextBox's onchange event, and calls the checkUser() function. Then the checkUser() function is defined in code.

When the user has added some text to the TextBox and then moves their cursor away, the chenage event is fired, and an AJAX call is made to the web service. If the response is not 0, then the web method has foound at least one row that matches the user name that the user is attempting to submit. The <span> with the ID is "duplicate" is emptied of any messages resulting from previous attempts, and the message displayed to the user.

More

I got given jQuery In Action for Christmas. By nature, I'm kind of a late adopter, and I'm already regretting this fact. jQuery has been around for some time, and I wished I had looked at it sooner. It's a fantastic library that really simplifies Javascript development, and is already attracting a goodly number of plug-ins. JCrop is one such, and while it hasn't yet reached version 1.0, it is remarkably easy to use as a web based image cropper. Here's how to put jQuery, JCrop and a FileUpload control together to allow users to upload images and crop them.

If you haven't already done so, you will need to download the jQuery library. The current version, and therefore the one that is used in this sample is 1.2.6. Then you need to get hold of the files for JCrop. The download also includes a number of samples which show the features offered by JCrop, such as specifying a fixed aspect or minimum and maximum sizes etc, but this sample uses the default out-of-the-box settings. Finally you could probably do with making sure that your VS 2008 or VWD 2008 has SP1 applied together with this hotfix which enables Intellisense on javascript files, including jQuery and JCrop. You need to get hold of the vsdoc.js file too.

This example consists of a single page. It caters for three actions: first, the user is presented with an Upload control to locate and upload their image; second, they will be presented with their uploaded image ready for cropping; and finally, they are presented with the cropped result. To accommodate this, three Panel controls are added to the page. The first, pnlUpload contains the FileUpload control and a button linked to an event handler for its click event. The second, pnlCrop contains an Image control and a button - again, linked to an event handler for its Click event. It also contains 4 HiddenField controls. They will be explained shortly. The Panel's Visibility is set to false. The final Panel, pnlCropped contains an Image control, and its Visibility is also set to false.

 

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="UploadAndCrop.aspx.cs" Inherits="UploadAndCrop" %>

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

  <title></title>

 

</head>

<body>

  <form id="form1" runat="server">

  <div>

    <asp:Panel ID="pnlUpload" runat="server">

      <asp:FileUpload ID="Upload" runat="server" />

      <br />

      <asp:Button ID="btnUpload" runat="server" OnClick="btnUpload_Click" Text="Upload" />

      <asp:Label ID="lblError" runat="server" Visible="false" />

    </asp:Panel>

    <asp:Panel ID="pnlCrop" runat="server" Visible="false">

      <asp:Image ID="imgCrop" runat="server" />

      <br />

      <asp:HiddenField ID="X" runat="server" />

      <asp:HiddenField ID="Y" runat="server" />

      <asp:HiddenField ID="W" runat="server" />

      <asp:HiddenField ID="H" runat="server" />

      <asp:Button ID="btnCrop" runat="server" Text="Crop" OnClick="btnCrop_Click" />

    </asp:Panel>

    <asp:Panel ID="pnlCropped" runat="server" Visible="false">

      <asp:Image ID="imgCropped" runat="server" />

    </asp:Panel>

  </div>

  </form>
</body>
</html>

 

Some Javascript is required. If you were starting this kind of application from scratch, it would need an awful lot of javascript. However, jQuery's real power is illustrated by just how little javascript this page actually needs. To make use of both jQuery and JCrop, they need to be linked to in the head section of the page, along with the css file that comes as part of the JCrop download. The link to jQuery makes use of the copy available from the Google Ajax API Library for better caching and faster downloading:

 

<link href="css/jquery.Jcrop.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript" src="script/jquery.Jcrop.pack.js"></script>

 

All that's now needed to activate JCrop is a handful of lines of Javascript, which go within <script> that's in the head of the document below the previous lines:

 

<script type="text/javascript">

  jQuery(document).ready(function() {

    jQuery('#imgCrop').Jcrop({

      onSelect: storeCoords

    });

  });

 

  function storeCoords(c) {

    jQuery('#X').val(c.x);

    jQuery('#Y').val(c.y);

    jQuery('#W').val(c.w);

    jQuery('#H').val(c.h);

  };

 

</script>

 

It really is that simple. Jcrop has been applied to the image that has the id of imgCrop (the one in pnlCrop), and an event handler has been added to the select event of the cropper. This will happen when the user has completed selecting the area of the image they want to keep. The handler makes use of the storeCoords function, which sets the values of the HiddenFields, passing them the x and y coordinates of the top left of the selection relative to the image, and the width and height of the selection. That's all ASP.NET needs to know in order to process the image on the server. Now on to the server-side code.

There are 4 namespaces that need to be referenced in additional to the default ones that a new Web Form brings in:

 

using System.IO;

using SD = System.Drawing;

using System.Drawing.Imaging;

using System.Drawing.Drawing2D;

 

Since we will be working with instances of System.Drawing.Image as well as System.Web.UI.WebControls, which also has an Image class, I have aliased System.Drawing.Image, which will permit me to use a shorthand to reference the System.Drawing.Image classes. The first four lines of the code-behind simply set a variable to point to the file system path of the directory in which uploaded images will be stored, and show an empty Page_Load method:

 

String path = HttpContext.Current.Request.PhysicalApplicationPath + "images\\";

 

protected void Page_Load(object sender, EventArgs e)

{}

 

The next section covers the event handler for the Upload button click:

 

 

protected void btnUpload_Click(object sender, EventArgs e)

{

  Boolean FileOK = false;

  Boolean FileSaved = false;

 

  if (Upload.HasFile)

  {

    Session["WorkingImage"] = Upload.FileName;

    String FileExtension = Path.GetExtension(Session["WorkingImage"].ToString()).ToLower();

    String[] allowedExtensions = { ".png", ".jpeg", ".jpg", ".gif" };

    for (int i = 0; i < allowedExtensions.Length; i++)

    {

      if (FileExtension == allowedExtensions[i])

      {

        FileOK = true;

      }

    }

  }

 

  if (FileOK)

  {

    try

    {

      Upload.PostedFile.SaveAs(path + Session["WorkingImage"]);

      FileSaved = true;

    }

    catch (Exception ex)

    {

      lblError.Text = "File could not be uploaded." + ex.Message.ToString();

      lblError.Visible = true;

      FileSaved = false;

    }

  }

  else

  {

    lblError.Text = "Cannot accept files of this type.";

    lblError.Visible = true;

  }

 

  if (FileSaved)

  {

    pnlUpload.Visible = false;

    pnlCrop.Visible = true;

    imgCrop.ImageUrl = "images/" + Session["WorkingImage"].ToString();

  }

}

 

This code should be pretty familiar to anyone who has worked with the FileUpload control before. It simply checks to see if a file has been submitted, and ensures that it is of the right type. Then it saves the file to disk and the name of the file to a Session variable. Once the image has been saved, it is set as the ImageUrl of the Image control which has been targeted by JCrop and makes the containing Panel visible.

 

The next section covers the event handler for the Crop button:

 

protected void btnCrop_Click(object sender, EventArgs e)

{

  string ImageName = Session["WorkingImage"].ToString();

  int w = Convert.ToInt32(W.Value);

  int h = Convert.ToInt32(H.Value);

  int x = Convert.ToInt32(X.Value);

  int y = Convert.ToInt32(Y.Value);

 

  byte[] CropImage = Crop(path + ImageName, w, h, x, y);

  using (MemoryStream ms = new MemoryStream(CropImage, 0, CropImage.Length))

  {

    ms.Write(CropImage, 0, CropImage.Length);

    using(SD.Image CroppedImage = SD.Image.FromStream(ms, true))

    {

      string SaveTo = path + "crop" + ImageName;

      CroppedImage.Save(SaveTo, CroppedImage.RawFormat);

      pnlCrop.Visible = false;

      pnlCropped.Visible = true;

      imgCropped.ImageUrl = "images/crop" + ImageName;

    }

  }

}

 

This section references the image name from the Session variable, and then declares a number of integers that get their values from the HiddenFields that JCrop wrote to when the user selected the area they wanted to keep.

 

It then calls a method called Crop() to perform the actual cropping of the image (more of which soon). Crop() returns a byte array, which is written to a MemoryStream so that it can be used and converted back to an Image. This is then prefixed with the word "crop" in its name before being saved to disk and displayed to the user.

 

The Crop() method is below:

 

static byte[] Crop(string Img, int Width, int Height, int X, int Y)

{

  try

  {

    using (SD.Image OriginalImage = SD.Image.FromFile(Img))

    {

      using (SD.Bitmap bmp = new SD.Bitmap(Width, Height, OriginalImage.PixelFormat))

      {

        bmp.SetResolution(OriginalImage.HorizontalResolution, OriginalImage.VerticalResolution);

        using (SD.Graphics Graphic = SD.Graphics.FromImage(bmp))

        {

          Graphic.SmoothingMode = SmoothingMode.AntiAlias;

          Graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;

          Graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;

          Graphic.DrawImage(OriginalImage, new SD.Rectangle(0, 0, Width, Height), X, Y, Width, Height, SD.GraphicsUnit.Pixel);

          MemoryStream ms = new MemoryStream();

          bmp.Save(ms, OriginalImage.RawFormat);

          return ms.GetBuffer();

        }

      }

    }

  }

  catch (Exception Ex)

  {

    throw (Ex);

  }

}

 

This might at first glance look a little daunting to beginners, but most of the code just sets properties that affect the quality and appearance of the resulting image. What it does is to simply use the original image as a base from which a new image is drawn, and then save it to a MemoryStream object, which is returned as a byte array to be consumed by the calling code above. You should take note of the using blocks that are employed in this method. They ensure that Image, Bitmap and Graphics objects are all disposed of when the method is done. There's nothing worse than finding that your busy web app has slowed to a crawl through unreleased resources.

Oh, and thanks go to my cat, Alfie, for kindly agreeing to model for this exercise.

More

Introduction

Whenever a browser requests a web page, image, CSS file, or other resource the web server returns a response that includes a status code. If the requested resource was found and the requestor is authorized to view it, the web server responds with a 200 status code (and the requested content). If the resource could not be found the web server replies with a 404 status. The HyperText Transfer Protocol (HTTP) standard defines these three-digit status codes and the status codes are grouped by their most significant digit. Status codes in the form 2xx indicate success, whereas status codes in the form 4xx report a client error.

The 3xx range of status codes specifies redirection codes. These are codes that tell the browser that it needs to undertake further action to complete the request. The most common redirection code is 302 Found, which informs the browser that the requested resource is temporarily available at an alternative location. When a web server returns a 302 Found status it must also return a Location HTTP header that indicates where the requested resource has been temporarily moved to. Upon receiving this status code, the browser automatically makes a request for the resource at the specified Location.

This redirection pattern is commonly used in websites that have certain pages that are restricted to a specific set of users. When an unauthorized visitor reaches such a page they are automatically redirected to the log in page. This workflow unfolds because the web server returns a 302 Found status with a Location header pointing to the log in page URL whenever an unauthorized visitor requests a protected page. Figure 1 illustrates this behavior.

Specifying Status Codes Programmatically

The Response object includes a number of properties for specifying the status and Location.

  • Response.Status - a string property that specifies the complete status, which includes a code and description, such as "302 Found".
  • Response.StatusCode - an integer property that specifies just the status code and not the description, such as 302.
  • Response.StatusDescription - a string property that specifies just the status description and not the code, such as "Found".
  • Response.RedirectLocation - a string property that specifies the value of the Location HTTP header.

The following code shows how to use these properties to send a 302 Found status to the browser and have it redirect to Login.aspx.

  1. // Set the status code and description  
  2. Response.StatusCode = 302;  
  3. Response.StatusDescription = "Found";  
  4. // Specify the Location via the RedirectLocation property  
  5. Response.RedirectLocation = "Login.aspx";  
  6. // End processing of the page  
  7. Response.End()  

The Location HTTP header can alternatively be set using the Response.AppendHeader(name, value) method. That is, you could replace the Response.RedirectLocation property assignment in the code above with the following line of code:

  1. // Specify the Location via the AppendHeader method  
  2. Response.AppendHeader("Location""Login.aspx");  

Fortunately there is a much more succinct version of the above code. The Response.Redirect(url) method executes virtually the same code as above, ending the response and returning a 302 Found status to the browser along with a Location HTTP header with the value specified by the url parameter.

Comparing "301 Moved Permanently" and "302 Found"

Web pages are the interface into your online application and therefore once created should always "work." A website with URLs that once functioned but now return 404 status codes is akin to a buggy desktop application. There are times when you may need to do a site redesign that will shuffle your pages into a new directory structure, or you may have pages that need to be renamed or replaced. In such a circumstance it is better to keep the old URL active and redirect users to the new URL, but rather than redirecting using a 302 Found status you should use the 301 Moved Permanently status.

The 302 Found status emitted by Response.Redirect tells the browser that the requested resource has been temporarily moved. On the other hand, the 301 Moved Permanently status code indicates that the resource has been permanently relocated. Regardless of whether a 301 or 302 status code is returned, the end user's experience is the same. However, search engine crawlers indexing your site treat the two status codes differently. When a 302 Found status code is encountered, a search engine crawler keeps the original page in its index; if it encounters a 301 Moved Permanently, it updates its index with the new URL. Using the 301 Moved Permanently status keeps search engine indexes less cluttered with defunct URLs.

The following code shows how to issue a 301 Moved Permanently redirect:

  1. // Set the status code and description  
  2. Response.StatusCode = 301;  
  3. Response.StatusDescription = "Moved Permanently";  
  4. // Specify the Location  
  5. Response.RedirectLocation = "NewPageUrl.aspx";  
  6. // End processing of the page  
  7. Response.End()  

Unfortunately there is no method in the Response class that provides a succinct 301 Moved Permanently status code, but you could place the above code in an extension method in order to create your own Response.PermanentlyRedirect method.

Further Reading

More

Visual Studio can be a tremendous resource hog, especially if you have a large solution and you're using a productivity add-in or two.

On my current project we're running VS 2008, we've got just under 20 projects in the solution, and several of us are using the ReSharper 4.0 EAP nightly builds to enhance our dev-fu. And you know what... we're restarting VS at least a half dozen times a day to work around a nasty exception we regularly encounter while trying to compile:

Not enough storage is available to complete this operation.

Not enough storage...?

Yep - storage. But you should read storage to mean memory... RAM that is.

After running for a while the Visual Studio process (found under devenv.exe in process explorer) maxes out its available memory and the above exception is thrown. The only way to reclaim the memory and successfully compile the solution is to restart the process. Bummer!

Maybe we should just upgrade our hardware, right?

I mean, with cost of processor cycles and RAM falling as fast as gas prices are rising, why not just spend a few bucks and make sure we're all running multi-core boxes with 4+ Gigabytes of memory and storage space to burn. Well guess what... we are.

All of the developers are running nice beefy machines with lots of RAM, super-fast processors, and we even have nice 21" wide screen DVI monitors. So this ain't no hardware problem.

Its a software problem.

I will admit, we are running a mix of 32-bit operating systems - mostly Vista with a handful of XP machines mixed in for the devs that roll that way. And Jeff Atwood has covered the missing RAM problem before, but even switching to a 64-bit OS wouldn't solve our problem. At least not entirely.

The problem is with Visual Studio. Being a 32-bit application its limited to just 2GB of virtual memory, even if its running in a 64-bit OS. At least, its limited to 2GB by default... but we can hack around change that.

The hack... err, solution.

The first thing to do is tell the OS to increase the amount user-mode memory from 2GB to 3GB. If you're running a 64-bit you can skip this step.

  • for Windows XP: Backup the boot.ini file and then put the /3GB switch in your boot.ini. (more information on the /3GB option)
  • for Vista: run the following from the Visual Studio command prompt (Brad Rutkowski has the full scoop):
   1:  BCDEDIT /Set IncreaseUserVa 3072

Then we have make Visual Studio large address aware.

  1. Be sure to backup devenv.exe
  2. Using the Visual Studio command prompt, navigate to C:\Program Files\Microsoft Visual Studio 9\Common7\IDE\
  3. execute the following command:
   1:  editbin /LARGEADDRESSAWARE devenv.exe

Finally we'll use the old Microsoft-fix-all - reboot the machine. Bounce that box!

Look at all that memory!

At this point Visual Studio should be allowed to consume up to 3GB of memory before throwing that ugly out of memory exception.

Just to show you I'm not lying, I grabbed a screen shot of my process explorer with devenv.exe process chewing up more than 2.5GB of memory. Sweet!

Note: even with our large solution and running the early, and memory-hungry, ReSharper bits, Visual Studio typically stays around or just above the 2GB mark. However it can spike up to 2.5+ GB while compiling, as show in this screen shot.

More

A brief introduction to jQuery and ways in which we can integrate it into ASP .NET

Introduction

In September 2008 Scott Guthrie, the head of the ASP.NET team, announced in a blog post that Visual Studiohttp://images.intellitxt.com/ast/adTypes/mag-glass_10x10.gif would be shipping with the jQuery library. He writes:

“jQuery is a lightweight open source JavaScript library (only 15kb in size) that in a relatively short span of time has become one of the most popular libraries on the web. A big part of the appeal of jQuery is that it allows you to elegantly (and efficiently) find and manipulate HTML elements with minimum lines of code … There is a huge ecosystem and community built up around JQuery. The jQuery library also works well on the same page with ASP.NET AJAX and the ASP.NET AJAX Control Toolkit.”

With that, JQuery is officially embraced by ASP.NET.

A brief introduction of JQuery

jQuery is the star among the growing list of JavaScript libraries. A few of its characteristics are light-weight, cross-browser compatibility and simplicity. A common task that sometimes takes 10 lines of code with traditional JavaScript can be accomplished with jQuery in just one line of code. For example, if you want to dress up a table with an ID mytable with alternative color for every other row, you can simple do this in jQuery. 

Listing 1: jQuery code for making a zebra-style table

  1. <script>  
  2. $(function() {  
  3.     $("table#mytable tr:nth-child(even)").addClass("even");  
  4. });  
  5. </script>  

The magic dollar sign ($) and a chain of operations

In jQuery, the most powerful character / symbol is the dollar sign. A $() function normally returns a set of objects followed by a chain of operations. An example

  1. $("div.test").add("p.quote").html("a little test").fadeOut();  

Think of it as a long sentence with punctuations. Indeed it is a chain of instructions to tell the browser to do the following:

  1. Get a div with class name is test;
  2. Insert a paragraph with class name is quote;
  3. Add a little text to the paragraph;
  4. Operate on the DIV using a predefined method called fadeout.

So there it is, the first two basics: $() and chainable.

More

Friday, February 20, 2009

Abstract:
In this article we will see how we can change the email addresses written on a website to images on the fly. The general opinion about this task is to revamp the form where we are asking user to input the email address and then generate an image which will display later instead of email address.

 

Introduction:

In this article we will see how we can change the email addresses written on a website to images on the fly. The general opinion about this task is to revamp the form where we are asking user to input the email address and then generate an image which will display later instead of email address.

Create Email Filter:

Fortunately, Asp.net provides us with a feature called Response filter which allow us to alter the response generated by web server. By using Response filter we don’t need to alter the foundation of our application. We just need to plug that response filter in and our work is done.
So to create a filter we need to create a class called “EmailFilter.CS” which will inherit from Stream.


public class EmailFilter : Stream
{
private string _path;
private Stream _response;
public EmailFilter(Stream response, string path)
{
_response = response;
_path = path;
}

public override int Read(byte[] buffer, int offset, int count)
{
return _response.Read(buffer, offset, count);
}


public override void Write(byte[] buffer, int offset, int count)
{
}


}



This can easily be read that we have two local variables which are getting set by our parameterized constructor and we have overrides two functions out of which the write function is really important. We are going to play with that function throughout the tutorial.
Note:
It is also important to mention here that we have removed some code for clarity but to use the stream class you need to override the some other functions and properties which you can find in code attached.

Now the next step is to write the code in Write method.


public override void Write(byte[] buffer, int offset, int count)
{
string html = System.Text.Encoding.UTF8.GetString(buffer);
string emailPattern = @"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*";

Regex objRegex = new Regex(emailPattern);
MatchCollection objCol = objRegex.Matches(html);

foreach (Match m in objCol)
{
string email = m.Value;
Font objFont = new Font("Arial", 12, FontStyle.Bold);

int width = (int) getTextWidth(email, objFont);

Bitmap objBitmap = new Bitmap(width, 20);
Graphics objGraphics = Graphics.FromImage(objBitmap);

objGraphics.FillRectangle(Brushes.White, new Rectangle(0, 0, width, 20)); //getting white bg
objGraphics.DrawString(email, objFont, Brushes.Black, new Point(0, 0));

string relpath = "images/" + Guid.NewGuid().ToString() + ".jpg";
string saveFileName = _path + relpath;

objBitmap.Save(saveFileName,System.Drawing.Imaging.ImageFormat.Jpeg);

objGraphics.Dispose();
objBitmap.Dispose();

string imgMarkup = "<img src='" + relpath + "'/>";
html = html.Replace(email, imgMarkup);
}

buffer = System.Text.Encoding.UTF8.GetBytes(html);
_response.Write(buffer, offset, count);
}

protected float getTextWidth(string strText, Font f)
{
float width = 0;
Bitmap objBitmap = new Bitmap(1, 1);
Graphics objGraphics = Graphics.FromImage(objBitmap);

try
{
width = objGraphics.MeasureString(strText, f).Width;
return width;
}
catch (Exception)
{
return 0;
}
finally
{
objBitmap.Dispose();
objGraphics.Dispose();
}
}


The first four lines are easy to understand we are just storing the HTML generated by web server to a variable and we have created a regular expression object to check for the email addresses in out html.

In foreach loop we are generating the images of every email address using System.Drawing and saving the images in a temp location and finally disposing the objects.Now the main stuff is here, we are creating a string variable which will hold html image tag with source and then replace the email address with the image tag.

Whereas, getTextWidth is a simple function which measure the width of our text and return it so that we can have dynamic width for different size of texts.

Let's use this response filter in our aspx page. To do that we need to write the following code in Page_Load


protected void Page_Load(object sender, EventArgs e)
{
Response.Filter = new EmailFilter(Response.Filter, Server.MapPath("/").ToString());
}


It is worth to mention here the parameter. Our Response filter is just a class file and we donot have the Server path in classes but we still want to store the images using relative path so to do that we just pass the root path as parameter which we will use in Response Filter to save the image. To understand the situation correctly we need to write the following code in the form tag of our aspx.

<div>
aghausman@gmail.com </br>
aghausman@ciberstrategies.com</br>
me@aghausman.net</br>
</div>

That is nothing but three simple email addresses. Now when you run the page you will see the following output.

Notice that we have write three email addresses but it is showing only two. To see what went wrotn we have let's have a look at the source given below:

Notice that there is no html after the br of second image. It means there is some thing wrong with the response.write. Now to understand what happen we need to go back and read the last line of our Write function which is as follows


_response.Write(buffer, offset, count);


here we are simply passing what we have get from Write parameter but the matter of fact is that it is now changed. Remember, we have change our email address with the image tag so to compare let's see our first email address and frst generated image.

Email Address : aghausman@gmail.com
Image Text : <img src='images/da04a458-7ff4-41cb-b982-5724c1eadb84.jpg'/>

Notice that image tag is using more then double characters. so we need to change the last parameter count according to the new condition. for that let's see the Write method code again.


public override void Write(byte[] buffer, int offset, int count)
{
string html = System.Text.Encoding.UTF8.GetString(buffer);
string emailPattern = @"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*";

Regex objRegex = new Regex(emailPattern);
MatchCollection objCol = objRegex.Matches(html);

int totCount = 0;

foreach (Match m in objCol)
{
string email = m.Value;
Font objFont = new Font("Arial", 12, FontStyle.Bold);

int width = (int) getTextWidth(email, objFont);

Bitmap objBitmap = new Bitmap(width, 20);
Graphics objGraphics = Graphics.FromImage(objBitmap);

objGraphics.FillRectangle(Brushes.White, new Rectangle(0, 0, width, 20)); //getting white bg
objGraphics.DrawString(email, objFont, Brushes.Black, new Point(0, 0));

string relpath = "images/" + Guid.NewGuid().ToString() + ".jpg";
string saveFileName = _path + relpath;

objBitmap.Save(saveFileName,System.Drawing.Imaging.ImageFormat.Jpeg);

objGraphics.Dispose();
objBitmap.Dispose();

string imgMarkup = "<img src='" + relpath + "'/>";
totCount += imgMarkup.Length;
html = html.Replace(email, imgMarkup);
}

buffer = System.Text.Encoding.UTF8.GetBytes(html);
_response.Write(buffer, offset, count + totCount);

}


We have only create an int variable before loop and on every loop we are adding the length of image tag to the variable and finally on response.write we are adding the count with the length of image tags we have generated. that's it.

Now if we run the page we will see the following output:

Conclusion:

That's all, we have now replace the emal addresses written on our website to images. Just in case you don't want to write the page_load stuff on every page as it is very difficult then you can also use httpModule. For the see the following code


public class EmailToImages : IHttpModule
{
public void Dispose()
{

}
public void Init(HttpApplication application)
{
HttpContext context = HttpContext.Current;

context.Response.Filter = new EmailFilter(context.Response.Filter, context.Server.MapPath("/"));

}
}

<httpModules>
<add name="EmailToImage" type="LearnWebApp.EmailToImages, LearnWebApp"/>
</httpModules>


Now to remove the temperory images you might need a code which delete the images in timely fashion. That's all.

[Download Sample]

 

More

Abstract:
We all have experienced the wrath of filling out lengthy online forms. we get frustrated when we fill out the complete form and as soon as we submit it returns with messages like “UserName has already been taken”. So, now we have to fill the username as well as the password since password fields are not maintained during postbacks. In this article we will learn how to use Ajax request to lookup the existing username.

Introduction:

We all have experienced the wrath of filling out lengthy online forms. we get frustrated when we fill out the complete form and as soon as we submit it returns with messages like “UserName has already been taken”. So, now we have to fill the username as well as the password since password fields are not maintained during postbacks. In this article we will learn how to use Ajax request to lookup the existing username.

Implementation:

This problem can be solved in multiple ways. One solution is to cut the form in small pieces so that it works like a wizard control. This will only allow the user to fill small portion of information at a given time. This will have a faster response than loading the complete detailed form.

Another way is to ajaxify the username search. This means we will search for the existing username as soon as the user starts typing the username. Let’s check out how this approach is implemented.

First let’s make a few controls that we will need in our application: 

Enter UserName: <input type="text" id="txtUserName" />   
    Password: <input type="password"  />
   
    <div id="display" style="width:100px; font-family:Arial; padding:5px 5px 5px 5px; font-weight:bold; font-size:14px"></div>
   


The div element is used to display the message whether the username already exists or not.

Now, let’s check out the JQuery code:

<script language="javascript" type="text/javascript">

var userName = '';
var keyChar = '';

$(document).ready(function()
{
    $("#txtUserName").keydown(function(e)
    {
        //userName = $(this).val();       
               
        keyChar = String.fromCharCode(e.which);             
       
        if(e.which == 8)
        {
            userName = userName.substring(0,userName.length - 1);
        }       
        else
        {
            userName += keyChar; 
        }
       
       
        if(userName.length <= 6)
        {
            $("#display").text("username must be atleast 7 characters");
            $("#display").css("background-color","red");
        }
       
        else
        {
            $.ajax(
            {
                type:"POST",
               
url:"AjaxService.asmx/CheckUserNameAvailability",
                data:"{\"userName\":\"" + userName + "\"}",
                dataType:"json",
                contentType:"application/json",
                success: function(response)
                {
                    if(response.d == true)
                    {
                        $("#display").text("username is available");
                        $("#display").css("background-color","lightgreen");
                    }
                    else
                    {
                      $("#display").text("username is already taken");
                      $("#display").css("background-color","red");
                    }
                }
            });
        }
       
       
    });
});


</script>


As, you can see we are restricting the user to make an Ajax call unless the username is of the required length. In this case the required length is greater than 6 characters. Let’s give this implementation a try in Firefox.


The above screenshot shows that for each keypress that happens after the 6 characters an Ajax call is made. This can end in many useless Ajax calls. A good web application is the one that makes fewer requests.

Let’s move our Ajax calls in the blur event of the TextBox which will be triggered whenever the user loses the focus from the TextBox control.

<script language="javascript" type="text/javascript">

var userName = '';
var keyChar = '';

$(document).ready(function()
{
    $("#txtUserName").blur(function(e)
    {
        userName = $(this).val();       
       
        if(userName.length <= 6)
        {
            $("#display").text("username must be atleast 7 characters");
            $("#display").css("background-color","red");
        }
       
        else
        {
            $.ajax(
            {
                type:"POST",
               
url:"AjaxService.asmx/CheckUserNameAvailability",
                data:"{\"userName\":\"" + userName + "\"}",
                dataType:"json",
                contentType:"application/json",
                success: function(response)
                {
                    if(response.d == true)
                    {
                        $("#display").text("username is available");
                        $("#display").css("background-color","lightgreen");
                    }
                    else
                    {
                      $("#display").text("username is already taken");
                      $("#display").css("background-color","red");
                    }
                }
            });
        }
       
       
    });
});


</script>

Now, the call will only be made when the user leaves the focus from the TextBox. Check out the animation below:

The animation shows that the Ajax calls are only made when the user losses the focus from the TextBox control. This will result in much fewer calls and will increase the performance of the application.

Also, if you are interested check out the screencast on the same topic:

Checking UserName Availability Instantly Using JQuery and Ajax

[Download Sample]

More