SingingEels : Development Community & Resource

Login

Articles

  • ADO.NET (2)
  • ASP.NET (36)
  • LINQ (5)
  • Security (2)
  • Silverlight (3)
  • SQL (7)
  • Standards (5)
  • WCF (2)

Syndication

  • Articles RSS
  • Blogs RSS

Contribute

  • Our Authors List
  • Member Sign-Up
  • Suggestions Box
Thursday, August 14, 2008 : 7:32 AM - (1 comment)

How to Handle "Side Content" in ASP.NET MVC

A couple of days ago, Stephen Walther made a great post (ASP.NET MVC Tip #31 – Passing Data to Master Pages and User Controls) on a subject that is bound to come up 100 times more until MVC is fully understood. This post is a follow-up to that one, in hopes to have a clear sense of what to do with the issue.

The issue is as follows: MVC is rests on the pillars of 1) Testability and 2) Single Responsibility. Every function (action, page, whatever you want to call it) should be fully testable, and it should only handle one point of concern. So the question is, how do we handle supplemental data?

Our Scenario

Imagine if you built an MVC web application for a car dealership that had the following actions (or pages):

  • Home - ContactUs
  • Home - OurLocations
  • Vehicles - ListCars
  • Vehicles - ViewCarDetail

At first glance, this would be very straight forward and very easy to solve (and it is). I would make a "HomeController" and have the ContactUs and OurLocations actions there, and I would make a "VehiclesController" and put the ListCars and ViewCarDetail actions there. So Where's the Problem?

A Slightly More Complex Page

Imagine, though, if you didn't just want to list all the cars on the "ListCars" page. What would you do if you wanted to also show the "Top 5 Custom Testimonials" in a <div> on the right side of the page. You want to have that shown on both of the 'vehicles' pages (ListCars and ViewCarDetail).

So the question comes in... "Who's responsibility is it to retrieve that data from the data store?" Would you add that code to each function?

public ActionResult ListCars()
{
   GetTestimonials();

   // Now do the ListCars stuff???

}

public ActionResult ViewCarDetail()
{
   GetTestimonials();

   // Now do the ViewCarDetail stuff???

}

You would *NEVER* want to do the above as that is a 100% violation of one of the pillars of MVC (the Single Responsibility Principle). Not to mention that you're working harder than you have to.

Would you make a custom ActionFilter and decorate your methods?

[TestimonialGetter]
public ActionResult ListCars()
{
   // Now do the ListCars stuf???

}

[TestimonialGetter]
public ActionResult ViewCarDetail()
{
   // Now do the ViewCarDetail stuf???

}

That's hideous, and is simply putting a new dress on an old wench. So then, what do we do?

Look At the Data for What It Is

The problem here is that we're losing focus of what the data really is. That supplemental data is not the main focus of the "View", and it's throwing us off. If we didn't have that "Top 5 Testimonials" stuff, we wouldn't have a problem.

To prove my point, imagine if we didn't want to show "Top 5 Testimonials", but instead we wanted to show... let's say... the logged in user's name! Would that be so hard?

"That's easy", you say, "all I have to do is <%= User.Identity.Name %>". True, that is easy. But did you notice that we're not freaking out about the fact that we just got some "data" from a "data base" and displayed it in our View :)

The same is true for other, non-view-specific data. So, to solve our issue above, we would most-likely create a base class for our Vehicles controller that got that extra data (in the constructor) and put the needed info into the ViewData collection.

Is that testable? Does that allow a single responsibililty? Yes, it is and yes it does. In your testing framework, you would mock up the data store, and then you could test each action to make sure that it has all the data (including the Top 5 Testimonials stuff).

Important Conclusion

MVC is a great design pattern, and it's been around for a long time. However, ASP.NET MVC is new, and there will likely be many revisions and redefinitions to how it will address issues like this. But as long as you keep to the guidelines of MVC then you will be able to reap it's benefits.

Monday, August 11, 2008 : 12:09 PM - (0 comments)

Visual Studio 2008 SP1 and .NET 3.5 SP1

