Saturday, October 04, 2008

Getting MVC setup

This is all about getting MVC Preview 5 running: http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=16775

ASP.NET Project page: http://www.asp.net/mvc/

Had a bit of trouble getting MVC setup. A nasty little bugger going by the name of "Cannot load assembly ..." etc. You know the score.

One post on forums.asp.net sorted it all out:

http://forums.asp.net/p/1314519/2596828.aspx

I short, do the following:

Go to: C:\Documents and Settings\All Users\Start Menu\Programs\Microsoft\Microsoft Visual Studio 2008\Visual Studio Tools

Run: Visual Studio 2008 Command Prompt

Go to: C:\Program Files\Microsoft ASP.NET\ASP.NET MVC CodePlex Preview 5\Assemblies

Type:
C:\Program Files\Microsoft ASP.NET\ASP.NET MVC CodePlex Preview 5\Assemblies>gacutil -if System.Web.Routing.dll

And:
C:\Program Files\Microsoft ASP.NET\ASP.NET MVC CodePlex Preview 5\Assemblies>gacutil -if System.Web.Abstractions.dll

That should install the DLL's into the GAC (Global Assembly Cache) and cause .NET 3.5 to find them suitably.

Thursday, August 28, 2008

Release Mode missing

I recently realised, after a long time of not caring, that there are two ways to create a web project, with only one allowing Release Mode compilation.

Release Mode allowed: File -> New -> Project -> Visual C# -> Web -> ASP.NET Web Application

Only Debug Mode allowed: File -> New -> Website

Of course, from the command line, both of these options are available, as the options taken when creating any project are simply preset instructions for the compiler switches.

However, I feel it's important to note that only in Release Mode can the source of the website be compiled into a single DLL.

Reference: http://forums.asp.net/p/1053679/1532732.aspx#1532732

Friday, June 20, 2008

Getting ASP.NET Authentication in SQL Working

Firstly, you could go here, which helped me: http://weblogs.asp.net/scottgu/archive/2005/08/25/423703.aspx

Otherwise, just go to: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727

Run the aspnet_regsql.exe and following through the Next button.

If you want to setup a connection to your local machine running sql express, be sure to enter <machinename>\<sqlserver> for example: MATTSMACHINE\SQLEXPRESS

Everything should now be setup.

The next bit is optional, but I like to go to: http://msdn.microsoft.com/en-us/library/cc467894.aspx

Get the latest build of the Microsoft Enterprise Library. The setup is fairly simple, just install and follow the instructions for setting up the web.config and connection strings for allowing the data access layer. This will provide easy to use connection pooling and everything you need for single command SQL execution on your db.

The important entries in your web.config file should be:

<configSections>
<section name="dataConfiguration"...
...
</configSections>
<connectionStrings>
<add name="chopDatabaseConnection" providerName="System.Data.SqlClient"...
...
<dataConfiguration defaultDatabase="chopDatabaseConnection"/>

And you're away!

You might also want to read this:

Friday, May 23, 2008

Slapdash - Putting feeds on your page the easy way

I wanted to read RSS into a DataSet but found that when loading the XML from, for example, a community server feed I would often get a 'column already exists'. This was because the feed used namespaces which causes elements to be declared like this: <slash:comment>

There are two solutions to this. First, write an XSLT to parse out the stuff I don't want. Second, run over the raw XML myself and filter it. I wanted to go with the second, because writing XSLT for every customised RSS, ATOM, etc feed that my front end developers might want to use didn't appeal - I just wanted to be able to load the RSS into a DataSet. However, then I found some code which seemed to work: http://www.aspcode.net/Updated-RSS-reader-class-dealing-with-already-belongs-error.aspx

The one problem I had was that the code did not seem to know when an element like <enclosure/> did not have a closing tag following it. I have fixed this code and present it below. I have used it to load the header information and each item entry in the RSS feed into a couple of repeaters, for quick databinding, so that I can provide a simple data layout for my front end designer to work with. He can then style this anyway he likes and I can even wrap the items table in a DataView to sort and filter it by any combination of fields in the feed. Of course, because this uses a DataSet, I could even merge other feeds into it.

Many thanks to, er, admin(?), for writing the original - you really have helped me a lot!...

    protected void Page_Load(object sender, EventArgs e)
{
DataSet set = new DataSet();
XmlTextReader xmlRdr = new XmlTextReader("http://stuff.tv/blogs/cool/rss.aspx");
XmlDocument doc = new XmlDocument();
doc.Load(xmlRdr);

set = GetRSSDataSet("http://stuff.tv/blogs/cool/rss.aspx");

headerRepeater.DataSource = set.Tables[1];
itemsRepeater.DataSource = set.Tables[2];

DataBind();
}

