Lets #crushit like GaryVee

If you haven’t had a chance to hear Gary Vaynerchuck speak, I’d highly recommend it.  The guy is motivating.  And he’s right – you should be doing what you are passionate about.  If you aren’t, you aren’t doing your best work.  Check out the video on his  bio page.

Advertisements

LINQ to SQL DataContext Initializer

In LINQ to SQL, you design a model by dropping tables from your DB onto a designer surface.  The model creates a DataContext, which allows you to reference your tables in the model as (something like) a collection you can query with LINQ.  You can also call SubmitChanges() on the DataContext to persist any local changes you made back to the database.

One way to do this in the webapp would be something like:

var datacontext = new ModelDataContext();
var user = (from u in datacontext.Users where u.UserID==5 select u).First();
user.Email = "newemail@email.com";
datacontext.SubmitChanges();

This isn’t ideal, because you are peppering your webapp with data/business logic – just because you need to keep an instance of a datacontext. You could pull out the data logic, but you’d still need to new up an instance of the data context and pass it to each business logic function – that would be a mess. I’d prefer the webapp to not know/care about persistence or a DataContext at all. It would be great if the Business logic classes could handle that.

The problem is, lots of the business logic uses a static method ( User.Add(“username”,”password”) – you shouldn’t need an instance of User to run that, it works like a Factory pattern and returns an instance). A local DataContext instance would have to be static to be accessible to those functions – and ASP.NET treats local statics something like global/application variables. One instance would be shared across every request and every user on the site. DataContext instances are supposed to be available for limited amount of time – reusing one in this way would create all kinds of weird issues under any kind of load.

So, what I needed was somewhere to store the instance – shared across multiple business logic calls but scoped to exactly one request. After some trial and error, I ended up storing it in different locations for ASPX pages, for ASMX webservices (standard, and WSE 3.0), and for non-ASP.NET uses (particularly LinqPad). First, I used a interface to implement for each type and cast to get the DataContext:

public interface IDataContextHelper
{
	ModelDataContext DataContext { get; }
}

Next, I implemented that handler for the special page class that all ASPX pages use:

public class FoliotekPage : System.Web.UI.Page, Foliotek.DataAccess.IDataContextHelper
{
.
.
.

	private Foliotek.DataAccess.ModelDataContext dataContext = null; //local and non-static, so scoped with the page handler
	public Foliotek.DataAccess.ModelDataContext DataContext
	{
		get
		{
			if (dataContext == null)
			{
				dataContext = new Foliotek.DataAccess.ModelDataContext();

			}
			return dataContext;
		}
	}
.
.
.
}

For various reasons, I didn’t have access to the CurrentHandler to do this for webservices and ashx files. Instead, I used the Items collection on the ASHX handler class, and the .Current[] collection on the SoapContext classes:

Standard webservice:

public class AjaxSupport : System.Web.Services.WebService
{

	public AjaxSupport()
	{
		this.Context.Items["ModelDataContext"] = new Foliotek.DataAccess.ModelDataContext();
	}
.
.
.
}

WSE 3.0 webservice (security object)

SoapContext.Current["ModelDataContext"] = new dac.ModelDataContext();

Finally, I tied it all together by writing a property in the super class for all of my business logic classes:

static ModelDataContext datacontext;
internal static ModelDataContext DataContext
{
	get
	{

		if (System.Web.HttpContext.Current == null) // for linqpad/etc
		{
			if (datacontext == null)
				datacontext = new ModelDataContext();
			return datacontext;
		}
		else if (System.Web.HttpContext.Current.CurrentHandler is IDataContextHelper) // for web page
		{
			return ((IDataContextHelper)System.Web.HttpContext.Current.CurrentHandler).DataContext;
		}
		else if (System.Web.HttpContext.Current.Items != null && System.Web.HttpContext.Current.Items["ModelDataContext"] != null) // for simple webservice
		{
			return (ModelDataContext)System.Web.HttpContext.Current.Items["ModelDataContext"];
		}
		else if (Microsoft.Web.Services3.SoapContext.Current != null) // for webservices (in auth)
		{
			return (ModelDataContext)Microsoft.Web.Services3.SoapContext.Current["ModelDataContext"];
		}
		else if (Microsoft.Web.Services3.RequestSoapContext.Current != null) // for webservices (in webservice call)
		{
			return (ModelDataContext)Microsoft.Web.Services3.RequestSoapContext.Current["ModelDataContext"];
		}
		else
		{ // make sure we know about it if something uses the static context, that can be bad under load...
			ErrorLog.Add(-1, -1, -1, "Warning - Using Static Data Context","",
			"", "", 80, System.Web.HttpContext.Current.Request.Url+"", "", "", new 	Foliotek.DataAccess.ErrorLog.QueryValueDataTable(), "",
			"", "", "", "", "");
			if (datacontext == null)
				datacontext = new ModelDataContext();
			return datacontext;
		}
	}
}

