• 0

Cool Site I made


Question

I thought you might be interested to check out the site I made that launched this evening.

http://www.letter-photo.com

This site was built for a client of ours (I work for a company called Orajen - http://www.orajen.com). The client goes around and takes pictures of things that look like letters and then lets you assemble a word from their letter collection. There are other sites / companies out there that do the same thing but I think our work is the best of the bunch.

The design work is not mine (it was done by our in house designer), I was 'merely' the developer on the project. The site is built in ASP.NET / c# and the client side stuff leverages scriptaculous. The shopping cart was built in house by me for this project.

There have been hundreds of hours put into this project and I have a lot of pride in the work so I wanted to show it off a little :)

Link to comment
https://www.neowin.net/forum/topic/647112-cool-site-i-made/
Share on other sites

Recommended Posts

  • 0

I would have made the header smaller so I didnt have to scroll to see the stuff down the bottom. But besides that I like it :) Thats at 1280x1024, you could argue no one uses that res anymore and that would be a valid but I guess some people do. Nevertheless, I reiterate that I like it. +2 thumbs up for you.

  • 0
I would have made the header smaller so I didnt have to scroll to see the stuff down the bottom. But besides that I like it :) Thats at 1280x1024, you could argue no one uses that res anymore and that would be a valid but I guess some people do. Nevertheless, I reiterate that I like it. +2 thumbs up for you.

Our designer was never completely satisfied with the header, but it is what is now (he never could arrive on something he liked better). And as an FYI, the site is designed to be usable (IE no horizontal scrolling) at 1024x768.

  • 0
Glad you like it. You're inclusion of that pic reminds me, we are looking at doing some more social / viral features for the site for phase 2, such as building a word and emailing it to a friend.

Good idea, as the site is easy to use and fun, people will want to send things to friends. :yes:

  • 0

What kind of design choices did you use when interacting with your database? Did you just use a SqlReader in each codebehind file for the pages, or did you use a separate class that handles all of the database stuff?

What do you think of the the LinqToSql technology by microsoft?

Nice site btw, I really like how everything fits together.

  • 0
What kind of design choices did you use when interacting with your database? Did you just use a SqlReader in each codebehind file for the pages, or did you use a separate class that handles all of the database stuff?

What do you think of the the LinqToSql technology by microsoft?

Nice site btw, I really like how everything fits together.

With all my projects I prefer to implement a data access layer that obfuscates my database functions. I typically will implement the basic CRUD functions behind appropriately named functions and add additional functions as required (like one for updating or adding a record to a one-to-many relationship). Naturally then I build my objects to adequately represent the things of the domain in code.

For letter-photo I have many objects; Word, Letter, LetterCollection, Attribute (which I inherit from to build things like Orientation, Easels and Color), etc. The shopping cart piece lives in a separate namespace entirely. I wrote it to understand how to handle items of type Product (base class I defined) and then had Word inherit off of product. This way adding those Words was easy and the entirety of my cart code base is quite flexible and reusable.

In regards to Linq and LinqToSql, I unfortunately have not yet made myself work with them in a project yet. We only installed 3.5 in production a few months ago. I must say I am intrigued by what they have to offer, and on my next project I am going to attempt to use the technology as soon as I find an appropriate spot.

Doesn't seem to work in Opera which is a shame..

We don't typically test for compatibility with Opera in house. We check all of our sites in IE6, IE7, Firefox 2 and 3, Safari 2 and 3. That being said I'll look at what I can do to fix this site for opera and perhaps get it added to our test suite.

  • 0
How about a feature where you can type in a word and it randomly selects the letter tiles for you?

This certainly is a good idea. The shame is that since this project was contracted by a client of ours, I can't just go adding features without having them pay for it (I could, but that's not smart business). As much as I like the site, I am biting my tongue when it comes to adding additional functionality until we start a Phase 2 of development with them.

  • 0
Doesn't seem to work in Opera which is a shame..

