Tuesday 29 May 2012

Some Notes about Finaliser and Dispose() Method in .NET


- A finaliser cannot be called explicitly therefore we cannot determine when exactly it will run. The finalisation process (using a queueing method called f-reachable queue) manages when objects' finalisers will be called. This finalisation process happens right before garbage collection.

- A finaliser does not accept any parameter and cannot be overloaded. They also do not support access modifiers.

- Finalisers should only be implemented on objects that use expensive resources. They are used to free up expensive resources that garbage collector does not know about. Therefore finalisers delay garbage collection.

- By using IDisposable and implementing its one and only Dispose() method, we are able to free up resources whenever we want by putting the codes in the Dispose() method. When combining this with using statement, we automatically have implemented an implicit try/finally block that will call the Dispose() method in the finally block.

- Object with finaliser should also implement IDisposable.

- Finaliser and Dispose() should have the same codes.

- Avoid any unhandled exception from happening inside a finaliser because this will be very hard to diagnose as finalisers run in their own thread.

- Dispose() should call System.GC.SuppressFinalize() which will remove the object from finalisation queue so that it can go to garbage collection immediately. Remember that finalisation must happen first before garbage collection. By calling System.GC.SuppressFinalize(), the resources clean up will not be repeated twice.

- The codes inside Dispose() or finaliser should be simple and do not refer to other objects. The codes should only be there for freeing up resources.

- If an object's class has a base class that implements Dispose() method then the derived class implementation should call the base class' Dispose().

- Dispose() method should be safe to be called multiple times.

- An object should be marked as unusable after its Dispose() method is called. An ObjectDisposedException() should be thrown when the object is tried to be used again.


Reference:
Essential C# 4.0 - Mark Michaelis , p 393-400

Thursday 17 May 2012

Using Remote Attribute Validator in ASP.NET MVC 3

In the past I have written a few posts about validation in ASP.NET MVC 3. One of them is about creating custom client side validation. There is another way to do client validation in MVC 3. This one is easier to implement for standard/common validation functions. It is the new RemoteAttribute. This attribute allows us to have client side validation that calls controller action on the back end.

To use the attribute, first we need to prepare an action method:
[HttpPost]
public ActionResult CheckFirstName(string firstname)
{
    return Json(firstname.Equals("firstname"));
}

Then specify the attribute on a field of a model:
[Remote("CheckFirstName", "Account", HttpMethod = "Post", ErrorMessage = "First name is not valid")]
public string FirstName { get; set; }
In this case we pass the action method name, controller name, HTTP method used by the action and a default error message. Notice also that the action method must accept an input parameter which would be the field's value. When specifying the Remote attribute we could also use a route name or action, controller and area names.

Let us look at another example. Here we have another action method:
[HttpPost]
public ActionResult CheckFullName(string fullName, string firstname, string lastname)
{
    return Json(fullName.Equals(string.Format("{0} {1}", firstname, lastname)));
}

Then on the model class:
[Remote("CheckFullName", "Account", HttpMethod="Post", AdditionalFields="FirstName,LastName", ErrorMessage = "Full name is not valid")]
public string FullName { get; set; }

This time we pass additional fields to the validation method. Notice the AdditionalFields parameter and also on the action method there are extra parameters passed.

One important thing to remember, to avoid the validation result being cached by the browser, we need to include this attribute on the controller action:
[OutputCache(Location = OutputCacheLocation.None, NoStore = true)]

Reference:
The Complete Guide To Validation In ASP.NET MVC 3 - Part 1