Getting started in Asp.Net

I recently met a guy who was new to town and had picked up a job doing development for a place that appeared to be moving towards Microsoft focused solutions meaning he was likely to move away from his LAMP (Linux, Apache, MySQL, PHP) background to a .Net/Sql Server environment.

I realised after talking to him that there are a lot of ways you could go wrong coming into the .Net realm from a LAMP/Java/Python/Ruby background and this post, although intend for him, is generic enough that it may save other web developers valuable time to get up and running, and producing valuable software using the M$ stack

Asp.Net

Asp.net is a different beast to the many other frameworks out there and you could spend years (and many have) learning all the ins and outs of the beast.
Dont.
I would highly recommend skipping WebForms all together as IMO it is a dead framework. I have been doing MS MVC for the last year and did MonoRail (an open source ASP MVC framework) on the side prior to that and I have never looked back. Some of the significant benefits are :

  • Matches the way the web works (you explicitly work with http verbs)
  • clean html
  • easy to learn
  • pluggable
  • testable
  • simple
  • And finally, IMO, encourages better coding practices, which web forms simply does not.

I will assume you will trust me and accept that MVC is the way forward and I will go ahead and recommend how to start.

Asp.Net MVC in action
First port-of-call is to pick up this book. It will give you the no BS version of the truth and covers some third party tools that will help you along the way. There is a second edition on the way however if you are using VS 2008 then this books is for you anyway. Manning (the publisher) often have good discounts so register for emails or follow them on Twitter to know when promos are running.

TekPub : Build your own blog with MVC
Tekpub is one of my favourite resources at the moment. It is great value for money and video is an efficient way to learn new concepts. I had bought several series and now have the yearly membership and many of my colleagues have done the same. Go check out the BYOB which shows how Rob* built a blog in MVC. There are also MVC 2.0 and various other Asp.net series available. Buy one, buy a bunch or get a month or yearly subscription, go on, you know you want to 😉
*Rob was on the team that actually built Asp.net MVC

Asp.net
Yes the website is a good place to get lots of info too! There are lots of little articles and videos from from smart people who live and breathe this stuff. Just be aware that there is sometimes a very Microsoft slant to the information, not a bad thing but something to be aware of.

Next there is the Database

SQL Server

If you have a background in Oracle or MySql then picking up M$ Sql Server should be pretty easy. The standard practices apply e.g. dont run your web app as System Administrator. Nothing to really say here to be honest.

Joining the web and data world is your data access strategy

Linq2Sql or NHibernate