I've downloaded Opera 9.5 from http://www.opera.com and the site works fine as far as I can tell. I noticed a few non-critical css anomalies, but those were in the cart during the checkout process. What version of Opera are you using and what exactly are you experiencing?

  • 0
With all my projects I prefer to implement a data access layer that obfuscates my database functions. I typically will implement the basic CRUD functions behind appropriately named functions and add additional functions as required (like one for updating or adding a record to a one-to-many relationship). Naturally then I build my objects to adequately represent the things of the domain in code.

For letter-photo I have many objects; Word, Letter, LetterCollection, Attribute (which I inherit from to build things like Orientation, Easels and Color), etc. The shopping cart piece lives in a separate namespace entirely. I wrote it to understand how to handle items of type Product (base class I defined) and then had Word inherit off of product. This way adding those Words was easy and the entirety of my cart code base is quite flexible and reusable.

In regards to Linq and LinqToSql, I unfortunately have not yet made myself work with them in a project yet. We only installed 3.5 in production a few months ago. I must say I am intrigued by what they have to offer, and on my next project I am going to attempt to use the technology as soon as I find an appropriate spot.

We don't typically test for compatibility with Opera in house. We check all of our sites in IE6, IE7, Firefox 2 and 3, Safari 2 and 3. That being said I'll look at what I can do to fix this site for opera and perhaps get it added to our test suite.

How do you deal with links between the objects in your data access layer? I am in the slow process of building an asset tracking system and some of my objects are linked to other objects. For example, an asset is linked to a location, which is then linked to a region. When creating an asset in my data access layer I would have to fill all the properties for that asset and then if a property is an object I would have to fill all the properties of that object and so on. So there is a lot of overhead when sometimes you just need the object to access a few properties so there is a big performance hit on the database.

I looked into something like nhibernate that supports lazy loading, but its not as flexible as building your own data access layer. For example, all collections have to conform to their specification and some other things that cause you to rethink your design a bit. Also, in order to support lazy loading you have to maintain a database session throughout the http request which can be a little tricky to implement. There is not much documentation on the proper way to do this, but the latest alpha relase does make it easy to handle.

I do like LinqToSql, but the problem with that is it enforces a database driven design and it does not support things like multiple table inheritance. I don't need multiple table inheritance in my design, but if I did then I would have to use something else. Another thing with LinqToSql is that it currently only supports MS Sql Server so again, you would have to switch to something else.

Did you encounter any database to object problems like this and what did you do to resolve them? Do you just not have that many links between objects so performance was not much of an issue?

  • 0
I've downloaded Opera 9.5 from http://www.opera.com and the site works fine as far as I can tell. I noticed a few non-critical css anomalies, but those were in the cart during the checkout process. What version of Opera are you using and what exactly are you experiencing?

I'm using Opera 9.27 - one of the last builds before Opera 9.5 was released. I haven't got round to upgrading it on my laptop yet.

If it works in 9.5 you probably don't have to worry about fixing it (the drag and drop didn't work at all).

  • 0
How do you deal with links between the objects in your data access layer? I am in the slow process of building an asset tracking system and some of my objects are linked to other objects. For example, an asset is linked to a location, which is then linked to a region. When creating an asset in my data access layer I would have to fill all the properties for that asset and then if a property is an object I would have to fill all the properties of that object and so on. So there is a lot of overhead when sometimes you just need the object to access a few properties so there is a big performance hit on the database.

I looked into something like nhibernate that supports lazy loading, but its not as flexible as building your own data access layer. For example, all collections have to conform to their specification and some other things that cause you to rethink your design a bit. Also, in order to support lazy loading you have to maintain a database session throughout the http request which can be a little tricky to implement. There is not much documentation on the proper way to do this, but the latest alpha relase does make it easy to handle.

I do like LinqToSql, but the problem with that is it enforces a database driven design and it does not support things like multiple table inheritance. I don't need multiple table inheritance in my design, but if I did then I would have to use something else. Another thing with LinqToSql is that it currently only supports MS Sql Server so again, you would have to switch to something else.

