Development With A Dot

Blog on development in general, and specifically on .NET
Loading a Template From a User Control

What if you wanted to load a template (ITemplate property) from an external user control (.ascx) file?

Yes, it is possible; there are a number of ways to do this, the one I'll talk about here is through a type converter.

You need to apply a TypeConverterAttribute to your ITemplate property where you specify a custom type converter that does the job. This type converter relies on InstanceDescriptor. Here is the code for it:

	public class TemplateTypeConverter: TypeConverter
	{
		public override Boolean CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
		{
			return ((sourceType == typeof(String)) || (base.CanConvertFrom(context, sourceType) == true));
		}

		public override Boolean CanConvertTo(ITypeDescriptorContext context, Type destinationType)
		{
			return ((destinationType == typeof(InstanceDescriptor)) || (base.CanConvertTo(context, destinationType) == true));
		}

		public override Object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, Object value, Type destinationType)
		{
			if (destinationType == typeof(InstanceDescriptor))
			{
				Object objectFactory = value.GetType().GetField("_objectFactory", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(value);
				Object builtType = objectFactory.GetType().BaseType.GetField("_builtType", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectFactory);				
				MethodInfo loadTemplate = typeof(TemplateTypeConverter).GetMethod("LoadTemplate");				
				return (new InstanceDescriptor(loadTemplate, new Object [] { "~/" + (builtType as Type).Name.Replace('_', '/').Replace("/ascx", ".ascx") }));
			}
			
			return base.ConvertTo(context, culture, value, destinationType);
		}

		public static ITemplate LoadTemplate(String virtualPath)
		{
			using (Page page = new Page())
			{
				return (page.LoadTemplate(virtualPath));
			}
		}
	}

And, on your control:

public class MyControl: Control
{
	[Browsable(false)]
	[TypeConverter(typeof(TemplateTypeConverter))]
	public ITemplate Template
	{
		get;
		set;
	}
}

This allows the following declaration:

	

Hope this helps!

Bookmark and Share
Posted: Mar 21 2010, 10:25 PM by Ricardo Peres | with no comments
Filed under: ,
ASP.NET MVC 2 Released

Get it while it’s hot from here. Also read the release notes.

Bookmark and Share
Introdução ao NHibernate on TechDays 2010

I’ve been working on the agenda for my presentation titled Introdução ao NHibernate that I’ll be giving on TechDays 2010, and I would like to request your assistance.

If you have any subject that you’d like me to talk about, you can suggest it to me. For now, I’m thinking of the following issues:

  • Domain Driven Design with NHibernate
  • Inheritance Mapping Strategies (Table Per Class Hierarchy, Table Per Type, Table Per Concrete Type, Mixed)
  • Mappings (hbm.xml, NHibernate Attributes, Fluent NHibernate, ConfORM)
  • Supported querying types (ID, HQL, LINQ, Criteria API, QueryOver, SQL)
  • Entity Relationships
  • Custom Types
  • Caching
  • Interceptors and Listeners
  • Advanced Usage (Duck Typing, EntityMode Map, …)
  • Other projects (NHibernate Validator, NHibernate Search, NHibernate Shards, …)
  • ASP.NET Integration
  • ASP.NET Dynamic Data Integration
  • WCF Data Services Integration

Comments?

Bookmark and Share
Microsoft TechDays 2010 Portugal

Once again, TechDays is at the door!

As you probably know, TechDays is Microsoft's annual event, which occurs on each country. This year, Luís Alves Martins (of Cloud Computing fame) gave me the oportunity to present one of my favorite subjects: NHibernate!

The presentation will be titled Introdução ao NHibernate. I will soon post more details, but, for now, if you live in Portugal, mark the days 20, 21 and 22 of April on your calendar, and join us there!

TechDays 2010 Portugal

Bookmark and Share
Three Ways To Create An Object

Enjoy!

Type type = typeof(StringBuilder);	//can be any type
ConstructorInfo ci = type.GetConstructor(new Type [ 0 ]);
Stopwatch watch = new Stopwatch();

watch.Start();
			
for (Int32 i = 0; i < 100; ++i)
{
	StringBuilder obj = Activator.CreateInstance(type) as StringBuilder;
}

Int64 time1 = watch.ElapsedTicks;

watch.Reset();

watch.Start();

for (Int32 i = 0; i < 100; ++i)
{
	StringBuilder obj = ci.Invoke(null) as StringBuilder;
}

Int64 time2 = watch.ElapsedTicks;

DynamicMethod m = new DynamicMethod(String.Empty, typeof(Object), null, type, true);
			
