Head.SmackOnTable();

Contains Nuts.

Archive for the ‘asp.net’ tag

Deleting FK’s from MSSQL

without comments

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

Written by Monty

January 30th, 2009 at 4:34 pm

Microsoft.WebApplication.targets

with 2 comments

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

Written by Monty

January 28th, 2009 at 5:34 pm

Posted in .NET

Tagged with , ,

Extending Nettiers Part 2 – Adding an OnItemCommand

without comments

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!

Written by Monty

November 21st, 2008 at 8:10 pm

Introduction to CSS Adapters – Label Control

without comments

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!

Written by Monty

November 5th, 2008 at 1:53 pm

Extending NetTiers part 1

without comments

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;
	}

Written by Monty

October 15th, 2008 at 7:03 pm

I want my .ForEach(System.Action)!

with one comment

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.

Written by Monty

October 14th, 2008 at 5:38 pm

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

with 2 comments

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.

Written by Monty

July 22nd, 2008 at 10:13 am

Posted in .NET

Tagged with , , , , ,

Another way to do user based security

with one comment

This is in response to a post by Anas Ghanem – regarding doing Session checks in Page Loads, and asks for a better way to do things – in my opinion there is.

Instead of doing:

public class AdminSecuredPage : System.Web.UI.Page
{
    public AdminSecuredPage()
    {}
    protected override void OnInit(EventArgs e)
    {
        // if the user is not Admin , redirect to Login Page
        if (Session["AdminUser"] == null)
            Response.Redirect("~/login.aspx");
        // this needed to initialize its base page class
        base.OnInit(e);
    }
}

You really should be doing:

image

But, you can further extend this by inherting from a parent base page, like so:

public class BasePage : System.Web.UI.Page
{
    public void RequireRole (String Role)
    {
        if (!User.IsInRole(Role))
        {
            Response.Redirect("~/Login.aspx");
        }
    }

    public void RequireAdministrator()
    {
        RequireRole("Administrator");
    }
}

And then you do the following in the page:

public partial class _Default : BasePage
{
    protected void Page_Load(object sender, EventArgs e)
    {
        RequireRole("Administrator");

        // OR

        RequireAdministrator();
    }
}

I think this is a much more elegant way of doing things, plus you are DRY compatible, since you only have to change one url to redirect to.

Written by Monty

May 8th, 2008 at 1:22 am

Posted in .NET

Tagged with ,

Refactoring Made Easy with Resharper 4.0

without comments

Yes, yes, I know that Resharper 4.0 is still in the pre beta crappyness muchos error stage:

image

But I just love Resharper too much, its the best tool around for speeding up development with Visual Studio. If you don’t have it, I suggest you go grab it now!

Anyway, back to my point with refactoring. I am writing a simple website (maybe with facebook capabilities, not sure yet) to display random quotes from GLaDOS – the senile deranged computer from "Portals" – I’m sorry if you don’t like her, I think she’s great, with excellent quotes such as

The Enrichment Center promises to always provide a safe testing environment. In dangerous testing environments, the Enrichment Center promises to always provide useful advice. For instance, the floor here will kill you. Try to avoid it.

And my favourite:

Did you know you can donate one or all of your vital organs to the Aperture Science Self Esteem Fund for Girls? It’s true!

Anyway! Keep going off a tangent. Resharper speeds up development of an application, and the way I seem to work, is I write the code, then refactor it to make it all shiny and proper. We go from this:

image

To this:

image

Via:

image

And other assorted Resharper menu items – the quickest (I find) is to use Control-Shift-R which will allow you to dynamically use a "Refactor this" menu that will pop up, and give you only the valid things you can do with Resharper (instead of a very large list with things greyed out, like in the menu).

Im currently running Resharper Nightly build #783 – it dosent seem too bad, but it still has errors. Unlike Derik, I cant leave Resharper (arguably the love of my life) alone, I want to feel her up and touch her inappropriately. Im not that fussed by the fact that she doesn’t have manners, or farts uncontrollably in bed, I still love her.

Written by Monty

April 28th, 2008 at 1:53 am

Posted in .NET,Bad Humour,Misc

Tagged with ,

Increasing Productivity with Resharper

without comments

For those people who rely on //TODO: Comments in their code, you should get Resharper! It will greatly improve how you can see TODO statements, among other things:

Todo Explorer

You can customise these options in the Resharper options page:

image

And you can edit the existing ones:

image

It actually works with files you dont even have open, unlike Visual Studio .NET’s Task list – great for those large projects you have!

If you dont have Resharper, I suggest you go grab it.

Technorati Tags: , ,

Written by Monty

September 9th, 2007 at 4:00 am

Posted in .NET

Tagged with , , ,