Archives

Archives / 2009 / October
  • Number Parsing in JavaScript

    How many times did you have this in your code:

    var str = getSomeNumber(); //say, 1212
    
    var num = parseInt(str);
    
    window.alert('Number is: ' + num);  //Number is: 1212
    
    

    Nothing special about it... or is it?

    It happens that JavaScript's parseInt function is smarter than you think (and, probably, smarter that it should): it tries to interpret the string passed as a parameter and returns the result based on its perceived radix, which may not be 10. An example? Try this:

    window.alert('Number is: ' + parseInt('010')); //Number is: 8!!
    
    

    So, what's the solution? Simply pass the appropriate radix as the second parameter for parseInt:

    window.alert('Number is: ' + parseInt('010', 10)); //Number is: 10!! Alright!!
    
    
    Bookmark and Share

    Read more...

  • Manually Indexing an Entity with NHibernate Search

    Updated: thanks, Ayende!

    NHibernate Search, which you can get in source format with SVN from the NHContrib trunk here, is an API that integrates NHibernate with the popular indexer Lucene.NET. Out of the box, it indexes the properties from your entities, the way you want it to (at the moment, only by using attributes), at insert/update/delete time, through the use of listeners. But what if you want to index an entity that already comes from the DB? Let's see how this can be done.

    First, out entity:

     

    [Indexed]
    public class SomeClass
    {
    	[DocumentId]
    	public virtual Int32 Id
    	{
    		get;
    		private set;
    	}
    
    	[Field(Index.Tokenized, Store = Store.Yes)]
    	public virtual String SomeProperty
    	{
    		get;
    		set;
    	}
    }
    

    Then, use this code:

    Configuration cfg = ...;
    ISession session = ...;
    SomeClass a = ...;
    
    using (IFullTextSession searchSession = Search.CreateFullTextSession(session))
    {
        searchSession.Index(a);
    }
    
    

    And, finally, query it using this:

    IList<SomeClass> items = searchSession.CreateFullTextQuery<SomeClass>("SomeProperty:SomeValue").List<SomeClass>();
    
    Bookmark and Share

    Read more...

  • Finding Dirty Properties in NHibernate

    Sometimes there may be a need for finding out if a specific entity, or a property of that entity, was changed, or, better yet, the original value for that property.

    Below is a set of extensions for ISession that give you just that.

     

    public static class SessionExtensions
    	{
    		public static Boolean IsDirtyEntity(this ISession session, Object entity)
    		{
    			String className = NHibernateProxyHelper.GuessClass(entity).FullName;
    			ISessionImplementor sessionImpl = session.GetSessionImplementation();
    			IPersistenceContext persistenceContext = sessionImpl.PersistenceContext;
    			IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(className);
    			EntityEntry oldEntry = sessionImpl.PersistenceContext.GetEntry(entity);
    
    			if ((oldEntry == null) && (entity is INHibernateProxy))
    			{
    				INHibernateProxy proxy = entity as INHibernateProxy;
    				Object obj = sessionImpl.PersistenceContext.Unproxy(proxy);
    				oldEntry = sessionImpl.PersistenceContext.GetEntry(obj);
    			}
    
    			Object [] oldState = oldEntry.LoadedState;
    			Object [] currentState = persister.GetPropertyValues(entity, sessionImpl.EntityMode);
    			Int32 [] dirtyProps = persister.FindDirty(currentState, oldState, entity, sessionImpl);
    			
    			return (dirtyProps != null);
    		}
    
    		public static Boolean IsDirtyProperty(this ISession session, Object entity, String propertyName)
    		{
    			String className = NHibernateProxyHelper.GuessClass(entity).FullName;
    			ISessionImplementor sessionImpl = session.GetSessionImplementation();
    			IPersistenceContext persistenceContext = sessionImpl.PersistenceContext;
    			IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(className);
    			EntityEntry oldEntry = sessionImpl.PersistenceContext.GetEntry(entity);
    
    			if ((oldEntry == null) && (entity is INHibernateProxy))
    			{
    				INHibernateProxy proxy = entity as INHibernateProxy;
    				Object obj = sessionImpl.PersistenceContext.Unproxy(proxy);
    				oldEntry = sessionImpl.PersistenceContext.GetEntry(obj);
    			}
    
    			Object [] oldState = oldEntry.LoadedState;
    			Object [] currentState = persister.GetPropertyValues(entity, sessionImpl.EntityMode);
    			Int32 [] dirtyProps = persister.FindDirty(currentState, oldState, entity, sessionImpl);
    			Int32 index = Array.IndexOf(persister.PropertyNames, propertyName);
    
    			Boolean isDirty = (dirtyProps != null) ? (Array.IndexOf(dirtyProps, index) != -1) : false;
    
    			return (isDirty);
    		}
    
    		public static Object GetOriginalEntityProperty(this ISession session, Object entity, String propertyName)
    		{
    			String className = NHibernateProxyHelper.GuessClass(entity).FullName;
    			ISessionImplementor sessionImpl = session.GetSessionImplementation();
    			IPersistenceContext persistenceContext = sessionImpl.PersistenceContext;
    			IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(className);
    			EntityEntry oldEntry = sessionImpl.PersistenceContext.GetEntry(entity);
    
    			if ((oldEntry == null) && (entity is INHibernateProxy))
    			{
    				INHibernateProxy proxy = entity as INHibernateProxy;
    				Object obj = sessionImpl.PersistenceContext.Unproxy(proxy);
    				oldEntry = sessionImpl.PersistenceContext.GetEntry(obj);
    			}
    
    			Object [] oldState = oldEntry.LoadedState;
    			Object [] currentState = persister.GetPropertyValues(entity, sessionImpl.EntityMode);
    			Int32 [] dirtyProps = persister.FindDirty(currentState, oldState, entity, sessionImpl);
    			Int32 index = Array.IndexOf(persister.PropertyNames, propertyName);
    
    			Boolean isDirty = (dirtyProps != null) ? (Array.IndexOf(dirtyProps, index) != -1) : false;
    
    			return ((isDirty == true) ? oldState [ index ] : currentState [ index ]);
    		}
    	}
    
    
    Bookmark and Share

    Read more...

  • .NET Serializers, part 2

    There were some things left (well, a lot, actually) from my previous article on .NET serializers. One of these things was the ability to have serializers call specific methods before or after serialization. This can be achieved in two ways:

    • Through implementation of interfaces;
    • Through the use of attributes.

    Interface System.Runtime.Serialization.IDeserializationCallback defines a method named OnDeserialization that is called after de deserialization process. You receive the deserialized object as its only argument and you can change it at your will. Only works with IFormatter-based serializers, such as BinaryFormatter and SoapFormatter, not with XmlSerializer.

    As for attributes, the following can be applied to methods of your class:

    • System.Runtime.Serialization.OnSerializingAttribute (IFormatter and XmlObjectSerializer)
    • System.Runtime.Serialization.OnSerializedAttribute (IFormatter and XmlObjectSerializer)
    • System.Runtime.Serialization.OnDeserializingAttribute (IFormatter and XmlObjectSerializer)
    • System.Runtime.Serialization.OnDeserializedAttribute (IFormatter and XmlObjectSerializer)

    Doesn't matter if the methods are public or private, but they must have the following signature:

    void MethodName(StreamingContext ctx)

    Through the StreamingContext parameter you can access the properties that will be serialized or deserialized and act upon them.

    Please notice that the attribute-based approach is the only one that works with WCF, which uses XmlObjectSerializer-based serializers, as well as IFormatter-based.

    Bookmark and Share

    Read more...

  • .NET Serializers

    (UPDATED) 

    As of version 3.5 SP1, .NET comes along with the following serializers:

    • System.Runtime.Serialization.Formatters.Binary.BinaryFormatter: binary serializer used in .NET Remoting, type information is included, understands System.Runtime.Serialization.ISerializable;
    • System.Runtime.Serialization.Formatters.Soap.SoapFormatter: SOAP (XML) serializer used in .NET Remoting, includes type information, understands System.Runtime.Serialization.ISerializable;
    • System.Runtime.Serialization.DataContractSerializer: XML serializer used in WCF, does not include type information;
    • System.Runtime.Serialization.Json.DataContractJsonSerializer: JSON serializer used in WCF, does not include type information;
    • System.Runtime.Serialization.NetDataContractSerializer: binary serializer used in WCF, includes type information;
    • System.Xml.Serialization.XmlSerializer: XML serializer used in ASP.NET Web Services (ASMX), type information is not included, understands System.Xml.Serialization.IXmlSerializable; 
    • System.Web.UI.LosFormatter: uses ObjectStateFormatter internally, does not account by itself;
    • System.Web.UI.ObjectStateFormatter: binary or text (base 64 encoded) serializer used in ASP.NET for storing items in view state, control state and session, type information is included, understands System.Runtime.Serialization.ISerializable.

    There isn't, however, a common interface for all of these serializers, and, in fact, they have quite different requirements.

    The base interfaces are:

    • System.Runtime.Serialization.IFormatter: for BinaryFormatter, SoapFormatter, NetDataContractSerializer and ObjectStateFormatter;
    • System.Runtime.Serialization.XmlObjectSerializer: for DataContractSerializer, DataContractJsonSerializer and NetDataContractSerializer;
    • XmlSerializer doesn't have any interface that specifies its behavior.

    The interfaces that can be used to control the serialization process are:

    • System.Runtime.Serialization.ISerializable: for all the IFormatter serializers;
    • System.Xml.Serialization.IXmlSerializable: for XmlSerializer.

    Also, there are a couple of attribute classes that can be used to control the serialization process:

    • System.Runtime.Serialization.OptionalFieldAttribute (IFormatter): field may be missing from the serialized content
    • System.Runtime.Serialization.NonSerializedAttribute (IFormatter): field is not serialized
    • System.Xml.Serialization.SoapAttributeAttribute (XmlSerializer)
    • System.Xml.Serialization.SoapElementAttribute (XmlSerializer)
    • System.Xml.Serialization.SoapEnumAttribute (XmlSerializer)
    • System.Xml.Serialization.SoapIgnoreAttribute (XmlSerializer)
    • System.Xml.Serialization.SoapIncludeAttribute (XmlSerializer)
    • System.Xml.Serialization.SoapTypeAttribute (XmlSerializer)
    • System.Xml.Serialization.SoapDocumentServiceAttribute (XmlSerializer): default format is Document
    • System.Xml.Serialization.SoapRpcServiceAttribute (XmlSerializer): default format is RPC
    • System.Xml.Serialization.SoapRpcMethodAttribute (XmlSerializer): method uses SOAP RPC format
    • System.Xml.Serialization.SoapDocumentMethodAttribute (XmlSerializer): method uses SOAP Document format
    • System.Xml.Serialization.XmlAnyAttribute (XmlSerializer)
    • System.Xml.Serialization.XmlAnyElementAttribute (XmlSerializer)
    • System.Xml.Serialization.XmlArrayAttribute (XmlSerializer)
    • System.Xml.Serialization.XmlArrayItemAttribute (XmlSerializer)
    • System.Xml.Serialization.XmlAttributeAttribute (XmlSerializer)
    • System.Xml.Serialization.XmlChoiceIdentifierAttribute (XmlSerializer)
    • System.Xml.Serialization.XmlElementAttribute (XmlSerializer)
    • System.Xml.Serialization.XmlEnumAttribute (XmlSerializer)
    • System.Xml.Serialization.XmlIgnoreAttribute (XmlSerializer)
    • System.Xml.Serialization.XmlIncludeAttribute (XmlSerializer)
    • System.Xml.Serialization.XmlRootAttribute (XmlSerializer)
    • System.Xml.Serialization.XmlTextAttribute (XmlSerializer)
    • System.Xml.Serialization.XmlTypeAttribute (XmlSerializer)
    • System.Xml.Serialization.XmlSchemaProviderAttribute (XmlSerializer): applied on a method that returns the XML schema
    • System.Runtime.Serialization.CollectionDataContractAttribute (XmlObjectSerializer)
    • System.Runtime.Serialization.DataContractAttribute (XmlObjectSerializer)
    • System.Runtime.Serialization.DataMemberAttribute (XmlObjectSerializer)
    • System.Runtime.Serialization.EnumMemberAttribute (XmlObjectSerializer)
    • System.Runtime.Serialization.IgnoreDataMemberAttribute (XmlObjectSerializer)
    • System.Runtime.Serialization.XmlSerializerFormatAttribute (XmlObjectSerializer): choose XmlSerializer instead of DataContractSerializer

    Note that the Soap* attributes are only considered if the SoapBindingUse.Encoded is set for the Use property of the binding, in ASP.NET Web Services, otherwise, its the Xml* attributes.

    It would be good to see a common interface (perhaps IFormatter, since it's the most common) for all of these serializers.

    Bookmark and Share

    Read more...

  • Generating a Unique Identifier for Each Page Instance

    Sometimes there may be a need for identifying each page instance univocally. One ocasion may be, for example, if we want to store something in a session which is specific to a certain page.

    What I did was override the Page class' ID property and have it return a unique value for a page that is kept throughout all postbacks. Here is my code:

    public override String ID

    {

        get

        {

            String id = null;

            if ((this.IsPostBack == true) && (String.IsNullOrEmpty(this.Context.Request.Form["__ID"]) == false))

            {

                id = this.Context.Request.Form["__ID"];

            }

            else if (String.IsNullOrEmpty(this.Context.Items [ "__ID" ] as String) == false)

            {

                 id =
    this.Context.Items [ "__ID" ] as String;

            }

            else

            {

                id =
    Guid.NewGuid().ToString();            this.Context.Items [ "__ID" ] = id;

            }

     

            return (id);

        }

    }

    protected override void OnPreInit(EventArgs e)

    {

        this.ClientScript.RegisterHiddenField("__ID", this.ID);    base.OnPreInit(e);

    }

    Bookmark and Share

    Read more...

  • Custom Binding With EntityDataSource

    Here's a common scenario: you are using an EntityDataSource control which you are binding to a data control, perhaps a ListView, DataGrid, DataList, Repeater, or GridView. The problem is, you want to do some custom binding. This happens, for example, when viewing a master-detail relationship.

    What you typically do then is implement a custom event handler for event ItemDataBound (for ListView, DataGrid, DataList and Repeater) or RowDataBound (for GridView) and do something with the e.Item.DataItem property value (in the former cases) or e.Row.DataItem (in the later one), which is, of course, a pointer to your entity object... or is it? Depending on the way you've set up EntityDataSource on your page, it may or may not be.

    If you used the EntitySetName property to indicate the name of your entity, it won't work, because the e.Item.DataItem (or e.Row.DataItem) will instead contain a wrapper object:

    <asp:EntityDataSource ID="myEntitiesDataSource" runat="server" ConnectionString="name=MyEntities" EntitySetName="Entity"

    DefaultContainerName="MyEntities" />

    protected void OnItemDataBound(Object sender, RepeaterItemEventArgs e)

    {

        Entity entity = e.Item.DataItem as Entity//null

        entity = this.GetWrappedEntity<Entity>(e.Item.DataItem);  //see code below

    }

    In this case, you must use this in order to get the actual entity: 

    protected TEntity GetWrappedEntity<TEntity>(Object dataItem) where TEntity : class

    {

        TEntity entity = dataItem
    as TEntity;
        if (entity != null)

        {

            return (entity);

        }

        else

        {

            ICustomTypeDescriptor td = dataItem as ICustomTypeDescriptor;        if (td != null)

            {

                return (td.GetPropertyOwner(null) as TEntity);

            }

            else

            {

                return (null);

            }

        }

    }

    If, however, you skip the EntitySetName property and instead set the CommandText property, everything works as usual:

    <asp:EntityDataSource ID="myEntitiesDataSource" runat="server"

    ConnectionString="name=MyEntities" CommandText="SELECT VALUE entity FROM MyEntities.Entities AS entity"

    DefaultContainerName="MyEntities" />

    protected void OnItemDataBound(Object sender, RepeaterItemEventArgs e)

    {

        Entity entity = e.Item.DataItem as Entity//ok

    }

    Hope this saves you some trouble! :-)

    Bookmark and Share

    Read more...

  • New Version of AJAX Control Toolkit Released

    Version 3.0.30930 is out. This release includes two new controls:

    • Seadragon - Seadragon enables you to pan, zoom, and make an image full screen. You can use it, for example, to display interactive product pictures.
    • AsyncFileUpload - This new control enables you to perform file uploads without doing a postback. The control displays a throbber image during upload and raises client and server events when the upload is complete. This control was contributed by Steven Lindsay.

    More than 20 bugs were also fixed. See them all live at the samples page.

    Get it here. Also check the candidate controls submitted by the community.

    Bookmark and Share

    Read more...