ILGenerator il = m.GetILGenerator();
il.Emit(OpCodes.Newobj, ci);
il.Emit(OpCodes.Ret);
Func<Object> creator = m.CreateDelegate(typeof(Func<Object>)) as Func<Object>;

watch.Reset();

watch.Start();

for (Int32 i = 0; i < 100; ++i)
{
	StringBuilder obj = creator() as StringBuilder;
}

Int64 time3 = watch.ElapsedTicks;

Bookmark and Share
Find Control that Caused a Postback

Sometimes there is the need to find the control that caused the postback from outside the event handler. The following code gives you just that:

public static class PageExtensions
{
	public static Control FindFiredControl(this Page page)
	{
		Control control = page;
		Boolean asyncPost = (page.Request.Form [ "__ASYNCPOST" ] == "true");
		String eventTarget = page.Request.Form [ "__EVENTTARGET" ];

		if (page.IsPostBack == true)
		{
			//check if the postback control is not a button
			if (String.IsNullOrEmpty(eventTarget) == false)
			{
				//all naming containers
				String [] parts = eventTarget.Split('$');
	
				foreach (String part in parts)
				{
					//find control on its naming container
					control = control.FindControl(part);
				}
			}
			else
			{
				//search all submitted form keys
				foreach (String key in page.Request.Form.AllKeys.Where(k => Char.IsLetter(k [ 0 ])).ToArray())
				{
					//all naming containers
					String [] parts = key.Split('$');

					//initialize control to page on each iteration
					control = page;

					foreach (String part in parts)
					{
						//find control on its naming container
						if ((part.EndsWith(".x")) || (part.EndsWith(".y")))
						{
							//ImageButton
							control = control.FindControl(part.Substring(0, part.Length - 2));
						}
						else
						{
							//other button type
							control = control.FindControl(part);
						}
					}
	
					if (control is IPostBackEventHandler)
					{
						if (((control is ScriptManager) || (control is ScriptManagerProxy)) && (asyncPost == true))
						{
							//ScriptManager/ScriptManagerProxy themselves never fire postback events
							continue;
						}
						else
						{
							//found firing event
							break;
						}
					}
	
					//clear control for next iteration
					control = null;
				}
			}
		}
	
		return (control);
	}
}
Bookmark and Share
ASP.NET Events

Here is the full list of all events that occur in an ASP.NET application, from the standard modules, to the page, master page, page controls and master page controls.

