Wednesday, March 27, 2013

Customize default ASP.NET validator javascript functions

These days we want some fancy css to be applied client side when the user entered some invalid data on a form. The good thing about ASP.NET validators is that they also validate server side. The bad thing is that you can only specify some text to be displayed when the entered data is invalid.

Well, we are about to change that! Let’s start with changing the validator evaluation function.

$(function () {
    for (var i = 0; i < window.Page_Validators.length; i++) {
        // Create a new property and assign the original evaluation function to it
        window.Page_Validators[i].baseEvaluationFunction = window.Page_Validators[i].evaluationfunction;

        // Set our own validation function
        window.Page_Validators[i].evaluationfunction = evaluateField;
    }
});

With the help of jQuery, this will run when the DOM is ready. It loops over the ASP.NET validators on the page and creates a new property ‘baseEvaluationFunction’ for each of them on the fly. That property is assigned with the current (default) evaluation function. Secondly, we assign our custom evaluation function to the ‘evaluationfunction’ property.

function evaluateField (validator) {
    // Run the original validation function
    var isvalid = validator.baseEvaluationFunction(validator);

    // Handle the result
    if (isvalid) {
        clearError(validator);
    } else {
        setError(validator);
    }

    // Return result
    return isvalid;
}

In the custom evaluation function the base (default) evaluation function is executed and based on the result things on the form can be changed. In the functions setError and clearError the correct css is applied. I used the errormessage property to also explain the user what is wrong. Finally the function returns if the evaluation was valid or not.

One more thing: set the Display property of the ASP.NET validators to None, otherwise ASP.NET will still display the error message.

<asp:RequiredFieldValidator ID="FirstNameValidator" ControlToValidate="FirstNameTextBox" Display="None" ErrorMessage="Please enter your first name." runat="server"></asp:RequiredFieldValidator>

Pretty easy, eh?

Wednesday, September 19, 2012

Handle regular html controls in ASP.NET Webforms

By "handle regular html controls in .NET" I mean handling values of non-ASP.NET controls, nor html server controls after a postback. Basically an input control with no runat="server" attribute. Why on earth would one do such a thing? Well, recently I was working on a project where input fields could be added kinda indefinitely in a certain form. The fields were added to the form by using javascript and templates. We preferred that over a postback per added field.

So, in our html template we had something like this:
<input id="MyRegularTextBox_" name="MyRegularTextBox_" type="text" value="" />

This was added to a container div and a counter was added to the id and name of the input field. In the end, a form could look like this when it was posted back to the server:
<input id="MyRegularTextBox_1" name="MyRegularTextBox_1" type="text" value="" />
<input id="MyRegularTextBox_2" name="MyRegularTextBox_2" type="text" value="" />
<input id="MyRegularTextBox_3" name="MyRegularTextBox_3" type="text" value="" />

As ASP.NET doesn't know about these fields, we need another way to access the values of those added field. In fact, if you are from the old asp era or know some php or the like, it's pretty obvious. You just need to loop over all the keys in the Request.Form object. Combine that with a LINQ expression and we have a winner!
foreach (string key in Request.Form.AllKeys.Where(x => x.StartsWith("MyRegularTextBox_")))
{
    string myRegularTextBoxValue = Request.Form[key];

    // Do some great stuff!
}

The same logic can also be applied for file uploads. Instead of looping over the Request.Form keys, you need to loop the Request.Files collection. However, one important thing to do is setting the encoding type of the form.
The html looks like this:
<input type="file" id="attachment_1" name="attachment_1" />

Code behind like this:
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);

    // The form must handle file uploads (with regular html, non-asp.net, controls)
    Page.Form.Enctype = "multipart/form-data";
}

foreach (string key in Request.Files)
{
    HttpPostedFile postedFile = this.files[key];
}

Et voilĂ , you're set to go!

Friday, December 23, 2011

.NET Entity Framework: Detect if an Entity is new

When I'm using Entity Framework (EF) I'd like to have a Save() method that I can call without having to know what the state of the object is. I don't care if the object should be inserted or updated, that's up to the Save() method to find out.

In Entity Framework you can find out the state of an object by calling context.ObjectStateManager.GetObjectStateEntry(obj). To be able to use this method, your object needs to be attached to the context. If not, it will raise an InvalidOperationException. And that will be the case if you are saving an object that was just created (and not attached yet).

So what I do is using an extension method to determine what to do in the Save() method:

public static bool IsNew(this EntityObject entity)
{
  return entity.EntityKey == null || entity.EntityKey.IsTemporary;
}