Did you encounter any database to object problems like this and what did you do to resolve them? Do you just not have that many links between objects so performance was not much of an issue?

Links between objects is something I have wrestled with for a long time. In this project the object with the most links is Order. Order has a collection of Products you ordered (and products have Attributes), Address objects for billing and shipping, and then order attributes (for expressing things like a Cart handling fee, etc). So of course that could potentially be a pretty mammoth set of queries to the database when you want to view an order.

I typically try and design what will be the best for my code first, and then later on implement the database stuff. Some simple objects translate nicely to a single row, but many do not. Rather than have these limitations limit my creativity in code, I let my DAL handle these troubles and I attempt to build the best relational design for the task and likewise with my objects.

When deciding how I want to handling the loading of big boys like that, I often let the user interface help me make those decisions. If the information that we'd be viewing can be separated, in a logical manner, over several requests. In my case, showing only the high level order details first, then only let them see the order items if they really ask for it. The part I dislike about this is you are conceding aspects of your design to the necessities of performance, but in reality part of application design should always focus on performance and if your model is affected slightly by it, so be it.

With that aside, there are 3 ways I typically approach my links (usually case-by-case):

1) When I know the O(n) of the queries to build the objects will be something trivial like 2 or 3, I lump them into one request and load. This is mostly things who have a 1 to 1 relationship or 1 to few.

2) If the associated objects are not likely to be needed when viewing the primary information, but there are few of those objects, I will mirror the database in that I actually expose a SomethingId property on my object so I may request them if the end user asks for them.

3) If I don't want to store ID's on the objects like that, and there will be potentially many associated objects, I will write functions in the DAL like List<Product> GetOrderItems(string orderId) So I can provide all that information after the user says they are actually interested in it.

And I always write a full load function just in case.

  • 0

A couple of other things I thought of;

I agree with you in not totally liking tools that emphasize the structure of your database as the model of your domain in code. I definitely see it's merits, but I prefer to to think of the persistence of my objects and data as secondary to the model of the domain. And more often than not on a fresh project neither is totally defined yet, so I usually start with the code.

In instances when I need to load something that I am going to use over and over, I leverage System.Web.Caching. If you are not familiar with this namespace, it allows you to persist items to memory, not unlike Session State. However the nice thing is that items persisted to cache are accessible by all sessions. In context of letter-photo.com, one place I use caching is for the letter's that are populated into the carousel. Here's the function I call to load some letters when someone clicks a category:

public static LetterCollection GetLetters(int categoryId)
	{
		string letterColKey = "LetterCollection" + categoryId.ToString();
		LetterCollection letters = new LetterCollection();

		if (System.Web.HttpContext.Current != null)
		{
			letters = (LetterCollection)System.Web.HttpContext.Current.Cache[letterColKey];

			if (letters == null)
			{
				letters = Letter.LettersFromSql(categoryId, true);
				System.Web.HttpContext.Current.Cache.Insert(letterColKey, letters, null, DateTime.UtcNow.AddMinutes(5d), System.Web.Caching.Cache.NoSlidingExpiration);
			}
		}
		else
		{
			letters = Letter.LettersFromSql(categoryId, true);
		}

		return letters;
	}

So you can see here that I first check to see if I have the object I want in cache, and if so I can return that directly from memory (all of this is transparent to the page level requests as I bundled this into my DAL functions). Only if I don't find what I'm looking for do I ask the database. Here's some more information on Caching http://msdn.microsoft.com/en-us/library/sy...che(VS.80).aspx