What When
HttpApplication.BeginRequest
HttpApplication.AuthenticateRequest
HttpApplication.PostAuthenticateRequest
HttpApplication.AuthorizeRequest
HttpApplication.PostAuthorizeRequest
HttpApplication.ResolveRequestCache
HttpApplication.PostResolveRequestCache
HttpApplication.MapRequestHandler
HttpApplication.PostMapRequestHandler
HttpApplication.AcquireRequestState
HttpApplication.PostAcquireRequestState
HttpApplication.PreRequestHandlerExecute
Page.FrameworkInitialize
Page.InitializeCulture
Page.OnPreInit
MasterPage.FrameworkInitialize
MasterPageControl.FrameworkInitialize
PageControl.FrameworkInitialize
MasterPageControl.OnInit
PageControl.OnInit
MasterPage.OnInit
Page.OnInit
Page.OnInitComplete
Page.LoadPageStateFromPersistenceMedium If IsPostBack
Page.LoadControlState If IsPostBack
MasterPageControl.LoadControlState If IsPostBack, RegisterRequiresControlState was called and control state contains elements
PageControl.LoadControlState If IsPostBack, RegisterRequiresControlState was called and control state contains elements
MasterPageControl.LoadViewState If IsPostBack and ViewState contains elements
PageControl.LoadViewState If IsPostBack and ViewState contains elements
Page.OnPreLoad
Page.OnLoad
MasterPage.OnLoad
MasterPageControl.OnLoad
PageControl.OnLoad
{PageControl|MasterPageControl}.OnCustomEvent If a custom event was fired on a control declared on the page/master page
{PageControl|MasterPageControl}.OnBubbleEvent If a custom event was fired on a control declared on the page/master page
{Page|MasterPage}.OnBubbleEvent If a custom event was fired on a control declared on the page/master page
Page.OnBubbleEvent If a custom event was fired
Page.OnLoadComplete
ClientCallbackControl.RaiseCallbackEvent If in a client callback asynchronous request
ClientCallbackControl.GetCallbackResult If in a client callback asynchronous request
Page.OnPreRender If not in an asynchronous postback
MasterPage.OnPreRender If not in an asynchronous postback
MasterPageControl.OnPreRender If Visible
PageControl.OnPreRender If Visible and not in an asynchronous postback
Page.OnPreRenderComplete If not in an asynchronous postback
Page.SaveControlState If not in an asynchronous postback and RegisterRequiresControlState is called for the page and control state contains additiona values
MasterPageControl.SaveControlState If not in an asynchronous postback and RegisterRequiresControlState is called for the master page control and control state contains additiona values
PageControl.SaveControlState If not in an asynchronous postback and RegisterRequiresControlState is called for the page control and control state contains additiona values
Page.SaveViewState If not in an asynchronous postback
MasterPage.SaveViewState If not in an asynchronous postback
MasterPageControl.SaveViewState If not in an asynchronous postback
PageControl.SaveViewState If not in an asynchronous postback
Page.SavePageStateToPersistenceMedium If not in an asynchronous postback
Page.OnSaveStateComplete If not in an asynchronous postback
Page.Render If not in an asynchronous postback
MasterPage.Render If not in an asynchronous postback
MasterPageControl.Render If Visible and not in an asynchronous postback
PageControl.Render If Visible and not in an asynchronous postback
Page.OnCommitTransaction If Transaction = Required or RequiresNew and a transaction was committed or no transaction was created
Page.OnAbortTransaction If Transaction = Required or RequiresNew and a transaction was rolled back
MasterPageControl.OnUnload
MasterPageControl.Dispose
PageControl.OnUnload
PageControl.Dispose
MasterPage.OnUnload
MasterPage.Dispose
Page.OnUnload
Page.Dispose
HttpApplication.PostRequestHandlerExecute
HttpApplication.ReleaseRequestState
HttpApplication.PostReleaseRequestState
HttpApplication.UpdateRequestCache
HttpApplication.PostUpdateRequestCache
HttpApplication.LogRequest
HttpApplication.PostLogRequest
HttpApplication.EndRequest
HttpApplication.PreSendRequestHeaders
HttpApplication.PreSendRequestContent
Bookmark and Share
Posted: Jan 04 2010, 04:33 PM by Ricardo Peres | with 6 comment(s)
Filed under: ,
ASP.NET Dynamic Data NHibernate Provider

My NHibernateDataSource was just a necessary step in order to build an ASP.NET Dynamic Data provider for NHibernate. I am pleased to say that it is now working! Like the NHibernateDataSource, it is only - for now - merely a proof of concept, it needs cleaning up and still misses the association metadata part, which means no links to associated entities, but list, edit, delete and insert are working fine.

If you want to try it, please download it and send me your feedback.

In order to use it, create a Dynamic Data Web Application project and change the name of the context class on the Global.asax.cs file:

model.RegisterContext(new NHibernateDataModelProvider(typeof(MyNHibernateContext)), new ContextConfiguration() { ScaffoldAllTables = true });

Then, on all of the ASPX files under the DynamicData folder, replace the EntityDataSource declaration for the NHibernateDataSource, keeping all of the properties. Add the NHibernateDataSource files to your project and add references to NHibernate and LINQ to NHibernate, from the NHContrib project, and that's it!

Bookmark and Share
NHibernateDataSource

I wrote a NHibernateDataSource, which can be used in ASP.NET web forms applications just like their counterparts EntityDataSource and LinqDataSource.

It requires a LINQ to NHibernate NHibernateContext-derived class which specifies the queryable entities. You can get it from the NHContrib site.

I have used code from Microsoft's LINQ samples, of which I talked about on a previous post, and you can get a precompiled assembly from there.

I have not implemented the InsertParameters, DeleteParameters and UpdateParameters properties, only the WhereParameters, but it shouldn't be too difficult.

Please note that this code is merely a proof of concept, it may have problems, and it is not optimized. If you find anything in it that should be improved, drop me a line. As usual, hope you find it useful!

Bookmark and Share
Using New ADO.NET Data Services Functionalities

In order to use the new functionalities (count, projections, server paging, for instance) supplied by version 1.5 of ADO.NET Data Services (see my previous post), you must explicitly enable them on the service side.

public static void InitializeService(DataServiceConfiguration config)
{
    config.EnableTypeConversion = true;
    config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    config.UseVerboseErrors = true;
    config.SetEntitySetAccessRule("*", EntitySetRights.All);
    config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
}

Note that you need to use the DataServiceConfiguration instead of the IDataServiceConfiguration interface, which was the one that the wizard previously declared.

Bookmark and Share
More Posts Next page »