public DataSet GetRSSDataSet(string m_strAdress)
{
DataSet m_ds = new DataSet();

System.Xml.XmlTextReader oXml = new System.Xml.XmlTextReader(m_strAdress);
oXml.WhitespaceHandling = System.Xml.WhitespaceHandling.None;
System.Text.StringBuilder oBuilder = new StringBuilder();

bool fContinue = oXml.Read();
while (fContinue)
{
string sName = oXml.Name.Replace(":", "_");
bool isClosed = oXml.IsEmptyElement;
if (oXml.NodeType == System.Xml.XmlNodeType.Element)
{
//Add the element...
oBuilder.Append("&lt;" + sName);
if (oXml.HasAttributes)
{
while (oXml.MoveToNextAttribute())
{
sName = oXml.Name.Replace(":", "_");
oBuilder.AppendFormat(" " + sName + "=\"" + oXml.Value + "\"");
}
}
if (isClosed)
oBuilder.Append("/");
oBuilder.Append("&gt;");
}
else if (oXml.NodeType == System.Xml.XmlNodeType.Text)
{
oBuilder.Append(System.Web.HttpUtility.HtmlEncode(oXml.Value));
}
else if (oXml.NodeType == System.Xml.XmlNodeType.EndElement)
{
oBuilder.Append("&lt;/" + sName + "&gt;");
}

fContinue = oXml.Read();
}
oXml.Close();

string sXmlResult = oBuilder.ToString();


m_ds = new DataSet();
System.IO.StringReader oStringReader = new System.IO.StringReader(sXmlResult);
try
{
m_ds.ReadXml(oStringReader, System.Data.XmlReadMode.Auto);
}
catch (Exception ex)
{
m_ds = null;
}
if (oStringReader != null)
oStringReader.Close();
if (oXml != null)
oXml.Close();
return m_ds.Tables.Count == 0 ? null : m_ds;
}
 [EDIT: 2008-06-20] I have a .NET3.5 new and improved version of this, which allows multiple feeds and optional sorting - I'll post this later.
[EDIT: 2009-02-19] Sorry for not having posted the replacement of this code.  I will, when I find it.  A lot has happened since the original posting.  

Tuesday, April 01, 2008

How to Auto-Create Stored Procedures

Use this script. I make no guarantees on it's solidity, but it has been useful. It will try to execute the CREATE PROCEDURE commands it executes, so comment those out if you want to run them manually.

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
-- Author: Matthew Webster
-- Create date: 2007-03-20
-- Description: Automatically creates stored procedures for insert, update and delete functions
ALTER PROCEDURE [dbo].[Cms_CreateAuto_Procs]
@author nvarchar(250),
@tableName varchar(8000)
AS
BEGIN
SET NOCOUNT ON;

--declare @tableName nvarchar(50)
--set @tableName = 'editorialtypegroup'
--declare @author nvarchar(50)
--set @author = 'Matthew Webster'

declare @insert varchar(8000)
declare @update varchar(8000)
declare @delete varchar(8000)

declare @key varchar(8000)
declare @fields varchar(8000)
declare @arguments varchar(8000)
declare @variables varchar(8000)
declare @assignments varchar(8000)

set @key=''
set @fields=''
set @arguments=''
set @variables=''
set @assignments=''

select @key=@key+ ', '+column_name
from information_schema.columns
where table_name=@tableName and (COLUMNPROPERTY(OBJECT_ID(@tableName), column_name, 'isidentity') = 1) AND (column_default IS NULL)

select @fields=@fields+ ', '+column_name
from information_schema.columns
where table_name=@tableName and (COLUMNPROPERTY(OBJECT_ID(@tableName), column_name, 'isidentity') = 0) --AND (column_default IS NULL)

select @arguments=@arguments+ ', @'+column_name+' '+data_type+'(' + cast(character_maximum_length as varchar(10)) +')' + case is_nullable when 'no' then ' ' when 'yes' then '=null' end
from information_schema.columns
where table_name=@tableName and (COLUMNPROPERTY(OBJECT_ID(@tableName), column_name, 'isidentity') = 0) and character_maximum_length<>null AND (column_default IS NULL)and data_type<>'text'

select @arguments=@arguments+ ', @'+column_name+' '+data_type
from information_schema.columns
where table_name=@tableName and (COLUMNPROPERTY(OBJECT_ID(@tableName), column_name, 'isidentity') = 0) -- and (character_maximum_length=null or data_type='text' ) AND (column_default IS NULL)

select @variables=@variables+ ', @'+column_name
from information_schema.columns
where table_name=@tableName and (COLUMNPROPERTY(OBJECT_ID(@tableName), column_name, 'isidentity') = 0) --AND (column_default IS NULL)

