Wrox Programmer Forums
Go Back   Wrox Programmer Forums > ASP.NET and ASP > Other ASP.NET > BOOK: Professional ASP.NET Design Patterns
|
BOOK: Professional ASP.NET Design Patterns
This is the forum to discuss the Wrox book Professional ASP.NET Design Patterns by Scott Millett; ISBN: 978-0-470-29278-5
Welcome to the p2p.wrox.com Forums.

You are currently viewing the BOOK: Professional ASP.NET Design Patterns section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old December 16th, 2010, 10:05 PM
Authorized User
 
Join Date: Dec 2010
Posts: 23
Thanks: 3
Thanked 2 Times in 2 Posts
Default Why is Price a "string" type in the ViewModel instead of Decimal?

Forgive me if this is a basic question, but I'm new to the layered architecture approach, and I'm learning a lot from reading the book and your code.

My question, why is the "Price" property on the "ProductView.cs" model a string type instead of a decimal type? Is it that way so that the ProductView is not responsible for formatting the display of the price amount?

I'm trying to think through how adding support for different currencies would affect the model and views. For example, if there was store-wide application setting to use, say, Euros instead of US Dollars.
 
Old December 17th, 2010, 04:44 AM
elbandit's Avatar
Wrox Author
 
Join Date: May 2007
Posts: 107
Thanks: 10
Thanked 17 Times in 15 Posts
Default

Hi ksouthworth,

Yes I want the price to be a string as I don't want any logic in the view, I want it to be as dumb as possible. The property is simply used to display the price on a screen and nothing else.

Taking your localised version needs into consideration I would pass a profile object to the service that returns a the PageView. So your controller might look something like..

Code:
 
    public class CustomerProfile
    {
        public Currency ViewingCurrency { get; set;}        
        // ... other properties...
    }
 
    public class ProductCategoryRequest
    {
        public int CategoryId { get; set;}
        public CustomerProfile CustomerProfile { get; set;}
    }
 
    // Controller action
    public ActionResult GetProductsByCategory(ProductCategoryRequest productCategoryRequest)
    {                  
        GetProductsByCategoryRequest productSearchRequest = 
            GenerateInitialProductSearchRequestFrom(productCategoryRequest);
 
        GetProductsByCategoryResponse response = 
            _productService.GetProductsByCategory(productSearchRequest);  
 
        ProductSearchResultView productSearchResultView = 
            GetProductSearchResultViewFrom(response);
 
        return View("ProductSearchResults", productSearchResultView);   
    }
The Currency would be stored in the users cookie and so you would need a Custom ModelBinder to convert the cookie value into a CustomerProfile. Alternatively you could instead pick up the cookie yourself and create the CustomerProfile object like so:

Code:
 
    public ActionResult GetProductsByCategory(int categoryId)
    {
        private CustomerProfile profile = GetCustomerProfile()
        //....            
        return View("ProductSearchResults", productSearchResultView);
    }
 
    public CustomerProfile GetCustomerProfile()
    {
        Currency currency = Currency.USD;            
 
        if (!string.IsNullOrEmpty(
                    _cookieStorageService.Retrieve(CookieDataKeys.Currency.ToString())))
            currency = Currency.Parse(
                    _cookieStorageService.Retrieve(CookieDataKeys.Currency.ToString()));
 
        return new CustomerProfile { ViewingCurrency = currency };
    }
If you were to support multiple currencies I would suggest using a value object for money rather than a decimal price. So change this code:

Code:
 
    public class Product : EntityBase<int>, IAggregateRoot
    {
        // ....
 
        public Decimal Price
        {
            get { return _title.Price; } 
        }
 
        // ....
    }
to this...

Code:
 
    public class Product : EntityBase<int>, IAggregateRoot
    {
        // ....
        public Money Price
        {
            get { return _title.Price; } 
        }
    }
 
    public class Money
    {
        private readonly decimal _price;
        private readonly Currency _currency;
 
        public Money(decimal price, Currency currency)
        {
            _price = price;
            _currency = currency;
        }
 
        public string FormattedPrice
        {
            get { return _currency.Format(_price); }
        }
 
        // ... other properties...
    }
I hope that makes sense, let me know if you have any more questions.
Cheers
Scott
 
Old December 17th, 2010, 11:22 AM
Authorized User
 
Join Date: Dec 2010
Posts: 23
Thanks: 3
Thanked 2 Times in 2 Posts
Default

When reading/writing the Product entity from/to the Product Repository, how would the Product.Price property be set ? How would the Repository know which Currency to pass in to the Money constructor?
 
Old December 17th, 2010, 11:53 AM
elbandit's Avatar
Wrox Author
 
Join Date: May 2007
Posts: 107
Thanks: 10
Thanked 17 Times in 15 Posts
Default

Hi ksouthworth,

