0

I'm looking for some guidance in terms of MVC architecture in terms of where to put the following logic.

My question is: Where should I put the logic to calculate the product rating?

I want to display some details about a product, and the rating in stars. The star rating is made up by the average user rating and an internal rating; weighted at 50% each.

Star Rating = 0.5(InternalRating) + 0.5(AverageUserRating)

I currently use the Product controller to populate 3 fields on the ViewModel:

@for (int i = 1; i <= Model.FullStars; i++)
{
    <i class="full-star"></i>
}
@if (Model.HalfStar == true)
{
    <i class="half-star"></i>
}
@for (int i = 1; i <= Model.EmptyStars; i++)
{
    <i class="empty-star"></i>
}

At the moment I loop through the UserRating result in the Produt controller to get the average rating, and the logic to split into full and empty stars lies there.

The problem with my approach is this logic has to be duplicated in various controllers which call the product.

In terms of my understanding, a good method would be to create a class:

public class ProductStars
{
    public int FullStars { get; set; }
    public bool HalfStar { get; set; }
    public int EmptyStars { get; set; }
}

Then create a DisplayTemplate for this class. Is this correct? And if so-- would I move the logic into a separate method in a utility class which accepts the product ID, gets the ratings from the database and populates the class?

Should the logic to populate the class then perhaps be moved into a table-valued function in SQL?

Thanks.

g4mbit
  • 5
  • 1
  • You should avoid fat controllers, and place all business logic into the model layer. Take a look at http://stackoverflow.com/questions/235233/asp-net-mvc-should-business-logic-exist-in-controllers/235243#235243. – rsenna Nov 03 '14 at 12:22
  • @TomTom more to the point: I *could* be aware if you could point me at the (supposedly) right direction. Simply stating that something is an "antipattern" is not enough. – rsenna Nov 03 '14 at 12:34

1 Answers1

1

Personally, I would move the ratings logic into a business logic service and have that injected into the controller via dependency injection, then create a stars rating view helper to encapsulate your HTML used for creating the stars.

This way you've encapsulated your rating business logic that could theoretically be called via a website or web service, and you've also encapsulated your HTML generation for the rating view.

This article does a good job at demonstrating how to create a custom view helper.

I would definitely recommend trying to keep your controllers as skinny as possible as highlighted in one of rsenna's earlier comments. The controller should really only be used for handling the request and talking between the view and model.

Joseph Woodward
  • 9,191
  • 5
  • 44
  • 63