The 2 standout choices for new commers IMO are the light weight data acess strategy from Microsfot called Linq2Sql (pronounced “Link to Sequel”, just dont ever write it like that) or the OpenSource and more heavy weight NHibernate. If you are from a Java background NH may be a good tool, if you are from a Rails background then Castle ActiveRecord (which sits on tope of NH) may even be a good idea. However for most Linq2Sql is probably the best bet when you are getting started and NH is the best if you are building up more complex domains. The caveat with NH is that there is a steep learning curve. If you are new to it then check out SharpArchitecture or one of the abstractions in the NHforge.com to help bootstrap yourself. If you have a simple domain or going to be building from the database up (i.e. create a database table and then the c# code to use it) Linq2Sql is a better fit anyway.

Tools

If you are playing with the M$ stack at home then you will most likely not want to shell out cash for the full blown enterprise versions of Visual studio and Sql Server. For this reason they have the express versions. I have only ever used the SQL express edition (which is great) so have no idea what VsExpress is like. In saying that if i did not have the full version of VS I probably would not be using .Net and just be doing rails/sinatra dev (but thats just me).
Assuming you are working with the full version at work then be sure to invest in the Resharper VS plug-in. Its not super cheap but the time it will save you will mean it will quickly pay for itself.

I terms of source control TFS is the M$ standard, but I personally don’t recommend it. I think tools like Git or even SVN are better tools that integrate better with other platforms/tools and are free. TFS however does more than source control, so if you are using make sure you use all the good ALM bug tracking bits etc

Extra links

Follow the team behind the framework, most importantly Scott Gu (all .net dev should read his blog) and Scott Hansleman. Mr Hanselman also has a good podcast called hanselminutes that is not Asp.Net specific but a good subscription nonetheless.
StackOverflow is a great QnA community place for lots of developer question. The are lots of .Net and Asp.Net people hanging out here so most of your initial question will most likely have already been answered. The site itslef is even built on top of Asp.Net MVC and Linq2Sql so you can see that this combination is a very real world and scalable solution.

If you are in Perth (like this person was) check out the Perth .Net Community of Practice and the Alt.Net lads that have monthly beers and discuss things that may or may not be from the Microsoft mother ship that affect .Net devs.

Soft Deletes in Nhibernate

The following was an email to my dev colleagues, sorry about the code formatting Im using the Blogger web interface (OSX really needs a WLW equivlient!):

Fellow nerds;
There are frequently requirements that we need to have soft deletes. These things are a pain, especially with an ORM as they can start becoming invasive to your domain code.

If you want soft deletes to be transparent as possibly in normal workings of the domain you can use a DeleteListener to intercept the deletion and, well, soften it.
Below is some code to show a parent and child relationship (ParentSampleDomainObject and SampleDomainObject).

Key points:
• The entities need to have a flag to show they are deleted eg IsDeleted
• The mapping on the parent needs to say that it is not interested in retrieving deleted items by using a where clause
• The mapping also need to say it want to delete orphan children, (we won’t actually delete them, but this needs to be here)
• We need to have an NHibernate delete listener to intercept the cascading delete and instead of deleting the entity mark it as deleted. This is why we need cascading deletes in the mapping
• We need to register the listener to the config.

The test code will be checked into the core soon.

Rhys

Nhibernate Configuration:




NHibernate.Dialect.MsSql2005Dialect
NHibernate.Connection.DriverConnectionProvider
NHibernate.Driver.SqlClientDriver
NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle
Data Source=.\SqlExpress;Database=CoreTests;Integrated Security=True;
ReadCommitted
CoreTests.dbo












Parent Domain entities mapping file:













[Serializable]
public class ParentSampleDomainObject : BaseEntity<int>
{
public ParentSampleDomainObject()
{
Children = new List<SampleDomainObject>();
}
public virtual IList<SampleDomainObject> Children { get; set; }
public virtual void AddChild(SampleDomainObject child)
{
Children.Add(child);
child.Parent = this;
}
public virtual void RemoveChild(SampleDomainObject child)
{
Children.Remove(child);
}
}
[Serializable]
public class SampleDomainObject : BaseEntity<int> , ISoftDeletable
{
public virtual string Name { get; set; }
public virtual bool IsDeleted { get; set; }
public virtual void MarkAsDeleted()
{
IsDeleted = true;
}
public virtual ParentSampleDomainObject Parent { get; protected internal set; }
}

public class SoftDeleteListener : DefaultDeleteEventListener
{
protected override void DeleteEntity(IEventSource session, object entity,
EntityEntry entityEntry, bool isCascadeDeleteEnabled,
IEntityPersister persister, ISet transientEntities)
{
if (entity is ISoftDeletable)
{
var e = (ISoftDeletable)entity;
e.MarkAsDeleted();
if(entity is IAuditableRecord)
{
var a = (IAuditableRecord) entity;
AuditListener.SetAuditInfo(a);//need to have a log of when this was actually deleted, probably the intent of the soft delete!
}
CascadeBeforeDelete(session, persister, entity, entityEntry, transientEntities);
CascadeAfterDelete(session, persister, entity, transientEntities);
}
else
{
base.DeleteEntity(session, entity, entityEntry, isCascadeDeleteEnabled,
persister, transientEntities);
}
}
}

Manning Book Reviews

Thought i’d let you guys know of some books i have been reading that are pretty good, They are all from Manning which I am really starting to like that publisher more and more.

JQuery In Action: Within about 90 minutes of reading this book you will understand the fundamentals of jQuery and be ready to do basic, but powerful, jQuery code. If you are using javascript natively seriously consider switching to jQuery and get this book. jQuery also has a test framework (QUnit) and a great suite of UI plugins (jQuery UI)

Art Of Unit Testing: Easily the best unit testing book I have read (and I have read a few). Great for newbies and those still getting to grips with how to test anything more than the most trivial of examples. It is the book i would recommend to people looking to learn to do TDD well. Note the examples are in C# but they really dont require indepth knowledge of .Net, in the same way all the other books are in java and I havent written a line of a coffee flavoured code in a decade. In saying that the tools are all .Net based but i am sure there are Python, Ruby and Java equivilents avaliable for most.

NHibernate in Action: Pretty much the same as the Hibernate book but shows all the .Net stuff you can do. its also a bit more up to date that the original Hibernate book (which has since had a second release). .Net devs nusing NH need* this book.

IronPython in Action: not a bad book… it does exactly what it intends, it teaches .Net devs about python on the CLR. The question is: Do you care? For me it was something of interest, i doubt I’ll ever use it in production. As a side note for the .Net kids i think the path of C# => Boo => Python =>Ruby is the one to take for the typical C# developer**. It keeps the “barrier to entry” low for the next step so you are picking up one new thing at a time (ie new syntax, dynamic language contrainst, DSLs and other scripty weirdness) and by the end of the process you have 4 languages under your belt in about the same time it would take to do the C# => Ruby jump.

that’s all

Rhys

*OK no one needs anything, especially as the NH doc a pretty good, but you will be severely hindered without it.
** VB.Net devs; you know you will never learn another language, you have had years to do so!

Gray hairs and coronaries …

Refactoring fundamentals of a rather large stack ca be daunting… I gave it a go over the weekend, modifying hundreds of files and tens of thousands of lines of code and, to be honest, I thought I had done a pretty good job doing so.
Monday morning comes around and there where some Small build issues (csproj.user are not in the a build outside of VS) but easily fix.
The really problem was when we started to do complex interactions… the app died…

Oh sh1t…. I’m fired..

Well maybe not fired just roll back to Friday and I have wasted a weekend.
Long story short… don’t leave on Nhibernate logging… it kills your app.
Commenting out log4net returned everything to normal, now we just need to log the correct things (ie not every NHibernate interaction!)

Dumb errors with NHibernate

Ok so I was getting “NHibernate.MappingException: Unknown entity class” for a revised/renamed class in my project. “Aha!”, I thought, “its not an embedded resource!”.. and it wasn’t. Re run my tests to confirm update worked… neagtive.
After about 30mins of seraching I noticed I had clipped the name too much and had removed the .hmb. part out of the file name in the mapping file… well thats annoying!

NHibernate many to many collections

We had been having issues with entities not serialising across the wire (yes we are sending Nhibernate entities over WCF services) with not a lot of clues why some worked and some didn’t.

Upon investingation it appeared it was the collections of some of these entiies that were causing the issues, not the enties themselves. I finally realised that we where creating entities for the join tables in the DB (which to me didnt really make sense), thus cause self referencing relationships in the object model, not a good place to be if this needs to be serialised to XML!

A bit of a clean up to the mapping files and we look to be all good.

I am sure this is the most trivial of trival ORM mapping stuff, but it was something that went un noticed around here for months, or at least swept under the rug by those that did.

Below is a the email outlining the scenario….

EMAIL TO WORK TEAM MATES

*If you use Nhibernate or other ORM’s this is of Note, otherwise feel free to delete*

ORM School time:

Background (trivial, but work with me here)

  • We have a whole bunch of Data Entities/ Database Tables that have “one to many” or “many to many” relationships
  • We use joining tables to create these relation ships I.e. to join AssetMetadata & GenreType we use AssetMetadataGenreType table.
  • We use an ORM (NHibernate) to convert the table structure to a usable C# managed code structure.
  • We also use the ORM to map these relationships.
  • Unfortunately we are mapping these tables too explicitly. There really is no such entity as an AssetMetadataGenreType, only an AssetMetadata entity and a GenreType entity. The AssetMetadataGenreType is only a relationship that has no context on its own.

This over eager mapping of joining table may be the problem of our serialisation issues.

Fore example: Currently we have a AssetMetadata entity that then has a collection of AssetMetadataGenreType with each one relating to a AssetMetadata and GenreType entity. The problem here is that every one of these causes a self referencing scenario (AssetMetadata è AssetMetadataGenreType è AssetMetadata). Normally no one would care. Serialisation however does not like this, as self referencing data and XML do not play nice.

Solution: Don’t map the joining tables.

These are not real entities so should not exist in the managed code world. They only exist in the DB thru necessity.

Step one: remove all of these mapping entities (well maybe not delete, but start re-factoring where possible)

Change the mapping so the subject entity knows about its relations. Inverse this relationship in the other mapping files IF NESSECARY. i.e. genre types do not need to know about there related asset metadata

Example below:

<!– The links to associated genres –><!–

–>

<!– RC: 07/02/2008: Trying a different approach so we dont try to pass self referencing data around,

I think this is a dormant issue waiting for collections to populate before it rears up and attacks us–>

<idbag name=GenreTypes table=ASSET_METADATA_GENRE_TYPE lazy=false>

<collection-id column=ID type=Int32>

<generator class=sequence>

<param name=sequence>ASSET_METADATA_GENRE_TYPE_SEQ</param>

</generator>

</collection-id>

<key column=ASSET_METADATA_ID/>

<many-to-many column=GENRE_TYPE_ID class=GenreType fetch=join/>

</idbag>

Another benefit includes faster update times as we are taking advantage of the index of the primary key on the join table.

http://www.hibernate.org/hib_docs/nhibernate/html/collections.html#collections-idbag

I still have to test the hell out of this, however prelim test are all positive.

Rhys

SubSonic

Like a lot of people, writing Data Access Layers is not something I really want to spend a lot of time doing. Thankfully there are a vast number of ways that you can improve the process, ORM’s and code generators are the two basic methods of assisting in this fashion. Many will be familiar with Hibernate (and its .Net equivalent), possibly the most popular ORM on the market. I quiet like it, but it’s fiddly and config heavy in terms of mapping files. You can Generate these thanks to product like MyGeneration but it often requires tweaking. once its up and running it really is a nice way to deal with persistence for very OO based applications. The other option I have used is Codesmith with it NetTiers templates. Well, up until finding Subsonic. It (so far) has been great.
What I like:

  • Can have the benefits of SP’s and ORM
  • Can set it to generate the code at build time, so you know every time you run it it is synched with the data base
  • If you don’t like the generate on build option you can easily generate the class files for the DAL as well as the create scripts for DB including data, all from with in VS (great for Source control!)
  • Author(s) seem to be very proactive in their support and maintenance
  • Can be used with in VS as an external tool, meaning one click generation from within VS.
  • Minimal additional config settings
  • Video showing you how to do it.
  • Its pretty fast

I last ran into Subsonic when it was ActionPack. Being happy with Codesmith I didn’t really follow it up. However, as I no longer have a license for CodeSmith, SubSonic being OSS is looking a lot nicer 🙂
No doubt as I continue to play with it I will find features and bugs, but so far so good.

NHibernate gotcha for Generated files

To save yourself repeated banging of you head make sure you HBM.XML file are embedded resources in the nhibernate project, otherwise how is nhibernate going to find these mappers….d’oh!
This highlights a point: Its nice to generate what you can. Hell, if you have already written the database tables, why not Gen the majority of your data access? You still however, have to know what is going on under the hood, whether its nhibernate, other ORM or straight ADO.Net. Otherwise how fix you fix lower level problems when you run in to them…