Development With A Dot

Blog on development in general, and specifically on .NET

Sponsors

News

My Friends

My Links

Permanent Posts

Portuguese Communities

September 2009 - Posts

Detecting Chrome Browser in ASP.NET

ASP.NET comes with a browser capabilities database (BCD), which describes the capabilities of known browsers. This database is usefull for control developers that want to take advantage on different browser capabilities. Of course, more recent browsers are not listed on that database, simply because they did not exist at the time ASP.NET 2.0 was released (versions 3.0, 3.5 and 3.5 SP1 don't add anything new), and, specifically, Chrome is not on that list.

If you want to add new browsers to the BCD, you have two options:

  1. The global database, located in the %Windir%\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers directory
  2. A local database on your ASP.NET application, in the App_Browsers directory

In any case, you start by adding a new file, say, Chrome.browser, to the appropriate directory. Looking at all browsers registed in the BCD, we choose Safari as the most similar one, and have our definition inherit from it:

<browsers>

    <browser id="Chrome" parentID="Safari1Plus">

        <identification>             <userAgent match="Chrome/(?'version'(?'major'\d+)\.(?'minor'\d+\.\d+).\d+)" />

        </identification>

        <capabilities>

            <capability name="browser" value="Chrome" />

            <capability name="majorversion" value="${major}" />

            <capability name="minorversion" value="${minor}" />

            <capability name="version" value="${version}" />

        </capabilities>

    </browser>

</browsers>

Of course, you can override the capabilities defined for Safari, if you want, but I think they should be OK. Also, you can add entries for all the Chrome versions.

If you try to access your web application running Chrome and look at the HttpContext.Request.Browser.BrowserName, you may be surprised to see that the name is... not Chrome! It so happens that you must increase the number of characters ASP.NET uses for the user agent header, and you do this in Web.config:

<system.web>

    <browserCaps userAgentCacheKeyLength="128" />

    ...

And that's it! If you try now, you'll see that the BrowserName property is now "Chrome" and that the listed capabilities match the configured ones.

Bookmark and Share
Posted: Sep 22 2009, 06:43 PM by Ricardo Peres | with 8 comment(s)
Filed under: ,
Data Annotations Property Validator for ASP.NET

Entity Framework, LINQ to SQL and ASP.NET MVC support Microsoft's new validation API, which you can find on System.ComponentModel.DataAnnotations. It basically consists on attribute classes, inherited from System.ComponentModel.DataAnnotations.ValidationAttribute. It is very easy to define your own, although Enterprise Library, xVal and Spring.NET validations are considerably power powerfull.

I wanted to have a custom ASP.NET validator that would validate the value of a form control against the validation attributes defined for a given property of a class, in a way similar to the Web Client Software Factory's PropertyProxyValidator, like you can read in this post. This is what I came up with: class DataAnnotationsValidator!

Here is the code:

public class DataAnnotationsValidator : BaseValidator

{

    protected override void OnInit(EventArgs e)

    {

        if ((this.Enabled == true) && (this.Visible == true))

        {

            this.Page.RegisterRequiresControlState(this);

        }

        base.OnInit(e);

    }

    protected override void LoadControlState(Object savedState)

    {

        Object [] state = savedState as Object [];

        base.LoadControlState(state [ 0 ]);

        this.DisplayMode = (ValidationSummaryDisplayMode) state [ 1 ];

        this.PropertyName = (String) state [ 2 ];

        this.SourceTypeName = (String) state [ 3 ];

    }

    protected override Object SaveControlState()

    {

        Object [] state = new Object [ 4 ];

        state [ 0 ] = base.SaveControlState();

        state [ 1 ] = this.DisplayMode;

        state [ 2 ] = this.PropertyName;

        state [ 3 ] = this.SourceTypeName;

        return (state);

    }

    protected override Boolean EvaluateIsValid()

    {

        if ((String.IsNullOrEmpty(this.SourceTypeName) == true) || (String.IsNullOrEmpty(this.PropertyName) == true))

        {

            return (true);

        }

        Type type = Type.GetType(this.SourceTypeName, false);

        if (type != null)

        {

            PropertyInfo prop = type.GetProperty(this.PropertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);

            if (prop != null)

            {

                ValidationAttribute [] attrs = prop.GetCustomAttributes(typeof(ValidationAttribute), true) as ValidationAttribute [];

                List<ValidationException> errors = new List<ValidationException>();

                String value = this.GetControlValidationValue(this.ControlToValidate);

                if (attrs.Length == 0)

                {

                    MetadataTypeAttribute [] metadata = type.GetCustomAttributes(typeof(MetadataTypeAttribute), true) as MetadataTypeAttribute [];

 

                    if (metadata.Length != 0)

                    {

                        prop = metadata[0].MetadataClassType.GetProperty(this.PropertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);

                        if (prop != null)

                        {

                            attrs = prop.GetCustomAttributes(typeof(ValidationAttribute), true) as ValidationAttribute [];

                        }

                    }

                }

                for (Int32 i = 0; i < attrs.Length; ++i)

                {

                    try

                    {

                        attrs [ i ].Validate(value, prop.Name);

                    }

                    catch (ValidationException ve)

                    {

                        errors.Add(ve);

                    }

                    catch

                    {

                    }

                }

                this.ErrorMessage = this.formatErrorMessage(errors);

                return (errors.Count == 0);

            }

        }

        this.ErrorMessage = String.Empty;

        return (true);

    }

    private String formatErrorMessage(IList<ValidationException> results)

    {

        String str = String.Empty;

        String str2 = String.Empty;

        String str3 = String.Empty;

        String str4 = String.Empty;

        StringBuilder builder = new StringBuilder();

        switch (this.DisplayMode)

        {

            case ValidationSummaryDisplayMode.List:

                str3 = "<br/>";

                break;

            case ValidationSummaryDisplayMode.SingleParagraph:

                str3 = " ";

                str4 = "<br/>";

                break;

            default:

                str = "<ul>";

                str2 = "<li>";

                str3 = "</li>";

                str4 = "</ul>";

                break;

        }

        if (results.Count != 0)

        {

           builder.Append(str);

            foreach (ValidationException result in results)

            {

                builder.Append(str2);

                builder.Append(result.Message);

                builder.Append(str3);

            }

            builder.Append(str4);

        }

        return (builder.ToString());

    }

    [Browsable(true)]

    [DefaultValue(ValidationSummaryDisplayMode.List)]

    public ValidationSummaryDisplayMode DisplayMode

    {

        get;

        set;

    }

    [Browsable(true)]

    [DefaultValue("")]

    public String PropertyName

    {

        get;

        set;

    }

    [Browsable(true)]

    [DefaultValue("")]

    public String SourceTypeName

    {

        get;

        set;

    }

}

As you can see, it is smart enough to try to find the validation attributes on a metadata class defined with a MetadataTypeAttribute attribute, like you would use with generated code, such as Entity Framework's. It also supports all of ValidationSummaryDisplayMode's options.

This is how you would use it:

 

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

<blog:DataAnnotationsValidator runat="server" ControlToValidate="text" SourceTypeName="SomeClass, SomeAssembly" PropertyName="SomeProperty" />

<asp:Button runat="server" Text="Validate" OnClick="OnValidate" />

Suppose the class you want to validate looks like this:

public class SomeClass

    [Required]

    [RegularExpression(@"\d\d\d")]

    public String SomeProperty

    {

        get;

        set;

    }

}