This was just released a couple of hours ago, but when I tried looking for the installer, I didn't see anyone blogging about it yet. So, I'll save you the trouble of looking. Here's the URL to the installer, and more imporantly the URL for the full 850 meg ISO for those of you who perfer the full installer at one time (like me).

  • Visual Studio 2008 Service Pack 1 and .NET Framework 3.5 Service Pack 1
  • Microsoft Visual Studio 2008 Service Pack 1 (iso)

Oh, also, if you are trying to install SQL Server 2008 RTM, and you have Visual Studio 2008 installed, you'll have issues until you upgrade to SP1.

Enjoy!

Update: Aug 14 2008

If you're wondering what is contained in this service pack, then check out Lost In Tangent. Jonathan Carter is a Technical Evangelist for Microsoft, and does a great job covering SP1 goodness on his blog.

Monday, August 4, 2008 : 10:42 PM - (0 comments)

LINQ to SQL - Am I Hitting The Database?

Like most other developers who have been using LINQ for a while (and in this particular case, LINQ to SQL) - I've unknowingly made a few 'bad queries' that performed great at first, but eventually made some pages crawl. This post isn't necessarily about performance, but if you don't know how to answer that question ("am I hitting the database"), then you'll likely find yourself in a world of problems down the road when you're using LINQ to SQL.

The Scenario - "Method ... has no supported translation to SQL"

If you've seen this error before, then you probably already know where I'm going with this post. But, for those of you who haven't run across this little gem of an error, I'll fill you in.

When you write LINQ statements that act against a LINQ to SQL data context - eventually your expression will be translated into SQL statements and executed against the database. Example:

this.MyGridView.DataSource = context.Persons
   .Where(dude => dude.FirstName.StartsWith("T"));

will translate into...

SELECT [t0].[ID], [t0].[FirstName], [t0].[LastName]
FROM [dbo].[People] AS [t0]
WHERE [t0].[FirstName] LIKE @p0

What you might be taking for granted here is that the developers at Microsoft (the LINQ to SQL team in particular) spent a lot of time making 'translations' for a lot of .NET functions out there (such as "String.StartsWith"). What this means is that you as a developer may be thinking that even your functions will be translated just like magic. This, of course, isn't the case. So, the following LINQ query:

this.ExpensiveOrdersGridView.DataSource = context.Persons
   .SelectMany(person => person.GetExpensiveOrders());

will result in the following error:

A runtime error generated from a LINQ to SQL query not having a translation

Where There Be Dragons

You may be wondering, "what's the problem... if my method doesn't work, then so what?"... and that's a great question. The 'problem' here is that at first you may not fully understand that LINQ to SQL isn't able to translate this method at all, so you may tinker around a bit and find a way to "make it work."

This slight change to the LINQ query will work, and will give you the results you expect:

this.ExpensiveOrdersGridView.DataSource = context.Persons
   .ToArray()    
   .SelectMany(person => person.GetExpensiveOrders());

... but this is a huge sin. Why you might ask? Let's break down what we just told LINQ to do, and you'll see:

// Create a data context... OK, not so bad...
this.ExpensiveOrdersGridView.DataSource = context.Persons

// now download EVERY 'PERSON' RECORD IN THE DATABASE... Yikes!

   .ToArray()

// now perform that stupid function in memory.

   .SelectMany(person => person.GetExpensiveOrders());

Conclusion

There isn't much of a moral here other than "make sure you understand what your query is doing." Queries like these can linger for a while in your code without you seeing a performance problem. Then, as your database continues to grow, your app will eventually crawl to uselessness.

Please, don't be afraid of LINQ, and don't be afraid of LINQ to SQL. Just make sure you understand what you're doing (as with any other new technology).

Developer / Architect / Author

Blog Archives

  • June 2009 - (1)
  • January 2009 - (1)
  • November 2008 - (1)
  • October 2008 - (2)
  • September 2008 - (2)
  • August 2008 - (3)
  • July 2008 - (1)
  • June 2008 - (3)
  • May 2008 - (2)
  • April 2008 - (2)
  • March 2008 - (4)
  • February 2008 - (2)
  • December 2007 - (2)
  • November 2007 - (1)
  • October 2007 - (4)
  • September 2007 - (9)
  • August 2007 - (7)

Related Ads

SingingEels.com as of Mar 15 2010 - 02:59:17 PM - (0.5000256)