select @assignments=@assignments+ ', '+column_name+' = @'+column_name
from information_schema.columns
where table_name=@tableName and (COLUMNPROPERTY(OBJECT_ID(@tableName), column_name, 'isidentity') = 0) --AND (column_default IS NULL)

set @key=SUBSTRING(@key,3,len(@key))
set @fields=SUBSTRING(@fields,3,len(@fields))
set @arguments=SUBSTRING(@arguments,3,len(@arguments))
set @variables=SUBSTRING(@variables,3,len(@variables))
set @assignments=SUBSTRING(@assignments,3,len(@assignments))

/*--
select @tableName
select @key
select @fields
select @arguments
select @variables
select @assignments
*/
declare @insertProc varchar(8000)
set @insertProc = '
CREATE PROCEDURE Cms_Auto_Insert'+@tableName+'
'+@arguments+'
AS
BEGIN
SET NOCOUNT ON;
insert into '+@tableName+' ('+@fields+') values ('+@variables+')
END
;
'

declare @updateProc varchar(8000)
set @updateProc = '
CREATE PROCEDURE Cms_Auto_Update'+@tableName+'
@'+@key+' int, '+@arguments+'
AS
BEGIN
SET NOCOUNT ON;
update '+@tableName+'
set '+@assignments+'
where '+@key+' = @'+@key+'
END
;
'

declare @deleteProc varchar(8000)
set @deleteProc = '
CREATE PROCEDURE Cms_Auto_Delete'+@tableName+'
@'+@key+' int
AS
BEGIN
SET NOCOUNT ON;
delete from '+@tableName+' where '+@key+' = @'+@key+'
END
;
'

exec (@insertProc)
exec (@updateProc)
exec (@deleteProc)

END

How to Stack Trace SQL

Just use SQL Profiler - if it's installed! Open the profiler, connect to a database, File->New. Remember to check the boxes for text query and hit run. Let your code do it's bit, then hit stop. But be quick about it, because there's probably a lot of other stuff going on and (like C# debugging) this could all come jumping out you in a very short space of time.....

Friday, January 11, 2008

Useful MSDN Blog Links and Immutable Classes

The standard feed provided in the Visual Studio 2005 Start Page provides some very useful links. One of them is this:

http://blogs.msdn.com/lucabol/archive/2007/12/28/creating-an-immutable-value-object-in-c-part-iv-a-class-with-a-special-value.aspx

a blog tutorial on creating immutable classes and the clever things to do with them.

I'm hoping to build a large list of really useful links featured on that feed, here.

Yes, yet another list.

MicroSoft Visual Source Safe

This is just a little post to lament the problems provide (as features) by VSS.  Fortunately, this guy has posted them already: http://www.highprogrammer.com/alan/windev/sourcesafe.html

Happy coding...

Thursday, January 10, 2008

SubSonic and some DAL stuff

So I've been using CodeSmith with NetTiers for over a year now and loving almost every minute. However, there is now a very large problem which seems to have settled in and won't go away, like an elephant in the corner at a party. Except that everyone is talking about how to get rid of it, but no-one's managing to shift the thing. This problem is that Deep-Loading and Deep-Saving cannot be guaranteed in any version. (My personal issue with this is that if a nightly release does appear with a fix, any number of other critical bugs arise to replace it.) So, what we have is a DAL (Data Access Layer) generator which used to be wonderful and cuddly, but is now more of a problem than the number it solves.

So, what am I doing about it? Helping to solve the code issues? Submitting a new series of DAL templates using a radical and effective new code schema? Or ignoring the problem entirely?

That's right, I'm leaving my rather large application using the last, most reasonable generated DAL layer as it is, until I find another DAL generator I can use. Obviously, this is because there's a lot of people with much more experience solving their own code bugs without me trying to hack their templates apart. While I feel a little guilty about jumping ship, I will quite happily throw my support behind them if this quite annoying bug gets solved - something which used to be a huge selling point, IMHO.

Anyhow, this situation has opened a number of avenues. Among them is a little thing called SubSonic, with the catchy slogan "All Your Database Are Belong To Us!" Nice.

I'm only just starting with this one, so I've no useful (or other) information to pass on, so I'll start with some links and hopefully, soon, there'll be plenty of musing from my addled brain...

http://geekswithblogs.net/dlussier/archive/2007/12/30/118069.aspx
http://geekswithblogs.net/scottkuhl/archive/2006/11/17/97470.aspx
http://subsonicproject.com/view/for-web-sites---using-the-buildprovider.aspx
http://www.codeplex.com/subsonictools
http://blog.benhall.me.uk/2007/10/setting-up-subsonic.html
http://www.scribd.com/doc/94319/SubSonic?query2=%27SubSonic.Generated.+does+not+contain+a+definition+for