And that's it! Happy validation!

Bookmark and Share
INotifyPropertyChang{ed,ing} and NHibernate

(Updated: thanks, Tom!) 

Here's the scenario: your domain model implements INotifyPropertyChanged and INotifyPropertyChanging, so you want to be notified whenever your properties change. NHibernate has an interceptor model that can be used with, together with code generators, to do this transparently.

First, let's define a custom NHibernate interceptor that is also a Castle Project interceptor:

public class NotifyPropertyChangeInterceptor : EmptyInterceptor, Castle.Core.Interceptor.IInterceptor

{

    private static readonly ProxyGenerator proxyGenerator = new ProxyGenerator();

    public NotifyPropertyChangeInterceptor(ISessionFactory sessionFactory)

    {

        this.SessionFactory = sessionFactory;

    }

    public ISessionFactory SessionFactory

    {

        set;

        private get;

    } 

    public override String GetEntityName(Object entity)

    {

        if (entity.GetType().Assembly.FullName.StartsWith("DynamicProxyGenAssembly2") == true)

        {

            return(entity.GetType().BaseType.FullName); 

        }

       else

        {

            return(entity.GetType().FullName);

        }

    }

    public override Object Instantiate(String clazz, EntityMode entityMode, Object id)

    {

        if (entityMode == EntityMode.Poco)

        {

            Type type = Type.GetType(clazz, false);

            if (type != null)

            {

                Object instance = this.create(type);

                this.SessionFactory.GetClassMetadata(clazz).SetIdentifier(instance, id, entityMode);

                return (instance);

            }

        }

        return (base.Instantiate(clazz, entityMode, id));

    }