I think the methodology is sound. I happened upon the Items collection on HttpContext fairly recently – its possible that is a solution that would cover all of the ASP.NET cases. You might even be able to instantiate it on Application_BeginRequest and clear it on Application_EndRequest and clear out some of the extra code. Here’s the resulting code:

Web App:

var user = Business.User.Get(userid);
user.Email = "newemail@email.com";
user.Update();

Business Class:

public static User Get(int userid)
{
	return (from u in DataContext.Users
	where u.UserID == userid
	select u).First();
}

public void Update()
{
	DataContext.SubmitChanges();
}

So, all that work had 2 main benefits: the web app developer doesn’t have to think about persistence at all, and the business logic developer doesn’t have to deal with managing a DataContext instance. Less than 100 lines of code eliminated several hundred lines of boiler plate code.

Disabling html drop and element resize inside of DesignMode

Add to FacebookAdd to DiggAdd to Del.icio.usAdd to StumbleuponAdd to RedditAdd to BlinklistAdd to TwitterAdd to TechnoratiAdd to Yahoo BuzzAdd to Newsvine

Background:

You can set the DesignMode attribute on a div/iframe/etc to get a WYSIWYG panel.  Some browsers enable interfaces in those boxes that may not be desirable in all circumstances – and it’s not well documented how to turn them off.

IE Element Resize:

IE has a bad habit of putting resize controls on any element inside the DesignMode element where “hasLayout” is set.  This includes images, inputs, things that are floated, absolutely positioned, etc.  Do you really want them to resize a radiobutton?  Probably not.  Use the following js event to stop the resize.  It still gives the controls to resize, but they don’t do anything:

this.onresizestart = function() { return false; };

Drop Html:

Most browsers allow you to drag html into the DesignMode surface.  I can see situations where this would be handy, but in our case it just allows the confusing behavior where someone can drag an application button/link from outside the editor into it.  To disable dropping content into your DesignMode surface, use something like:

element.ondragstart = function(e) { return false; };

where element is either the designmode div, or the iframe’s document (iframe.contentWindow.document).

Bad Design, Samsung Team

One of my major pet peeves is when aesthetics override usability in a design.  Don’t get me wrong, aesthetics are important.  They speak to a user’s emotions.  Done correctly, they can improve usability – if something is pretty, it makes you happy.  If you are happy, you are less likely to get frustrated.  Patient users make any interface more usable.

The problem comes in when the design team’s sole goal is to make something pretty.  There are design choices you can make that do look good, but make things nearly impossible to use.  In Donald Norman’s classic Design of Everyday Things, He talks about a large bank that had front doors  with no visible handles or hinges.  It looked good – the front of the building was all seamless glass.  But, there were no “affordances” – looking at the doors, you had no idea which side to push or pull, let alone whether to push or pull.  That’s bad design.

Here’s a pic of my widescreen Samsung monitor at work:

You may not be able to see it, but the monitor has NO BUTTONS!  Instead, the bottom right corner’s controls are touch activated.  Not only can you not use them without looking/in low light – they are practically invisible in the best light (a slightly lighter gray than the black they are on).  The first day I got the monitor, it took several minutes just to get the thing on.  Months later, I still struggle touching exactly the right spot to turn it on – and cannot use any of the other adjustment “buttons” without my eyes being a few inches from them.  I don’t care if my monitor is pretty if it doesn’t work.

I think that web designers can learn valuable lessons from things in the real world like this one.  In fact, I remember a time when I was trying to help with a problem on one of the custom sites we do for a client.  No one was using a new feature.  That feature was a tab on a fairly well used screen.  The problem?  Throughout the site, the current tab (the one you were on) actually looked like a tab – it had a rounded border, was easy to see, etc.  Other tabs had no border (and seemed to “float”), were a grey text, weren’t underlined…basically it was something your eye naturally skipped over when scanning the page.  Sometimes you have to compromise your personal style and conform to some standards to make sites work – tabs should be recognizable as tabs, links should be recognizable as links, buttons should be recognizable as buttons.

FIRST POST!

Okay.  So we are REALLY LATE to the blogosphere.  Better late than never, right?

Thanks to some of the great speakers at the first ever BigOmaha, I’m extremely exited to start sharing the Lanit story and expertise.  I firmly believe we have an awesome software team and that we have some great things to share with the rest of the world.