As we are just talking about a straight currency conversion then there is no need get currency info from the database for each product, because you already have it (i.e. you must know what currency the customer wants to see products displayed in), so maybe something like this....

Code:
 
     public class Money
     {
        private readonly decimal _priceInGBP;
 
        public Money(decimal priceInGBP)
        {
            _priceInGBP = priceInGBP;
        }
 
        public string FormatPriceFor(Currency currency)
        {
            get { return currency.FormatAndApplyExchangeRateTo(_priceInGBP)); }
        }
 
        // ... other properties...
 
    }
After a bit of thinking about it that makes sense to me - your thoughts?

Cheers
Scott

Last edited by elbandit; December 17th, 2010 at 12:29 PM..
 
Old December 17th, 2010, 12:08 PM
Authorized User
 
Join Date: Dec 2010
Posts: 23
Thanks: 3
Thanked 2 Times in 2 Posts
Default

That's helping, although I'm not an NHibernate user, but I think I get the idea.

However, if my storefront just has a store-wide setting for the Currency to use then should I just store the currency along with the Product in the "OrderItems" table when the user places the order?

For example, I might start with my store in USD, so all products prices are displayed as USD and when they're purchased it would be recorded in the OrderItems as USD for that product. Later on, the store owner might decide to sell products in Euros, so he changes the store-wide currency setting to be Euros. Now all products are displayed and sold in Euros.

Not sure if this scenario even makes sense, since it seems unlikely that someone would change the currency of their store once it's been established? In my application, I'm thinking of just selling all products in Currency "X" and letting the payment processor/credit card do the automatic exchange rate conversion for foreign currencies...
 
Old December 17th, 2010, 12:27 PM
elbandit's Avatar
Wrox Author
 
Join Date: May 2007
Posts: 107
Thanks: 10
Thanked 17 Times in 15 Posts
Default

Hi ksouthworth,

I re-read your post and have updated my previous post. I was thinking about prices being set per dispatch country, i.e. you might charge $5.00 for a hat to US customers as the US has a competitive Hat industry, but $20.00 to the UK because you control the market, but this is getting into dispatch regions as well! Sorry I was getting ahead of myself! Please reread my last post to see if it answers your question.

Cheers
Scott
 
Old December 17th, 2010, 03:18 PM
Authorized User
 
Join Date: Dec 2010
Posts: 23
Thanks: 3
Thanked 2 Times in 2 Posts
Default

So, in your revised code sample, how does the Repository (NHibernate in this case) know how to populate the Product.Price property (which is of type Money) ?

The Money class itself makes sense to me, with a single constructor that takes in the decimal value amount, and the "FormatPriceFor()" method.
 
Old December 18th, 2010, 01:06 PM
elbandit's Avatar
Wrox Author
 
Join Date: May 2007
Posts: 107
Thanks: 10
Thanked 17 Times in 15 Posts
Default

In order for NHibernate to work with the Money value object you will need to add a constructor that takes no parameters like so..

Code:
 
 
     public class Money
     {
        private readonly decimal _priceInGBP;
 
        private Money()
        {    
        }
 
        public Money(decimal priceInGBP)
        {
            _priceInGBP = priceInGBP;
        }
 
        public string FormatPriceFor(Currency currency)
        {
            get { return currency.FormatAndApplyExchangeRateTo(_priceInGBP)); }
        }
 
        // ... other properties...
 
    }
Given that the database table for a Product looks like...

Column Name
-----------------------
Id
Name
Colour
PriceInGBP
Stock

You would map the money object as a component like so..

Code:
 
<class name="Product" table="Products" lazy="false" >

    <id name="Id" column="Id"  type="int" unsaved-value="0">
      <generator class="native" />
    </id>

    <property access="field.camelcase-underscore" name="Name">
      <column name="Name" not-null="true" />
    </property>
 
    <property name="Colour">
      <column name="Colour" not-null="true" />
    </property>
 
    <component access="field.camelcase-underscore" name="Price" class="Money">
      <property access="field.camelcase-underscore" 
                     column="PriceInGBP"/>
    </component>
 
   .....
</class>
Make sense?

Cheers
Scott





Similar Threads
Thread Thread Starter Forum Replies Last Post
MSXSL gives error message for "for" inside "select" ilyaz XSLT 1 December 9th, 2010 05:02 PM
<input type="Checkbox" question??? RinoDM HTML Code Clinic 1 October 26th, 2009 06:00 AM
How to theme the "Browse" button of "FileUpload" control? varunbwj BOOK: Beginning ASP.NET 3.5 : in C# and VB BOOK ISBN: 978-0-470-18759-3 2 October 14th, 2009 01:22 AM
Add a CheckBox DataColumn to my DataGridView, Null format: "" or "True" but Error: F ismailc C# 2005 0 September 25th, 2009 04:56 AM
Reading a files general property of "Type of file" GregSivers Visual Basic 2008 Essentials 7 June 3rd, 2009 09:38 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.