    void Castle.Core.Interceptor.IInterceptor.Intercept(IInvocation invocation)

    {

        if (typeof(INotifyPropertyChanging).IsAssignableFrom(invocation.Method.DeclaringType) == true)

        {

            if (invocation.Method.Name.StartsWith("set_") == true)

            {

                String propertyName = invocation.Method.Name.Substring(4);

                FieldInfo field = invocation.InvocationTarget.GetType().BaseType.GetField("PropertyChanging", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField);

                MulticastDelegate evt = field.GetValue(invocation.InvocationTarget) as MulticastDelegate;

                if (evt != null)

                {

                    foreach (Delegate del in evt.GetInvocationList())

                    {

                        del.Method.Invoke(invocation.InvocationTarget, new Object [] { invocation.InvocationTarget, new PropertyChangingEventArgs(propertyName) });

                    }

                }

            }

        }

        invocation.Proceed();

        if (typeof(INotifyPropertyChanged).IsAssignableFrom(invocation.Method.DeclaringType) == true)

        {

            if (invocation.Method.Name.StartsWith("set_") == true)

            {

                String propertyName = invocation.Method.Name.Substring(4);

                FieldInfo field = invocation.InvocationTarget.GetType().BaseType.GetField("PropertyChanged", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField);

                MulticastDelegate evt = field.GetValue(invocation.InvocationTarget) as MulticastDelegate;

                if (evt != null)

                {

                    foreach (Delegate del in evt.GetInvocationList())

                    {

                        del.Method.Invoke(invocation.InvocationTarget, new Object [] { invocation.InvocationTarget, new PropertyChangedEventArgs(propertyName) });

                    }

                }

            }

        }

    }

    private Object create(Type type)

    {

        return (proxyGenerator.CreateClassProxy(type, new Type [] { typeof(INotifyPropertyChanged), typeof(INotifyPropertyChanging) }, this));

    }

}

You class is something like this:

[Serializable]

public class SomeClass : INotifyPropertyChanged, INotifyPropertyChanging

{

    public virtual Int32 Id

    {

        get;

        set;

    }

    public virtual String SomeProperty

    {

        get;

        set;

    }

    public virtual event PropertyChangedEventHandler PropertyChanged;

    public virtual event PropertyChangingEventHandler PropertyChanging;

}

And this is how you would use it:

using (ISessionFactory factory = cfg.BuildSessionFactory())

{

    NotifyPropertyChangeInterceptor interceptor = new NotifyPropertyChangeInterceptor(factory);

 

    using (ISession session = factory.OpenSession(interceptor))

    using (ITransaction tx = session.BeginTransaction())

    {

        SomeClass c = session.Load<A>(1);

        c.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e) { Console.WriteLine("Property {0} Changed", e.PropertyName); };

        c.SomeProperty = "blah";

    }

Bookmark and Share
NHibernate Image User Type

