Creating FK’s

Posted by Monty on February 4th, 2009

If you get the following error, when trying to export data from YAF:

sqlpubwiz

You might want to try running this script, to generate the create FK statements. Inconjuction with the drop FK statements, it will alow you to generate YAF scripts painlessly.


SELECT 'ALTER TABLE ' +  OBJECT_NAME(f.parent_object_id) + ' ADD CONSTRAINT '  + f.name + ' FOREIGN KEY (' + COL_NAME(fc.parent_object_id, fc.parent_column_id) + ') REFERENCES ' + OBJECT_NAME (f.referenced_object_id) + '(' + COL_NAME(fc.referenced_object_id, fc.referenced_column_id) + ')' FROM sys.foreign_keys AS f INNER JOIN sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id

It should give you an output like:


ALTER TABLE yaf_Choice ADD CONSTRAINT FK_yaf_Choice_yaf_Poll FOREIGN KEY (PollID) REFERENCES yaf_Poll(PollID)
ALTER TABLE yaf_Topic ADD CONSTRAINT FK_yaf_Topic_yaf_Poll FOREIGN KEY (PollID) REFERENCES yaf_Poll(PollID)
ALTER TABLE yaf_PollVote ADD CONSTRAINT FK_yaf_PollVote_yaf_Poll FOREIGN KEY (PollID) REFERENCES yaf_Poll(PollID)
ALTER TABLE yaf_AccessMask ADD CONSTRAINT FK_yaf_AccessMask_yaf_Board FOREIGN KEY (BoardID) REFERENCES yaf_Board(BoardID)
ALTER TABLE yaf_Active ADD CONSTRAINT FK_yaf_Active_yaf_Board FOREIGN KEY (BoardID) REFERENCES yaf_Board(BoardID)
ALTER TABLE yaf_BannedIP ADD CONSTRAINT FK_yaf_BannedIP_yaf_Board FOREIGN KEY (BoardID) REFERENCES yaf_Board(BoardID)
ALTER TABLE yaf_Category ADD CONSTRAINT FK_yaf_Category_yaf_Board FOREIGN KEY (BoardID) REFERENCES yaf_Board(BoardID)
ALTER TABLE yaf_Group ADD CONSTRAINT FK_yaf_Group_yaf_Board FOREIGN KEY (BoardID) REFERENCES yaf_Board(BoardID)
ALTER TABLE yaf_NntpServer ADD CONSTRAINT FK_yaf_NntpServer_yaf_Board FOREIGN KEY (BoardID) REFERENCES yaf_Board(BoardID)
ALTER TABLE yaf_Rank ADD CONSTRAINT FK_yaf_Rank_yaf_Board FOREIGN KEY (BoardID) REFERENCES yaf_Board(BoardID)
ALTER TABLE yaf_Registry ADD CONSTRAINT FK_yaf_Registry_yaf_Board FOREIGN KEY (BoardID) REFERENCES yaf_Board(BoardID)
ALTER TABLE yaf_Smiley ADD CONSTRAINT FK_yaf_Smiley_yaf_Board FOREIGN KEY (BoardID) REFERENCES yaf_Board(BoardID)
ALTER TABLE yaf_User ADD CONSTRAINT FK_yaf_User_yaf_Board FOREIGN KEY (BoardID) REFERENCES yaf_Board(BoardID)
ALTER TABLE yaf_User ADD CONSTRAINT FK_yaf_User_yaf_Rank FOREIGN KEY (RankID) REFERENCES yaf_Rank(RankID)
ALTER TABLE yaf_Active ADD CONSTRAINT FK_yaf_Active_yaf_User FOREIGN KEY (UserID) REFERENCES yaf_User(UserID)
ALTER TABLE yaf_CheckEmail ADD CONSTRAINT FK_yaf_CheckEmail_yaf_User FOREIGN KEY (UserID) REFERENCES yaf_User(UserID)
ALTER TABLE yaf_EventLog ADD CONSTRAINT FK_yaf_EventLog_yaf_User FOREIGN KEY (UserID) REFERENCES yaf_User(UserID)
ALTER TABLE yaf_Forum ADD CONSTRAINT FK_yaf_Forum_yaf_User FOREIGN KEY (LastUserID) REFERENCES yaf_User(UserID)
ALTER TABLE yaf_Message ADD CONSTRAINT FK_yaf_Message_yaf_User FOREIGN KEY (UserID) REFERENCES yaf_User(UserID)
ALTER TABLE yaf_PMessage ADD CONSTRAINT FK_yaf_PMessage_yaf_User1 FOREIGN KEY (FromUserID) REFERENCES yaf_User(UserID)
ALTER TABLE yaf_Topic ADD CONSTRAINT FK_yaf_Topic_yaf_User FOREIGN KEY (UserID) REFERENCES yaf_User(UserID)
ALTER TABLE yaf_Topic ADD CONSTRAINT FK_yaf_Topic_yaf_User2 FOREIGN KEY (LastUserID) REFERENCES yaf_User(UserID)
ALTER TABLE yaf_UserForum ADD CONSTRAINT FK_yaf_UserForum_yaf_User FOREIGN KEY (UserID) REFERENCES yaf_User(UserID)
ALTER TABLE yaf_UserGroup ADD CONSTRAINT FK_yaf_UserGroup_yaf_User FOREIGN KEY (UserID) REFERENCES yaf_User(UserID)
ALTER TABLE yaf_UserPMessage ADD CONSTRAINT FK_yaf_UserPMessage_yaf_User FOREIGN KEY (UserID) REFERENCES yaf_User(UserID)
ALTER TABLE yaf_WatchForum ADD CONSTRAINT FK_yaf_WatchForum_yaf_User FOREIGN KEY (UserID) REFERENCES yaf_User(UserID)
ALTER TABLE yaf_WatchTopic ADD CONSTRAINT FK_yaf_WatchTopic_yaf_User FOREIGN KEY (UserID) REFERENCES yaf_User(UserID)
ALTER TABLE yaf_Forum ADD CONSTRAINT FK_yaf_Forum_yaf_Category FOREIGN KEY (CategoryID) REFERENCES yaf_Category(CategoryID)
ALTER TABLE yaf_Active ADD CONSTRAINT FK_yaf_Active_yaf_Forum FOREIGN KEY (ForumID) REFERENCES yaf_Forum(ForumID)
ALTER TABLE yaf_Forum ADD CONSTRAINT FK_yaf_Forum_yaf_Forum FOREIGN KEY (ParentID) REFERENCES yaf_Forum(ForumID)
ALTER TABLE yaf_ForumAccess ADD CONSTRAINT FK_yaf_ForumAccess_yaf_Forum FOREIGN KEY (ForumID) REFERENCES yaf_Forum(ForumID)
ALTER TABLE yaf_NntpForum ADD CONSTRAINT FK_yaf_NntpForum_yaf_Forum FOREIGN KEY (ForumID) REFERENCES yaf_Forum(ForumID)
ALTER TABLE yaf_Topic ADD CONSTRAINT FK_yaf_Topic_yaf_Forum FOREIGN KEY (ForumID) REFERENCES yaf_Forum(ForumID)
ALTER TABLE yaf_UserForum ADD CONSTRAINT FK_yaf_UserForum_yaf_Forum FOREIGN KEY (ForumID) REFERENCES yaf_Forum(ForumID)
ALTER TABLE yaf_WatchForum ADD CONSTRAINT FK_yaf_WatchForum_yaf_Forum FOREIGN KEY (ForumID) REFERENCES yaf_Forum(ForumID)
ALTER TABLE yaf_Attachment ADD CONSTRAINT FK_yaf_Attachment_yaf_Message FOREIGN KEY (MessageID) REFERENCES yaf_Message(MessageID)
ALTER TABLE yaf_Forum ADD CONSTRAINT FK_yaf_Forum_yaf_Message FOREIGN KEY (LastMessageID) REFERENCES yaf_Message(MessageID)
ALTER TABLE yaf_Message ADD CONSTRAINT FK_yaf_Message_yaf_Message FOREIGN KEY (ReplyTo) REFERENCES yaf_Message(MessageID)
ALTER TABLE yaf_Topic ADD CONSTRAINT FK_yaf_Topic_yaf_Message FOREIGN KEY (LastMessageID) REFERENCES yaf_Message(MessageID)
ALTER TABLE yaf_Active ADD CONSTRAINT FK_yaf_Active_yaf_Topic FOREIGN KEY (TopicID) REFERENCES yaf_Topic(TopicID)
ALTER TABLE yaf_Forum ADD CONSTRAINT FK_yaf_Forum_yaf_Topic FOREIGN KEY (LastTopicID) REFERENCES yaf_Topic(TopicID)
ALTER TABLE yaf_Message ADD CONSTRAINT FK_yaf_Message_yaf_Topic FOREIGN KEY (TopicID) REFERENCES yaf_Topic(TopicID)
ALTER TABLE yaf_NntpTopic ADD CONSTRAINT FK_yaf_NntpTopic_yaf_Topic FOREIGN KEY (TopicID) REFERENCES yaf_Topic(TopicID)
ALTER TABLE yaf_Topic ADD CONSTRAINT FK_yaf_Topic_yaf_Topic FOREIGN KEY (TopicMovedID) REFERENCES yaf_Topic(TopicID)
ALTER TABLE yaf_WatchTopic ADD CONSTRAINT FK_yaf_WatchTopic_yaf_Topic FOREIGN KEY (TopicID) REFERENCES yaf_Topic(TopicID)
ALTER TABLE yaf_NntpForum ADD CONSTRAINT FK_yaf_NntpForum_yaf_NntpServer FOREIGN KEY (NntpServerID) REFERENCES yaf_NntpServer(NntpServerID)
ALTER TABLE yaf_NntpTopic ADD CONSTRAINT FK_yaf_NntpTopic_yaf_NntpForum FOREIGN KEY (NntpForumID) REFERENCES yaf_NntpForum(NntpForumID)
ALTER TABLE yaf_ForumAccess ADD CONSTRAINT FK_yaf_ForumAccess_yaf_AccessMask FOREIGN KEY (AccessMaskID) REFERENCES yaf_AccessMask(AccessMaskID)
ALTER TABLE yaf_UserForum ADD CONSTRAINT FK_yaf_UserForum_yaf_AccessMask FOREIGN KEY (AccessMaskID) REFERENCES yaf_AccessMask(AccessMaskID)
ALTER TABLE yaf_ForumAccess ADD CONSTRAINT FK_yaf_ForumAccess_yaf_Group FOREIGN KEY (GroupID) REFERENCES yaf_Group(GroupID)
ALTER TABLE yaf_UserGroup ADD CONSTRAINT FK_yaf_UserGroup_yaf_Group FOREIGN KEY (GroupID) REFERENCES yaf_Group(GroupID)
ALTER TABLE yaf_UserPMessage ADD CONSTRAINT FK_yaf_UserPMessage_yaf_PMessage FOREIGN KEY (PMessageID) REFERENCES yaf_PMessage(PMessageID)