There is a nice ebook that is available for free (all you need to do is register on their site), that talking about good domain based modeling of your code. Its called 'Domain Driven Design Quickly' and you can get it here - http://www.infoq.com/minibooks/domain-driven-design-quickly

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • If someone chooses to continue using SB and therefore goes through the manual intervention in the thread, afterwards the BSOD problem is gone. Whether they then re-enable the task doesn't matter, they're done, though on such machines it might pay to keep it disabled in case the next update (if there is a next) causes the same problem. OTOH, if someone disables SB in the BIOS, the problem is also gone. Incidentally, I noticed that this task exists even on machines that don't support SB. It's just installed across the board...and runs. Doing what on such machines is a little hazy.
    • qBittorrent 5.2.2 by Razvan Serea The qBittorrent project aims to provide a Free Software alternative to µtorrent. qBittorrent is an advanced and multi-platform BitTorrent client with a nice user interface as well as a Web UI for remote control and an integrated search engine. qBittorrent aims to meet the needs of most users while using as little CPU and memory as possible. qBittorrent is a truly Open Source project, and as such, anyone can and should contribute to it. qBittorrent features: Polished µTorrent-like User Interface Well-integrated and extensible Search Engine Simultaneous search in most famous BitTorrent search sites Per-category-specific search requests (e.g. Books, Music, Movies) All Bittorrent extensions DHT, Peer Exchange, Full encryption, Magnet/BitComet URIs, ... Remote control through a Web user interface Nearly identical to the regular UI, all in Ajax Advanced control over trackers, peers and torrents Torrents queueing and prioritizing Torrent content selection and prioritizing UPnP / NAT-PMP port forwarding support Available in ~25 languages (Unicode support) Torrent creation tool Advanced RSS support with download filters (inc. regex) Bandwidth scheduler IP Filtering (eMule and PeerGuardian compatible) IPv6 compliant Available on most platforms: Linux, Mac OS X, Windows, OS/2, FreeBSD qBittorrent 5.2.2 changelog: FEATURE: Use D-Bus to show file in file managers (Chocobo1) #24340 BUGFIX: Fix friendlyUnitCompact precision calculation (vafada) #24323 BUGFIX: Remove all top-level folders (glassez) #24333 BUGFIX: Use proper API for checking exit status (Chocobo1) #24349 BUGFIX: Delete stale lockfile when hostname mismatch (TurboTheTurtle, glassez) #24363 BUGFIX: Fix wrong removal procedure of watched folder paths (Chocobo1) #24413 BUGFIX: Don't reannounce before interface changes are applied (glassez) #24447 BUGFIX: Use Latin script for Bosnian locale name (Andy Ye) #24342 WEBUI: Fix performance of global checkbox toggling (tehcneko) #24316 WEBUI: Fix Safari transfer list header misalignment (Piccirello) #24377 WEBUI: Fix error when submitting magnet before metadata loads (Piccirello) #24378 WEBUI: Use correct row id when updating Rss Downloader feed selection (Chocobo1) #24402 WEBUI: Use SameSite=Lax for session cookie to fix cross-site login (Piccirello) #24422 WEBUI: Bring back properties panel expand/collapse button (vafada) #24430 WEBAPI: Only use X-Forwarded-Host header when reverse proxy support is enabled (Chocobo1) #24457 RSSS: Fix "RSS Smart Episode Filter" RegEx (nathanon-akk, glassez) #24398 RSS: Fix previously matched episode format (glassez) #24452 WINDOWS: Fix Python fallback search path (TurboTheTurtle) #24325 WINDOWS: NSIS: Allow to install x64 binary on ARM64 (Chocobo1) #24358 Download: qBittorrent 5.2.2 | 41.1 MB (Open Source) Download: qBittorrent 64-bit installer (qt6) | 43.6 MB Links: qBittorrent Home page | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • Weechat. https://weechat.org/
    • they should stop making bad games that no one asked for
  • Recent Achievements

    • Veteran
      branfont went up a rank
      Veteran
    • Reacting Well
      Almohandis earned a badge
      Reacting Well
    • First Post
      Cosminus earned a badge
      First Post
    • One Year In
      ThatGuyOnline earned a badge
      One Year In
    • Week One Done
      Jeroen Wilms earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      483
    2. 2
      +Edouard
      183
    3. 3
      PsYcHoKiLLa
      124
    4. 4
      Steven P.
      87
    5. 5
      neufuse
      72
  • Tell a friend

    Love Neowin? Tell a friend!