Supose you want to have in your domain model a property which is of type System.Drawing.Image. On SQL Server, you would map this as a column of type IMAGE, and on your domain model you would define it like this:

public virtual System.Drawing.Image Image

{

    get;

    set;

}

In order to use it with NHibernate, you must define a custom user type, by implementing the NHibernate.UserTypes.IUserType interface. We write a ImageUserType class and register it at the property definition in the .hbm.xml file:

<property name="Image" column="`Image`" type="ImageUserType, MyAssembly"/>

And here is the code;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using NHibernate.UserTypes;

using System.Data;

using NHibernate.SqlTypes;

using System.Drawing;

using NHibernate;

using System.IO;

using System.Drawing.Imaging;

public class ImageUserType: IUserType

{

    public Object Assemble(Object cached, Object owner)

    {

        return (cached);

    }

    public Object DeepCopy(Object value)

    {

        if (value == null)

        {

            return (null);

        }

        else

        {

            return ((value as ICloneable).Clone());

        }

    }

    public Object Disassemble(Object value)

    {

        return (value);

    }

    public Int32 GetHashCode(Object x)

    {

        return (x != null ? x.GetHashCode() : 0);

    }

    public Boolean IsMutable

    {

        get

        {

            return (false);

        }

    }

    public Object NullSafeGet(IDataReader rs, String [] names, Object owner)

    {

        Byte [] data = NHibernateUtil.Binary.NullSafeGet(rs, names [ 0 ]) as Byte [];

        if (data != null)

        {

            using (Stream stream = new MemoryStream(data))

            {

                Image image = Image.FromStream(stream);

                return (image);

            }

        }

        else

        {

            return (null);

        }

    }

    public void NullSafeSet(IDbCommand cmd, Object value, Int32 index)

    {

        if (value == null)

        {

            NHibernateUtil.Binary.NullSafeSet(cmd, null, index);

        }

        else

        {

            using (MemoryStream stream = new MemoryStream())

            {

                Image image = value as Image;

                image.Save(stream, ImageFormat.Png);

                NHibernateUtil.String.NullSafeSet(cmd, stream.GetBuffer(), index);

            }

        }

    }

    public Object Replace(Object original, Object target, Object owner)

    {

        return (original);

    }

    public Type ReturnedType

    {

        get

        {

            return (typeof(Image));

        }

    }

    public SqlType [] SqlTypes

    {

        get

        {

            return (new SqlType [] { new SqlType(DbType.Binary) });

        }

    }

    Boolean IUserType.Equals(Object o1, Object o2)

    {

        return (Object.Equals(o1, o2));

    }

}

This saves the image object as an array of bytes (in PNG format, to use compression) and loads it into an System.Drawing.Image. The image is immutable, so a lot of methods are quite simple.

I think the code is easily understandable, but if you have problems, let me know!

Bookmark and Share
AntiXSS 3.1 Released

New version, 3.1, was released yesterday. You can get it from here.

Read about the new features here.

Bookmark and Share
Thread Synchronization in .NET

This comes after my last post Multi-threading in .NET. There are several synchronization mechanisms you can use in your .NET applications, so choosing among them must be done wisely.

First you must decide one thing:

Do you need to synchronize threads in different processes on the same machine?

If so, the available possibilities are:

  • System.Threading.Semaphore: the number of concurrent entries is specified at construction time; all entries are treated equally; the name of the synchronization object must also be specified when the semaphore is created;
  • System.Threading.Mutex: equals a semaphore with the maximum number of concurrent entries set to 1; the name of the synchronization object must be specified when the mutex is created;
  • System.Threading.EventWaitHandle (or their better known children, System.Threading.ManualResetEvent and System.Threading.AutoResetEvent): the name of the synchronization object must be specified when the instance is created, as well as the reset policy; if set to auto, whenever the EventWaitHandle is signaled, only one object waiting on it will succeed.

If you only want to synchronize threads inside a single process, you have more options, but first you must decide on this:

Do you want all of your threads to be equally treated?