Deleting FK’s from MSSQL

Posted by Monty on January 30th, 2009

SQL SERVER – 2005 – Find Tables With Foreign Key Constraint in Database

via SQL SERVER – 2005 – Find Tables With Foreign Key Constraint in Database « Journey to SQL Authority with Pinal Dave.

This script is a godsend. Basically, we had a botched install of Yet Another Forum, and we had to delete it (YAY!), but because of the FK constraints, we couldnt do a simple “DROP TABLE *” on the database, and nor could we just drop the database.

So I came up with this script that generated the SQL Script for me, based on the above:


SELECT 'ALTER TABLE ' +  OBJECT_NAME(f.parent_object_id) + ' DROP CONSTRAINT [' + f.name + ']' AS Moo, f.name AS ForeignKey,
OBJECT_NAME(f.parent_object_id) AS TableName,
COL_NAME(fc.parent_object_id,
fc.parent_column_id) AS ColumnName,
OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
COL_NAME(fc.referenced_object_id,
fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id

Can be refined alot better, but works. The resulting script is as follows – note I added the “drop table” by hand:

ALTER TABLE yaf_Topic DROP CONSTRAINT [FK_yaf_Topic_yaf_Forum]
ALTER TABLE yaf_Active DROP CONSTRAINT [FK_yaf_Active_yaf_Forum]
ALTER TABLE yaf_ForumAccess DROP CONSTRAINT [FK_yaf_ForumAccess_yaf_Forum]
ALTER TABLE yaf_WatchForum DROP CONSTRAINT [FK_yaf_WatchForum_yaf_Forum]
ALTER TABLE yaf_NntpForum DROP CONSTRAINT [FK_yaf_NntpForum_yaf_Forum]
ALTER TABLE yaf_UserForum DROP CONSTRAINT [FK_yaf_UserForum_yaf_Forum]
ALTER TABLE yaf_Forum DROP CONSTRAINT [FK_yaf_Forum_yaf_Forum]
ALTER TABLE yaf_Forum DROP CONSTRAINT [FK_yaf_Forum_yaf_Message]
ALTER TABLE yaf_Topic DROP CONSTRAINT [FK_yaf_Topic_yaf_Message]
ALTER TABLE yaf_Attachment DROP CONSTRAINT [FK_yaf_Attachment_yaf_Message]
ALTER TABLE yaf_Message DROP CONSTRAINT [FK_yaf_Message_yaf_Message]
ALTER TABLE yaf_Topic DROP CONSTRAINT [FK_yaf_Topic_yaf_Poll]
ALTER TABLE yaf_Choice DROP CONSTRAINT [FK_yaf_Choice_yaf_Poll]
ALTER TABLE yaf_PollVote DROP CONSTRAINT [FK_yaf_PollVote_yaf_Poll]
ALTER TABLE yaf_Forum DROP CONSTRAINT [FK_yaf_Forum_yaf_Topic]
ALTER TABLE yaf_Message DROP CONSTRAINT [FK_yaf_Message_yaf_Topic]
ALTER TABLE yaf_Topic DROP CONSTRAINT [FK_yaf_Topic_yaf_Topic]
ALTER TABLE yaf_Active DROP CONSTRAINT [FK_yaf_Active_yaf_Topic]
ALTER TABLE yaf_WatchTopic DROP CONSTRAINT [FK_yaf_WatchTopic_yaf_Topic]
ALTER TABLE yaf_NntpTopic DROP CONSTRAINT [FK_yaf_NntpTopic_yaf_Topic]
ALTER TABLE yaf_Forum DROP CONSTRAINT [FK_yaf_Forum_yaf_User]
ALTER TABLE yaf_Message DROP CONSTRAINT [FK_yaf_Message_yaf_User]
ALTER TABLE yaf_Topic DROP CONSTRAINT [FK_yaf_Topic_yaf_User]
ALTER TABLE yaf_Topic DROP CONSTRAINT [FK_yaf_Topic_yaf_User2]
ALTER TABLE yaf_Active DROP CONSTRAINT [FK_yaf_Active_yaf_User]
ALTER TABLE yaf_CheckEmail DROP CONSTRAINT [FK_yaf_CheckEmail_yaf_User]
ALTER TABLE yaf_PMessage DROP CONSTRAINT [FK_yaf_PMessage_yaf_User1]
ALTER TABLE yaf_WatchForum DROP CONSTRAINT [FK_yaf_WatchForum_yaf_User]
ALTER TABLE yaf_WatchTopic DROP CONSTRAINT [FK_yaf_WatchTopic_yaf_User]
ALTER TABLE yaf_UserGroup DROP CONSTRAINT [FK_yaf_UserGroup_yaf_User]
ALTER TABLE yaf_UserForum DROP CONSTRAINT [FK_yaf_UserForum_yaf_User]
ALTER TABLE yaf_UserPMessage DROP CONSTRAINT [FK_yaf_UserPMessage_yaf_User]
ALTER TABLE yaf_EventLog DROP CONSTRAINT [FK_yaf_EventLog_yaf_User]
ALTER TABLE yaf_User DROP CONSTRAINT [FK_yaf_User_yaf_Rank]
ALTER TABLE yaf_Category DROP CONSTRAINT [FK_yaf_Category_yaf_Board]
ALTER TABLE yaf_Rank DROP CONSTRAINT [FK_yaf_Rank_yaf_Board]
ALTER TABLE yaf_AccessMask DROP CONSTRAINT [FK_yaf_AccessMask_yaf_Board]
ALTER TABLE yaf_Active DROP CONSTRAINT [FK_yaf_Active_yaf_Board]
ALTER TABLE yaf_User DROP CONSTRAINT [FK_yaf_User_yaf_Board]
ALTER TABLE yaf_BannedIP DROP CONSTRAINT [FK_yaf_BannedIP_yaf_Board]
ALTER TABLE yaf_Group DROP CONSTRAINT [FK_yaf_Group_yaf_Board]
ALTER TABLE yaf_NntpServer DROP CONSTRAINT [FK_yaf_NntpServer_yaf_Board]
ALTER TABLE yaf_Smiley DROP CONSTRAINT [FK_yaf_Smiley_yaf_Board]
ALTER TABLE yaf_Registry DROP CONSTRAINT [FK_yaf_Registry_yaf_Board]
ALTER TABLE yaf_ForumAccess DROP CONSTRAINT [FK_yaf_ForumAccess_yaf_Group]
ALTER TABLE yaf_UserGroup DROP CONSTRAINT [FK_yaf_UserGroup_yaf_Group]
ALTER TABLE yaf_UserPMessage DROP CONSTRAINT [FK_yaf_UserPMessage_yaf_PMessage]
ALTER TABLE yaf_ForumAccess DROP CONSTRAINT [FK_yaf_ForumAccess_yaf_AccessMask]
ALTER TABLE yaf_UserForum DROP CONSTRAINT [FK_yaf_UserForum_yaf_AccessMask]
ALTER TABLE yaf_NntpForum DROP CONSTRAINT [FK_yaf_NntpForum_yaf_NntpServer]
ALTER TABLE yaf_NntpTopic DROP CONSTRAINT [FK_yaf_NntpTopic_yaf_NntpForum]
ALTER TABLE yaf_Forum DROP CONSTRAINT [FK_yaf_Forum_yaf_Category]

drop table dbo.yaf_AccessMask
drop table dbo.yaf_Active
drop table dbo.yaf_Attachment
drop table dbo.yaf_BannedIP
drop table dbo.yaf_Board
drop table dbo.yaf_Category
drop table dbo.yaf_CheckEmail
drop table dbo.yaf_Choice
drop table dbo.yaf_EventLog
drop table dbo.yaf_Forum
drop table dbo.yaf_ForumAccess
drop table dbo.yaf_Group
drop table dbo.yaf_Mail
drop table dbo.yaf_Message
drop table dbo.yaf_NntpForum
drop table dbo.yaf_NntpServer
drop table dbo.yaf_NntpTopic
drop table dbo.yaf_PMessage
drop table dbo.yaf_Poll
drop table dbo.yaf_PollVote
drop table dbo.yaf_Rank
drop table dbo.yaf_Registry
drop table dbo.yaf_Replace_Words
drop table dbo.yaf_Smiley
drop table dbo.yaf_Topic
drop table dbo.yaf_User
drop table dbo.yaf_UserForum
drop table dbo.yaf_UserGroup
drop table dbo.yaf_UserPMessage
drop table dbo.yaf_WatchForum
drop table dbo.yaf_WatchTopic
drop view dbo.yaf_vaccess

Microsoft.WebApplication.targets

Posted by Monty on January 28th, 2009

I seem to be getting quite a few hits regarding Microsoft.WebApplication.targets file, and im guessing its because people’s copies are missing, so I have decided to attach the file to this post. Enjoy!

Linky

Extending Nettiers Part 2 – Adding an OnItemCommand

Posted by Monty on November 21st, 2008

A few days ago, I decided to try to extend the Repeater Control, by adding an OnItemCommand, like the System.Web.UI.WebControl. Simple I thought. Shouldnt be that hard I thought.

I couldnt have been more wrong.

I have learned alot with the whole experience. I have learned about event bubbling, the way that events get passed up the control tree till they are handled by their parents. Iv learned about the way that items that are nested will need to be databound for the event to be fired, even if the data is being shown on the page, you still have to explicitly call DataBind(); And I got some help from a random guy (who works for telerik!) on StackOverflow, thanks!

Basically, this is the way it works. When a user hits a button (Like a <asp:button) on the page, it will bubble up (OnBubbleEvent) on the ITemplate (In this case, the actual type of the ItemRepeater). That will do its magic, work out if its a CommandEventArgs, if it is, then bubble it up:


protected override bool OnBubbleEvent(object source, EventArgs e)
{
if (e is CommandEventArgs)
{
RepeaterCommandEventArgs args = new RepeaterCommandEventArgs(this, source, (CommandEventArgs) e);
base.RaiseBubbleEvent(this, args);
return true;
}
return false;
}

Taken from System.Web.UI.WebControls.RepeaterItem.OnBubbleEvent(object source, EventArgs e);

From there, the Repeater will intercept that, then process it:

private static readonly object EventItemCommand = new object();

protected override bool OnBubbleEvent(object sender, EventArgs e)
{
bool flag = false;
if (e is RepeaterCommandEventArgs)
{
this.OnItemCommand((RepeaterCommandEventArgs)e);
flag = true;
}
return flag;
}

protected virtual void OnItemCommand(RepeaterCommandEventArgs e)
{
RepeaterCommandEventHandler handler = (RepeaterCommandEventHandler)base.Events[EventItemCommand];
if (handler != null)
{
handler(this, e);
}
}

public event RepeaterCommandEventHandler ItemCommand
{
add
{
base.Events.AddHandler(EventItemCommand, value);
}
remove
{
base.Events.RemoveHandler(EventItemCommand, value);
}
}

This is where the fun starts. First off, in the RepeaterItem source code, you cannot call:

RepeaterCommandEventArgs args = new RepeaterCommandEventArgs(<strong>this</strong>, source, (CommandEventArgs) e);
base.RaiseBubbleEvent(this, args);

because this refers to a RepeaterItem, which, in my case, it is not because its a Nettiers generated RepeaterItem. So you have to go off and create your own CommandEventArgs. If you create your own EventArgs, the event handler RepeaterCommandEventHandler wont work, because its not of the type RepeaterCommandEventArgs. Which is a pain in the arse!

Once you have created the EventArgs and the event handler though, its fairly simple from there – you just modify the Reflector’ed code (From the RepeaterControl), to get it to handle your custom Repeater Item’s event, and not the RepeateItem default event which you cant even call!

But your not done! I found out that the command wont get called when someone clicky’s on it, because you havnt called DataBind(); on the control, which explains some … oddities I spotted in the code when I was digging around inside the Repeater – I kept finding calls to “EnsureDataBound()” – which is called OnPreRender:

Note: I will provide code samples and Nettiers templates very soon, as soon as I have integrated my changes into Nettiers!

Introduction to CSS Adapters – Label Control

Posted by Monty on November 5th, 2008

CSS Adapters in .net are rarely used, even though they are really powerful and can fix things like xhtml validation errors. This very quick sample will show you how to replace the <span> tags with a <div>

Create a class file, something like “LabelOverride.cs”, and put in the following:


using System.Web.UI;

namespace CSSAdapterTest
{
public class LabelOverride : System.Web.UI.WebControls.Adapters.WebControlAdapter
{
protected override void RenderBeginTag(HtmlTextWriter writer)
{
writer.RenderBeginTag(HtmlTextWriterTag.Div);
}
protected override void RenderEndTag(HtmlTextWriter writer)
{
writer.RenderEndTag();
}
}
}

Create a folder in the web application called “App_Browsers”, and create a .browsers file called “CSSAdapter.browser”, and enter in the following:


<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.WebControls.Label"
adapterType="CSSAdapterTest.LabelOverride" />
</controlAdapters>
</browser>
</browsers>

This basically tells asp.net to override the controlType’s renderer with the one you have specified.

Once you have done this, and when you build your application, all <span>’s will disappear and be replaced with <div>’s!

Extending NetTiers part 1

Posted by Monty on October 15th, 2008

Im a very big fan of NetTiers – its an excellent product, an amazing piece of code created by the community, it rapidly speeds up development and basically gets rid of all the boring faff that you have to do to create databases – all that select, insert and update statements etc etc etc.

I would like to do some minor improvements to the project thoguh – iv already experimented with ILMERGE’ing all of the Microsoft.Patterns dll’s into one (So you dont have 500 DLLs referenced in each project, and speeds up deployment). One thing id like to detail on this blog is how to implement a SeperatorTemplate (ala System.Web.WebControls.Repeater) on one of the generated UI Component’s repeaters…

For this demo, im going to be using the Nettiers 2.3.0 beta 1 release…

Firstly, to find out the actual code to include a SeperatorTemplate, by our good friend the Reflector has revealed that you need to create a property and an accessor for it like the following:

	private ITemplate m_seperatorTemplate;

	[Browsable(false)]
	[TemplateContainer(typeof(WebsiteItem))]
	[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
	public ITemplate SeperatorTemplate
	{
		get { return m_seperatorTemplate; }
		set { m_seperatorTemplate = value; }
	}

(Side note – I know that prefixing member variables with m_ is a bad practice, but I want to keep to the standards of the NetTiers code, because in my opinion, having 2 coding standards is worse than having one “bad” one)

Once you have created this property, all you have to do is create the seperator when it creates the child controls, in CreateChildControls, replace the following:

	if (m_itemTemplate != null &amp;amp;amp;amp;&amp;amp;amp;amp; (pos % 2) == 0)
	{
		m_itemTemplate.InstantiateIn(container);
	}

with:

	if (m_itemTemplate != null &amp;amp;amp;amp;&amp;amp;amp;amp; (pos % 2) == 0)
	{
		m_itemTemplate.InstantiateIn(container);
		m_seperatorTemplate.InstantiateIn(container);
	}

What this basically does, is instead of just creating the template, it will create teh template AND the seperator template underneath it. You can fiddle this around to how you want. Just as a side note, you will want to add the m_seperatorTemplate’s instantiator in the 2 other references a few lines down where it creates the alternating item style and the itemtemplate (if there is no alternate provided).

Once you have done this change, a quick check of the page, and it seems to work fine and exactly how I had planned. The next step is to change the Nettiers codesmith project so this gets done automatically, and for every repeater in the project.

By looking at where the source file is living, and a lil experimenting, you have to change both TableRepeater.cst and ViewRepeater.cst that lives in the WebLibrary/UI directory, like the following:

        /// <summary>
        /// Gets or sets the Seperator Template
        /// </summary>
        [Browsable(false)]
        [TemplateContainer(typeof(<%=entityItem%>))]
        [PersistenceMode(PersistenceMode.InnerDefaultProperty)]
        public ITemplate SeperatorTemplate
        {
            get { return m_seperatorTemplate; }
            set { m_seperatorTemplate = value; }
        }

Note the replacing of the type with <%=entityItem%> so it automagically generates this for all types.

A small improvement on the code above (Check to see that a Seperator template has actually been set!) when inserting, and your CreateChildControls should look something like this:

	/// <summary>
	/// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.
	/// </summary>
	protected override int CreateChildControls(System.Collections.IEnumerable dataSource, bool dataBinding)
	{
	 int pos = 0;

	 if (dataBinding)
	 {
		//Instantiate the Header template (if exists)
		if (m_headerTemplate != null)
		{
			Control headerItem = new Control();
			m_headerTemplate.InstantiateIn(headerItem);
			Controls.Add(headerItem);
		}
		if (dataSource != null)
		{
			foreach (object o in dataSource)
			{
					<%=entityName%> entity = o as <%=entityName%>;
					<%=entityItem%> container = new <%=entityItem%>(entity);

					if (m_itemTemplate != null &amp;amp;&amp;amp; (pos % 2) == 0)
					{
						m_itemTemplate.InstantiateIn(container);

						if (m_seperatorTemplate != null)
						{
							m_seperatorTemplate.InstantiateIn(container);
						}
					}
					else
					{
						if (m_altenateItemTemplate != null)
						{
							m_altenateItemTemplate.InstantiateIn(container);

							if (m_seperatorTemplate != null)
							{
								m_seperatorTemplate.InstantiateIn(container);
							}

						}
						else if (m_itemTemplate != null)
						{
							m_itemTemplate.InstantiateIn(container);

							if (m_seperatorTemplate != null)
							{
								m_seperatorTemplate.InstantiateIn(container);
							}
						}
						else
						{
							// no template !!!
						}
					}
					Controls.Add(container);

					container.DataBind();

					pos++;
			}
		}
		//Instantiate the Footer template (if exists)
		if (m_footerTemplate != null)
		{
			Control footerItem = new Control();
			m_footerTemplate.InstantiateIn(footerItem);
			Controls.Add(footerItem);
		}

	}

		return pos;
	}

I want my .ForEach(System.Action)!

Posted by Monty on October 14th, 2008

Well I was adding things to a dictionary today (Because im lazy, I have to store 2 values, and I really cant be bothered with creating a class just for that), and I wanted to run a ForEach(System.Action<T>) on it, because I like doing that on System.Collections.Generic.List<t> – it works well, so why change what you know?

But, it turns out Dictionary<TKey, TValue> dosent have a .ForEach. It implements IEnumerable, but it dosent have support for the .ForEach, which is rather strange, since they both do the same thing, but it dosent have the Action<T> method. So I did some digging, and found that .ForEach is a method that belongs to List<T>, and its pretty much the only way to do it (There is a System.Array.Foreach(T[] array, Action<T>) method, but that dosent work with a dictionary.

What I see happening is me extending Dictionary<TKey, TValue> to add a .ForEach (And the other functions that are missing from it, in my opinion at least), because I think that since it implements IEnumerable<T>, it should support .ForEach.

MS Build – “Microsoft.WebApplication.targets” was not found.

Posted by Monty on July 22nd, 2008

This is a stupid error, an oversight by Microsoft. As far as I can tell, you can ONLY install the Web Application pack for vs2005 if you have VS installed – you cant install it on a build server, which is nice and “fun”.

A solution is to just create the directory structure it asks for -

C:\Program Files\MSBuild\Microsoft\VisualStudio\v8.0\WebApplications\

And copy over the files from your own copy. I don’t know why Microsoft did it this way, but its criminally retarded.

Edit – You can now download the file from here.

Abstraction Layer

Posted by Monty on July 4th, 2008

Well here at my new place of work, after only being here for 5 weeks (I think), we had a company meeting in Brighton, and sofar its been quite well, but I guess I have to, as is my prerogative, complain about something.

Its about the information in the meeting, basically, its all interesting on a level, but totally useless to me. No offence to anyone, but I don’t particularly care how the design team is doing, or how much revenue we have coming in, or we lost this or that project – I know its all company information, and I work for the company, so I should be interested, but unfortunately, im not.

Joel on Software calls it the “Developer Abstraction Layer” – basically, I shouldn’t be fussed with any other information apart from what I need to get my program running. I dont need to know about how we missed the 5th Q targets for 34.6% of the projects last year, its fascinating, so is the fact that sharks are the only animal that dont get cancer. But, both facts are totally useless to me at work, so id rather not know it.

Im not saying I dont want to get involved at all – give me tidbits, then if I dont ask for more information, dont take it personally. I know it sounds really harsh, but to be really honest, im not that fussed with office politics etc, I just want to sit down, write damn good code, and be proud of it. Sometimes, if I am really passionate about something, I will get involved, or if I know of a different way of doing things, then I will voice my opinion. But in circumstances where, in a company meeting, loads of people tell me stuff that will not impact my work, and being forced to sit through that for a morning, thats just a waste of time in my opinion.

I have a feeling if my boss read this tomorrow morning, he will fire me. Good thing he dosent have his laptop with him.

Consider if you actually need a variable…

Posted by Monty on June 16th, 2008

Take this scenario, you need to call a function, so you do the following:

I basically needed to call GetCustomAttribute(true) (if you know a better way to check custom attributes, please let me know!). But then I had an epiphany. Do I really need the trace and frame objects, or can I just do the following:

Which does exactly the same thing, but is shorter, and is easier to read and follow!

I love simplicitiy.


Copyright © 2007-2010 Muntedhar Alhakim. All rights reserved.