If an object isn't attached yet, its EntityKey will be null. Otherwise, if it's attached but new, its EntityKey will be indicated as temporary.

The Save() mehtod calls the IsNew() method and acts accordingly.
private void Save(Product product)
{
  if (product.IsNew())
  {
    Insert(product);
  }
  else
  {
    Update(product);
  }
}

Thursday, September 15, 2011

Installing Windows 8 Developer Preview in VMware

Several versions of Windows 8 Developer Preview are public available on Microsoft’s Windows Developer Preview downloads. Just pick the one that fits for you. The downloaded file is an ISO file. You don’t need to burn it on disc.

If you don’t have a spare computer where you can install Windows 8 Developer Preview on, you can install it on your own machine using VMware. First you’ll need VMware Workstation 8 or VMware Player 4. The latter one is free, but at this moment you can only get it by downloading VMware Workstation 8. Don’t worry if you don’t have a license, you don’t need one because we will only use the free VMware Player 4. If you want full functionality you can download a trial version. For both downloads you’ll need to create an account. Go ahead and download and install VMware 8 if you have not already.

In this little tutorial I will use VMware Player, but the steps are nearly the same for VMware Workstation. Start VMware Player and click “Create a New Virtual Machine”. In the window that pops up, make sure you choose “I will install the operating system later.”

Installing-Win8-VMware-1

If you select one of the other options, you’ll get in trouble when Windows 8 Developer Preview is installing. Because in one of the next screens of the VMware wizard you’ll be asked to enter the license key for Windows 8 Developer Preview which you don’t have. You can leave it empty, but when Windows 8 Developer Preview is installing you’ll get the following error: “Windows cannot read the <ProductKey> setting from the unattend answer file”.

Installing-Win8-VMware-2

So, let’s proceed with the last option and click “Next >”. Depending on which version you have downloaded, select “Windows 7” or “Windows 7 x64” as operating system. I have downloaded the 64-bit version, so I chose “Windows 7 x64”.

Installing-Win8-VMware-3

Enter a Virtual machine name in the next step, for instance “Windows 8 Developer Preview”, and set the location of your virtual machine. I did not change anything in the next steps of the wizards, but you can choose the maximum disk size (default 60GB), whether to split the virtual disk or not. If you want to adjust the default allocated memory (1GB) you’ll need to click on “Customize Hardware…” in the last step to change it. This is my summary screen:

Installing-Win8-VMware-4

Click “Finish” and select the created virtual machine in VMware Player. Open the Virtual Machine Settings by clicking “Edit virtual machine settings” and select “CD/DVD IDE” in the device list. Make sure “Connect at power on” is checked and that you point it to the downloaded ISO file.

Installing-Win8-VMware-5

Click “OK” and power on the virtual machine. The Windows 8 Developer Preview installation wizard will start. At the end you can enjoy Windows 8 Developer Preview! One more tip: the metro style apps will only run if your screen resolution is at least 1024x768 (hardware or virtual machine).

UPDATE 1 (2 jan 2012): Some people have still trouble installing Windows 8 Developer Preview. You can fix that by removing the floppy of the virtual machine: Power off Windows 8 Virtual Machine, go to Virtual Machine Settings and remove the floppy drive. Thanks for the tip abkar, John and Claudiu!

UPDATE 2 (2 jan 2012): Modified links to download page for VMware Player.


Monday, December 13, 2010

Using macros in Visual Studio to rename files and classes

Recently I was working on a project that was initially started back in 2005. The solution is divided in several layers: entity layer, business layer, data layer and UI. For the first three layers CodeSmith is used to generate base classes based on the database schema. Extra functionality is added by implementing derived classes. Every database change or new common functionality can be added for all classes by changing a CodeSmith template. Very handy if there are more than 100 objects per layer.

Friday, August 6, 2010

log4net ColoredConsoleAppender: log levels and its problems

I was playing around with the ColoredConsoleAppender of log4net. It allows you to display a certain log level in another color. For instance messages with an error level can be displayed red in the console. But I encountered some problems with it.

Thursday, July 1, 2010

Making log4net run on .NET 4.0

I was playing around with .NET 4.0 and wanted to include logging. So I downloaded log4net (v1.2.10) and added the source project to my solution. The next thing to do was to configure log4net and I would be able to log to one or several 'appenders'. At least, that was what I thought! How to configure and use log4net is not the scope of this article, but you can find all what you need on the log4net site. A summary of the solution can be found at the bottom of this article.