If so, try these:

  • All of the above classes, but you can skip setting the name of the synchronization object;
  • System.Threading.Monitor (best known as the lock keyword): only one object at a time can have hold of the synchronization lock;
  • System.Runtime.CompilerServices.MethodImplAttribute attribute: if used with System.Runtime.CompilerServices.MethodImplOptions.Synchronized option, marks a method as synchronized, so there can be only one thread at a time running it.

Otherwise, the BCL has support for a classical synchronization scenario: reader-writer. In this case, all access are not equal: some require write access and some require read access. There are two classes available for implementing this:

  • System.Threading.ReaderWriterLock: allows at any time either: 1) a single writer or 2) any number of readers;
  • System.Threading.ReaderWriterLockSlim: a more recent and optimized version of ReaderWriterLock; you should use this instead.

It is worth noting that typically scenarios with different access levels offer better performance than the ones where every thread is treated the same, and thus waits on the same object.

Happy multi-threading!

 

Bookmark and Share
Multi-threading in .NET

In .NET 2.0+, if you want to have something run on another thread, you have a number of choices:

  • The classical System.Threading.Thread class
  • The not-so-known System.Threading.ThreadPool
  • The System.ComponentModel.BackgroundWorker
  • Delegates invoked asynchronously

Let's see how we would do it in each case, and what would be the benefits. Let's suppose our thread method looks like this:

private void ThreadMethod(Object state)

{

}

Using System.Threading.Thread

You start a new System.Threading.Thread instance and pass it a pointer to the thread method wrapped in a System.Threading.ParameterizedThreadStart (for an optional state parameter) or System.Threading.ThreadStart delegate, then, you start it, by calling Start:

Thread thread = new Thread(state => ThreadMethod(state));

thread.Start(state); 

As you can see, I am using the new .NET 3.5 lambda syntax for delegates.

If you want to wait for the thread to exit, do this:

thread.Join(timeout);

 

Using System.Threading.ThreadPool

Assuming your thread pool is properly configured (maximum number of threads, minimum number of threads before creating another one, etc), all you have to do is enqueue a method for execution, whenever a thread from the pool is free:

Boolean result = ThreadPool.QueueUserWorkItem(ThreadMethod, state);

Or, if you must wait for the result:

ManualResetEvent handle = new ManualResetEvent(false);

ThreadPool.RegisterWaitForSingleObject(handle, (s, timedout) => ThreadMethod(s), state, timeout, true);

handle.WaitOne();

By the way, QueueUserWorkItem always returns true, otherwise an exception is thrown.

 

Using System.ComponentModel.BackgroundWorker

You create an instance of the System.ComponentModel.BackgroundWorker class, add an event handler to its DoWork event, and start the processing by calling RunWorkerAsync, with an optional state parameter:

BackgroundWorker worker = new BackgroundWorker();worker.DoWork += delegate(Object sender, DoWorkEventArgs args) { ThreadMethod(args.Argument); };

worker.RunWorkerAsync(state); 

Waiting for the worker to complete is accomplished this way:

ManualResetEvent handle = new ManualResetEvent(false);

ThreadPool.RegisterWaitForSingleObject(handle, (s, timedout) => ThreadMethod(s), state, timeout, true);

handle.WaitOne();

The System.ComponentModel.BackgroundWorker class is available from the Windows Forms toolbox, in design view, so you can drag it into your form, and change its properties or register events through the property inspector.

 

Using Delegates

You declare a delegate that points to your method and you start its BeginInvoke method, passing it the state parameter and optionally a callback method, that gets called when the method terminates, and a state argument for that callback: Action<Object> action = ThreadMethod;

action.BeginInvoke(state, null, null);

And waiting:

Action<Object> action = ThreadMethod;IAsyncResult result = action.BeginInvoke(state, null, null);

result.AsyncWaitHandle.WaitOne(timeout);

 

So, what is the difference between all these methods? Let's see:

  • You would use System.Threading.Thread class when you want your task to be run exactly now; you may also want to suspend it or kill it;
  • System.Threading.ThreadPool helps preserving resources: no new threads are created, we just grab another one from the pool, if it is available, or wait for it, so the job may not start immediately; you don't have control over the actual thread that does the job;
  • If you want to have feedback from a thread, you use System.ComponentModel.BackgroundWorker. Its events allows you to set the completion status and to be notified when the task finishes. Typically you use it in a Windows Forms application. As it uses internally the thread pool, jobs may not start immediately;
  • Delegates are a fast way of launching a thread from a method delegate; it also uses the thread pool, so a task may take some time to actually start.

In all cases, starting from .NET 2.0, the spawned threads retain the same principal (System.Threading.Thread.CurrentPrincipal property), which is great for access control.

Bookmark and Share
Developing SharePoint Applications Guidance Released

August release is available at http://www.microsoft.com/downloads/details.aspx?FamilyId=91f3c22c-8be7-4721-9449-84f699337d55&displaylang=en.

The SharePoint Guidance site is available at http://www.codeplex.com/spg/.

Bookmark and Share
Set Default Interceptor Unity Extension

With Unity, it is quite easy to implement an extension that automatically sets the appropriate interceptor for each registered type.

Here is how I did it:

public class DefaultInterceptorInterceptionExtension : Interception

{

     private static readonly IInterceptor [] interceptors = null;    static DefaultInterceptorInterceptionExtension()

    {

        interceptors = (from interceptorType in

        (from type in typeof(IInterceptor).Assembly.GetExportedTypes()

        where typeof(IInterceptor).IsAssignableFrom(type) &&

        type.IsAbstract == false &&

        type.IsInterface == false

        select type)        select Activator.CreateInstance(interceptorType) as IInterceptor).ToArray();

    }

    protected override void Initialize()

    {

        base.Initialize();

        IConfigurationSource configSource = ConfigurationSourceFactory.Create();

        PolicyInjectionSettings section = configSource.GetSection(PolicyInjectionSettings.SectionName) as PolicyInjectionSettings;

        if (section != null)

        {

            section.ConfigureContainer(
this.Container, configSource);

        }

        this.Context.Registering += new EventHandler<RegisterEventArgs>

        (

            delegate(Object sender, RegisterEventArgs e)

            {

                this.setInterceptorFor(e.TypeFrom, e.TypeTo, e.Name);

            }

        );

        this.Context.RegisteringInstance += new EventHandler<RegisterInstanceEventArgs>

        (

            delegate(Object sender, RegisterInstanceEventArgs e)

            {

                this.setInterceptorFor(e.RegisteredType, e.Instance.GetType(), e.Name);

            }

        );

    }

    private void setInterceptorFor(Type typeToIntercept, Type typeOfInstance, String name)

    {

        foreach (IInterceptor interceptor in interceptors)

        {

            if ((interceptor.CanIntercept(typeToIntercept) == true) && (interceptor.GetInterceptableMethods(typeToIntercept, typeOfInstance).Count() != 0))

            {

                if (interceptor is IInstanceInterceptor)

                {

                    this.Container.Configure<Interception>().SetDefaultInterceptorFor(typeToIntercept, interceptor as IInstanceInterceptor);

                }

                else if (interceptor is ITypeInterceptor)

                {

                    this.Container.Configure<Interception>().SetDefaultInterceptorFor(typeToIntercept, interceptor as ITypeInterceptor);

                }

                break;

            }

        }

    }

}

And you register with like this:

<unity>

    <typeAliases>

        <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

        <typeAlias alias="transient" type="Microsoft.Practices.Unity.TransientLifetimeManager, Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

        <typeAlias alias="external" type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager, Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

        <typeAlias alias="thread" type="Microsoft.Practices.Unity.PerThreadLifetimeManager, Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

    </typeAliases>

    <containers>

        <container>

            <extensions>

                <add type="DefaultInterceptorInterceptionExtension, SomeAssembly" />

            </extensions>

        </container>

    </containers>

<unity>

Bookmark and Share
More Posts