<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Max Akbar : Catalog System</title><link>http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx</link><description>Tags: Catalog System</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Virtual Catalog Limitation</title><link>http://blogs.msdn.com/maxakbar/archive/2008/04/05/virtual-catalog-limitation.aspx</link><pubDate>Sat, 05 Apr 2008 20:43:46 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8361106</guid><dc:creator>Max Akbar</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/maxakbar/comments/8361106.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maxakbar/commentrss.aspx?PostID=8361106</wfw:commentRss><description>&lt;p&gt;I was working with a client and they run into an error that they had reached their Virtual Catalog limit. This was an issue with the previous versions of the product (&lt;a href="http://msdn2.microsoft.com/en-us/library/ms915173.aspx"&gt;Catalog Name and Size Restrictions&lt;/a&gt; and the interop API &lt;a href="http://technet.microsoft.com/en-us/library/aa482524.aspx"&gt;IProductCatalog3::AddVirtualCatalogRule Method&lt;/a&gt; throws an exception E_CAT_VC_TOO_MANY_BASECATALOGS) but I thought that we had removed this limitation when I was with Microsoft for Commerce Server 2007. In fact I can't find this limitation anywhere documented in Commerce Server 2007 help files. It seems that this was not addressed and the stored procedure that enforces this limitation was not modified :(.&lt;/p&gt; &lt;h2&gt;Why the limitation?&lt;/h2&gt; &lt;p&gt;For whatever reason the limit is set for 84??? Why 84 not 80 as it is documented in the previous version? I don't think anyone will know but having this large amount of base catalogs per virtual catalog has a performance impact. You will have to do some testing to fully understand the consequences. If this proves to be an issue try materializing the Virtual Catalog. For more details see Vinayak's blog &lt;a href="http://blogs.msdn.com/vinayakt/archive/2004/04/28/121961.aspx"&gt;Virtual Catalogs : To materialize or not to materialize&lt;/a&gt;.&lt;/p&gt; &lt;h2&gt;What stored procedure enforces this?&lt;/h2&gt; &lt;p&gt;The stored procedure is in the &amp;lt;sitename&amp;gt;_productcatalog.dbo.ctlg_VC_AddVCRule. Line 161 has this rule:&lt;br&gt;&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="400" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="400"&gt; &lt;p&gt;if (@NumCatalogsInVc_tmp &amp;gt; 84)&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;h2&gt;What do I do if I hit this limitation?&lt;/h2&gt; &lt;p&gt;Call PSS and ask for a hotfix.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8361106" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx">Catalog System</category></item><item><title>A few things you didn't know about Commerce Server's Catalog Cache</title><link>http://blogs.msdn.com/maxakbar/archive/2007/11/22/a-few-things-you-didn-t-know-about-commerce-server-s-catalog-cache.aspx</link><pubDate>Thu, 22 Nov 2007 23:56:36 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6473317</guid><dc:creator>Max Akbar</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/maxakbar/comments/6473317.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maxakbar/commentrss.aspx?PostID=6473317</wfw:commentRss><description>&lt;p&gt;One of the most important aspect of any e-commerce is their Catalog(s) and Commerce Server provides a system that allows customers to manage and organize their products. In any e-commerce site the most profile usage the Catalog. Searches and Catalog&amp;nbsp;browsing constitutes about 70 percent or more of a site. Performance becomes an issue when you have to make that many round trip calls to the database. In order to minimize this you have to provide some mechanism for caching. Well as it happens Commerce Server's Catalog System has such a caching system.&lt;/p&gt; &lt;h2&gt;Catalog Cache&lt;/h2&gt; &lt;p&gt;Commerce Server's Catalog Cache is a lazy cache. If caching is turned on under the web.config in runtime scenarios then any request made is checked, if caching is on then we look into the cache and see if the object exists if not then a request is made to the database and the object is cached before returned to the caller.&lt;/p&gt; &lt;h2&gt;Web.config Settings&lt;/h2&gt; &lt;p&gt;The table below shows the cache settings for a Commerce Server site.&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="600" border="1" unselectable="on"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="596"&gt; &lt;p&gt;&amp;lt;catalog&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;catalogSets defaultAnonymous="Anonymous User Default CatalogSet" defaultAuthenticated="Registered User Default CatalogSet"/&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;cache enable="true" schemaTimeout="10" itemInformationCacheTimeout="10" itemHierarchyCacheTimeout="10" itemRelationshipsCacheTimeout="10" itemAssociationsCacheTimeout="10" catalogCollectionCacheTimeout="10"/&amp;gt;&lt;br&gt;&amp;lt;/catalog&amp;gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;As you can see caching is enabled and there are five items that can be cached. Instead of me explaining this which is already documented how about you do a bit of leg work. You can find more detailed info about these settings as well as the CacheConfiguration object &lt;a href="http://msdn2.microsoft.com/en-us/library/microsoft.commerceserver.catalog.cacheconfiguration_properties.aspx"&gt;here&lt;/a&gt;. Each item has a timeout period after which the item is dropped from cache.  &lt;h2&gt;Refreshing the Cache&lt;/h2&gt; &lt;p&gt;Catalog Cache can be refreshed by using Catalog Manager, Staging Services or hitting a specific URL. This URL is protected and by default only administrators can access it. The URL is an httpHandler and this setting can also be found at the web.config.&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="600" border="1" unselectable="on"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="596"&gt; &lt;p&gt;&amp;lt;httpHandlers&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="SiteCacheRefresh.axd" type="Microsoft.CommerceServer.Runtime.SiteCacheRefresh, Microsoft.CommerceServer.Runtime, Version=6.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 "/&amp;gt;&lt;br&gt;&amp;lt;/httpHandlers&amp;gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;To add an account that accesses this URL you must do so under the web.config. &lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="600" border="1" unselectable="on"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="596"&gt; &lt;p&gt;&amp;lt;location path="SiteCacheRefresh.axd"&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;system.web&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;authorization&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;allow roles="BUILTIN\Administrators"/&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;allow roles="VORDEFINIERT\Administratoren"/&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;allow roles="BUILTIN\Administrateurs"/&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;deny users="*"/&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;deny users="?"/&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/authorization&amp;gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/system.web&amp;gt;&lt;br&gt;&amp;lt;/location&amp;gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;h2&gt;Cache Size&lt;/h2&gt; &lt;p&gt;Commerce Server's Catalog items are typed DataSets and can be as large as 300KB per item. If you have a large Catalog the cache size can grow pretty big. To minimize this you can set the Cache Timeout to a smaller amount like 10 minutes. If I remember correctly this is the number of minutes that we tested the Commerce Server's Catalog Performance.&lt;/p&gt; &lt;h2&gt;Where is the Cache?&lt;/h2&gt; &lt;p&gt;Commerce Server utilizes ASP.NET cache. The following code will dump all the cache keys.&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="600" border="1" unselectable="on"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="596"&gt; &lt;p&gt;foreach (DictionaryEntry key in Cache)&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Response.Write(key.Key.ToString());&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Response.Write("&amp;lt;br /&amp;gt;");&lt;br&gt;}&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;The following is the cache out put&amp;nbsp;from Starter Site. &lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="600" border="1" unselectable="on"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="596"&gt; &lt;p&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogsInCatalogSetByName,&lt;br&gt;Registered User Default CatalogSet&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogLanguages,&lt;br&gt;Adventure Works Catalog&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogsInCatalogSetByName,&lt;br&gt;Anonymous User Default CatalogSet&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetParentCategories,&lt;br&gt;Adventure Works Catalog,Adventure Works Catalog,en-US,14,*,False&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertiesInCatalog,&lt;br&gt;Adventure Works Catalog&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetProductOIDAndType,&lt;br&gt;Adventure Works Catalog,AW099-15,en-US,,,,,,&lt;br&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;ctlg_QueryCatalogInfo|Adventure Works Catalog|AW099-15||en-US&lt;/strong&gt;&lt;br&gt;&lt;/font&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,&lt;br&gt;IntroductionDate&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetDefinitions,,Crampon,&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetProductProperties,&lt;br&gt;Adventure Works Catalog,False,14,ProductCode,VariantCode,&lt;br&gt;Adventure Works Catalog,en-US,NoJoin,,,,P.BaseCatalogName,CategoryName,&lt;br&gt;P.oid,DefinitionName,IsSearchable,cy_list_price,UseCategoryPricing,&lt;br&gt;i_ClassType,CatalogName,ProductId,OrigProductId,&lt;br&gt;VariantId,OrigVariantId,PrimaryParentCategory,DisplayName,Timestamp,&lt;br&gt;OriginalPrice,LastModified,ParentOId,True,,,False,False,False,True,False,0&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogGlobalProperties,&lt;br&gt;Adventure Works Catalog,en-US&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,Test&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,Image_filename&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetRootProducts,&lt;br&gt;Adventure Works Catalog,en-US,False,NoJoin,,,, &lt;br&gt;[CategoryName],[ProductID],[CatalogName],[i_ClassType],[DisplayName],[cy_list_price],&lt;br&gt;[BaseCatalogName],[oid],[OrigProductId],[DefinitionName],&lt;br&gt;[PrimaryParentCategory],[UseCategoryPricing],1,10,,True,0,True,,,False,False,False,True,False,0,*&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,Image_height&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCategoryOID,Adventure Works Catalog,,en-US,,,,&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_VC_BC_GetDependentCatalogs,&lt;br&gt;Adventure Works Catalog,1,2147483646,,True,0,en-US&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,ProductCode&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogSetInfoByName,Registered User Default CatalogSet&lt;br&gt;CatalogHelper.CatalogsForAnonymousUser&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,Image_width&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCategoryOID,Adventure Works Catalog,,en-US,,,False,False&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogProperties,Adventure Works Catalog,en-US,,&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetRootProducts,Adventure Works Catalog,en-US,False,NoJoin,,,,*,&lt;br&gt;1,2147483646,,True,0,True,,,False,False,False,True,False,0,*&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,OnSale&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetRootCategories,&lt;br&gt;Adventure Works Catalog,en-US,False,*,1,2147483646,,True,0&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCategoryProperties,Adventure Works Catalog,-1,&lt;br&gt;Adventure Works Catalog,en-US,BaseCatalogName,CategoryName,&lt;br&gt;OrigCategoryName,oid,DefinitionName,IsSearchable,cy_list_price,&lt;br&gt;UseCategoryPricing,i_ClassType,CatalogName,ProductId,OrigProductId,&lt;br&gt;VariantId,OrigVariantId,PrimaryParentCategory,DisplayName,&lt;br&gt;Timestamp,OriginalPrice,LastModified,ParentOId,False&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogProperties,Adventure Works Catalog,,,&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogSetInfoByName,Anonymous User Default CatalogSet&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetDefinitionProperties,Crampon,&lt;br&gt;CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,ProductSize&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;h2&gt;So here is something you may not have known&lt;/h2&gt; &lt;p&gt;When you add an item to basket and execute the basket pipeline component there are two components that interact with the Catalog System &lt;a href="http://msdn2.microsoft.com/en-us/library/ms961004.aspx"&gt;QueryCatalogInfo&lt;/a&gt; and &lt;a href="http://msdn2.microsoft.com/en-us/library/ms959488.aspx"&gt;RequiredProdInfo&lt;/a&gt;. The &lt;a href="http://msdn2.microsoft.com/en-us/library/ms961004.aspx"&gt;QueryCatalogInfo&lt;/a&gt; is also dependant upon the cache values under the web.config. Why is that? The &lt;a href="http://msdn2.microsoft.com/en-us/library/ms961004.aspx"&gt;QueryCatalogInfo&lt;/a&gt; checks to make sure that the lineitems are in synch with the Catalog System and if not then marks them as deleted and the &lt;a href="http://msdn2.microsoft.com/en-us/library/ms959488.aspx"&gt;RequiredProdInfo&lt;/a&gt;&amp;nbsp;removes the lineitem from the basket. The &lt;a href="http://msdn2.microsoft.com/en-us/library/ms961004.aspx"&gt;QueryCatalogInfo&lt;/a&gt; also keeps a cache of it's own separate from sites items cache. This increases the cache size and the same cache configuration values under the web.config&amp;nbsp;are applied to the &lt;a href="http://msdn2.microsoft.com/en-us/library/ms961004.aspx"&gt;QueryCatalogInfo&lt;/a&gt; component cache. &lt;/p&gt; &lt;p&gt;As you can see there are two processes that depend on one configuration setting. under the "Where is the cache?" section in&amp;nbsp;the second table,&amp;nbsp;notice the red text that defines the QueryCatalogInfo cache item.&lt;/p&gt; &lt;h2&gt;How to decouple this Configuration&lt;/h2&gt; &lt;p&gt;There maybe scenarios that you will need to disable the Commerce Server's Cache as you may have implemented your own caching mechanism. Which means that by disabling the Commerce Server's Catalog Cache you will suffer performance hit in the checkout process.&lt;/p&gt; &lt;p&gt;The &lt;a href="http://msdn2.microsoft.com/en-us/library/microsoft.commerceserver.catalog.cacheconfiguration_properties.aspx"&gt;CacheConfiguration&lt;/a&gt; is passed as a&amp;nbsp;context to the pipeline component so it's possible to disable the web.config Cache and create your own pipeline component that sets a cache settings for the &lt;a href="http://msdn2.microsoft.com/en-us/library/ms961004.aspx"&gt;QueryCatalogInfo&lt;/a&gt;&amp;nbsp;component. Just make sure that this component is placed before the &lt;a href="http://msdn2.microsoft.com/en-us/library/ms961004.aspx"&gt;QueryCatalogInfo&lt;/a&gt;&amp;nbsp;component.&lt;/p&gt; &lt;p&gt;The following code enables you to set your own cache settings.&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="600" border="1" unselectable="on"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top" width="596"&gt; &lt;p&gt;public int Execute(object pdispOrder, object pdispContext, int lFlags)  &lt;p&gt;{  &lt;p&gt;CacheConfiguration cacheConfig = new CacheConfiguration();  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cacheConfig.CacheEnabled = true;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cacheConfig.ItemInformationCacheTimeout = 10;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((IDictionary)pdispContext)["CatalogCacheConfiguration"] = cacheConfig;  &lt;p&gt;return 1;  &lt;p&gt;}&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;This post was done with consultation of Ben Taylor from Shape Factory LTD in UK.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6473317" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx">Catalog System</category><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Architectural+and+Design/default.aspx">Architectural and Design</category></item><item><title>Catalog Web Service and SetJoin API Configuration</title><link>http://blogs.msdn.com/maxakbar/archive/2007/07/14/catalog-web-service-and-setjoin-api-configuration.aspx</link><pubDate>Sun, 15 Jul 2007 09:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3874558</guid><dc:creator>Max Akbar</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/maxakbar/comments/3874558.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maxakbar/commentrss.aspx?PostID=3874558</wfw:commentRss><description>&lt;P&gt;I was debugging why the Catalog Web Service was not working with my Set Join API and found that the documentation was pointing to the runtime site web.config values (which is incorrect). What this means is the Catalog Web Service web.config is configured differently slightly different. I worked with the Product Group and we found the solution. This will be fixed in the next doc refresh but I thought I post here just in case someone is interested.&lt;/P&gt;
&lt;P&gt;You will need to add a Join table name for every SQL object you whish to join. This is done for security reason you don’t want just anyone to be able to join to whatever table. The other options are passed using the JoinTableInformation object.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;JoinTable&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;JoinTable&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/FONT&gt;&lt;FONT size=2&gt;joinTable_A&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;JoinTable&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;JoinTable&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/FONT&gt;&lt;FONT size=2&gt;joinTable_B&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;JoinTable&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a31515 size=2&gt;JoinTable&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3874558" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx">Catalog System</category></item><item><title>Looking for Commerce Server Training?</title><link>http://blogs.msdn.com/maxakbar/archive/2007/07/01/looking-for-commerce-server-training.aspx</link><pubDate>Mon, 02 Jul 2007 05:28:49 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3654468</guid><dc:creator>Max Akbar</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/maxakbar/comments/3654468.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maxakbar/commentrss.aspx?PostID=3654468</wfw:commentRss><description>&lt;p&gt;Look no further. I have just completed my first video tutorial for Commerce Server Catalog System.&amp;nbsp;It's about six hours of video and 850 megs. For more details on how to get it and when it will be available see &lt;a href="http://www.commerceservertraining.com/Training_Outline.html"&gt;Training Outline @ Commerce Server Training&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;I will be working on the next video and should have it out sooner. I learned a lot doing this video about and I will look forward to your feedback on how to improve :).&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3654468" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx">Catalog System</category></item><item><title>Do you have your eye on it CS2007 SP1</title><link>http://blogs.msdn.com/maxakbar/archive/2007/06/22/do-you-have-your-eye-on-it-cs2007-sp1.aspx</link><pubDate>Fri, 22 Jun 2007 10:13:06 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3454379</guid><dc:creator>Max Akbar</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/maxakbar/comments/3454379.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maxakbar/commentrss.aspx?PostID=3454379</wfw:commentRss><description>&lt;p&gt;Commerce Server 2007 Service Pack 1 is due out end of June if all goes well :),&amp;nbsp;keep your eye on it. There are two things note worthy:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;Replication of Orders and Profiles Database&lt;br&gt;&lt;br&gt;&lt;/strong&gt;This was a design change request that was introduced right after the product went live so a lot of testing wen into it. The replication will allow to have more than one Data Centers acting as active active. If one data center goes down the other can pick up the load. Should be interesting to read all the details on how to do this.&lt;br&gt;&lt;/li&gt; &lt;li&gt;&lt;strong&gt;Using Tabular functions for Catalogs SetJoin API&lt;br&gt;&lt;/strong&gt;&lt;br&gt;I am very proud of this as I had a hand in it :). I had my hand in lots of cookie jars when I was at Microsoft, still do&amp;nbsp;;). Originally the product only supported tables and views to be joined with the Product object. Some scenarios made it impossible to use the SetJoin API. Imagine if you had dynamic pricing scenario, you could write a function that runs a select statement based on parameters you passed it and the product API would then return you some results that you could then perform validations and selecting the correct price. What if you needed to search a table before the join occurred? Well now you can. I am very eager to see how this is implemented and how people will use.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;And they say Microsoft doesn't listen to it's customers :). I am very proud to have been part of the product group developing such a great software. Make sure to read every little bit of what's new.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3454379" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Orders+System/default.aspx">Orders System</category><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx">Catalog System</category><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Profile+System/default.aspx">Profile System</category></item><item><title>Adding Image Management to your Commerce Site Part (V)</title><link>http://blogs.msdn.com/maxakbar/archive/2006/12/16/adding-image-management-to-your-commerce-site-part-v.aspx</link><pubDate>Sun, 17 Dec 2006 02:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1306888</guid><dc:creator>Max Akbar</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/maxakbar/comments/1306888.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maxakbar/commentrss.aspx?PostID=1306888</wfw:commentRss><description>
&lt;STYLE type=text/css&gt;
 p.msonormal
	{margin-top:0in;
	margin-right:0in;
	margin-bottom:10.0pt;
	margin-left:0in;
	line-height:115%;
	font-size:11.0pt;
	font-family:"Calibri","sans-serif";
	}
&lt;/STYLE&gt;

&lt;P&gt;Welcome to the last post of our Image Management System, this certainly has been a long post. I hope that by now you see some value in taking some time and designing your system instead of coding first and now some code:). If you have not created any of the wire frame projects now would be a good time to look at &lt;A href="http://blogs.msdn.com/maxakbar/archive/2006/11/28/adding-image-management-to-your-commerce-site-part-iv.aspx" mce_href="http://blogs.msdn.com/maxakbar/archive/2006/11/28/adding-image-management-to-your-commerce-site-part-iv.aspx"&gt;Adding Image Management to your Commerce Site Part (IV)&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;I am going to include the code as part of this post see attachment at the bottom. Also we are going to walk through one of the operations instead of having the complete end to end development. I want to minimize the length of this post :). So by walking through one operation you should have a good understanding of how to fill the rest of the operations.&lt;/P&gt;
&lt;H2&gt;Operations&lt;/H2&gt;
&lt;P&gt;We need to define the operations for Image Management this is defined for us based on the Catalog UI forms and Controls we created to display images.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Get Catalog Languages 
&lt;UL&gt;
&lt;LI&gt;You don't need a method for this you can get this from the CatalogContext. You use this to populate the languages field when the user is uploading an image. Remember that when we started this post we would support only one language if you have requirements for multiple languages for images then you have a bit work a head of you.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Get File Types 
&lt;UL&gt;
&lt;LI&gt;We need to get the supported file types when the user is uploading images.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Get Images 
&lt;UL&gt;
&lt;LI&gt;This method is the main method for getting a list of all images to be displayed under the Image tab in &lt;STRONG&gt;ProductCatalogEdit.cs&lt;/STRONG&gt; form.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Search Images 
&lt;UL&gt;
&lt;LI&gt;This method is invoke by the Search tab in our &lt;STRONG&gt;AssociateImages.cs &lt;/STRONG&gt;form.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Add Images 
&lt;UL&gt;
&lt;LI&gt;This method is invoked when the user has uploaded images and select OK under the upload tab from &lt;STRONG&gt;AssociateImages.cs &lt;/STRONG&gt;form.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Remove Image 
&lt;UL&gt;
&lt;LI&gt;Remove just one image and disassociate with the product.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Sort Images 
&lt;UL&gt;
&lt;LI&gt;You may need this method to sort the images under the Image tab in &lt;STRONG&gt;ProductCatalogEdit.cs&lt;/STRONG&gt; form.&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;H2&gt;Image Management System code&lt;/H2&gt;
&lt;P&gt;We are going to add some code to get the Image management System up and running. for this sample we are only going to work with the Get Images operation. The following references needs to be added to our &lt;STRONG&gt;ImageManagementSystem&lt;/STRONG&gt; project:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Microsoft.CommerceServer.Runtime&lt;BR&gt;ImageModule&lt;BR&gt;Microsoft.Practices.EnterpriseLibrary.Data&lt;BR&gt;Microsoft.Practices.EnterpriseLibrary.Common&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The following Web References needs to be added to our project:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;localhost&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Now lets add some methods, properties and members.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;From the solution explorer navigate to &lt;STRONG&gt;ImageManagementSystem &lt;/STRONG&gt;project. 
&lt;LI&gt;Right click on the project and add a new folder called UML. We will use this folder to generate our Bridge Pattern. 
&lt;LI&gt;Right click on the UML folder you just created and add a new item &lt;STRONG&gt;Class Diagram &lt;/STRONG&gt;and name it &lt;STRONG&gt;ImageManagement.cd&lt;/STRONG&gt;. 
&lt;LI&gt;Add the following classes under the &lt;STRONG&gt;ImageManagement.cd&lt;/STRONG&gt; diagram. 
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;ImageSiteAgent&lt;/STRONG&gt; 
&lt;UL&gt;
&lt;LI&gt;Sets the Imagecontext to connect to the Product Catalog database for image tables.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;STRONG&gt;ImageServiceAgent&lt;/STRONG&gt; 
&lt;UL&gt;
&lt;LI&gt;Sets the Imagecontext to connect to the Catalog Image Service&amp;nbsp;for image objects to be accessed through HTTP Soap.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;STRONG&gt;ImageContext&lt;/STRONG&gt; 
&lt;UL&gt;
&lt;LI&gt;Context for access to the Image APIs.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;STRONG&gt;AbstractImage&lt;/STRONG&gt; 
&lt;UL&gt;
&lt;LI&gt;Defines the abstraction's interface. 
&lt;LI&gt;Maintains a reference to an object of type Implementor.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;STRONG&gt;ImageImplementor&lt;/STRONG&gt; 
&lt;UL&gt;
&lt;LI&gt;Defines the interface for Image implementation classes.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;STRONG&gt;ImageWebServiceAccess&lt;/STRONG&gt; 
&lt;UL&gt;
&lt;LI&gt;Implements the ImageImplementor interface and defines its concrete implementation to access our Image Web Service.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;&lt;STRONG&gt;ImageDatabaseAccess&lt;/STRONG&gt; 
&lt;UL&gt;
&lt;LI&gt;Implements the ImageImplementor interface and defines its concrete implementation to access the Product Catalog Database for image objects.&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Make sure that &lt;STRONG&gt;ImageImplementor&lt;/STRONG&gt; is an internal abstract class. 
&lt;LI&gt;&lt;STRONG&gt;ImageDatabaseAccess&lt;/STRONG&gt; and &lt;STRONG&gt;ImageWebServiceAccess&lt;/STRONG&gt; must be internal. 
&lt;LI&gt;&lt;STRONG&gt;&lt;STRONG&gt;ImageSiteAgent&lt;/STRONG&gt;, &lt;STRONG&gt;ImageServiceAgent&lt;/STRONG&gt;, ImageContext&lt;/STRONG&gt; and &lt;STRONG&gt;AbstractImage&lt;/STRONG&gt; are public. 
&lt;LI&gt;Now we will implement the interfaces for our &lt;STRONG&gt;ImageImplementor&lt;/STRONG&gt;. Remember for this sample we will only create one operation. 
&lt;UL&gt;
&lt;LI&gt;From the &lt;STRONG&gt;ImageManagement.cd&lt;/STRONG&gt; diagram right click on &lt;STRONG&gt;ImageImplementor &lt;/STRONG&gt;class and select &lt;STRONG&gt;Add &lt;/STRONG&gt;then &lt;STRONG&gt;Method&lt;/STRONG&gt;. Name the new method &lt;STRONG&gt;RetrieveImageRecords&lt;/STRONG&gt;. 
&lt;LI&gt;Right click on the &lt;STRONG&gt;RetrieveImageRecords&lt;/STRONG&gt; method and select &lt;STRONG&gt;Class Details&lt;/STRONG&gt;. 
&lt;LI&gt;From the &lt;STRONG&gt;Class Details&lt;/STRONG&gt; select &lt;STRONG&gt;RetrieveImageRecords&lt;/STRONG&gt; and add DataSet as the return data type. 
&lt;LI&gt;From the &lt;STRONG&gt;Class Details&lt;/STRONG&gt; select &lt;STRONG&gt;RetrieveImageRecords&lt;/STRONG&gt; and expand it. Next add a new parameter ProductID as type string.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Now from the &lt;STRONG&gt;Toolbox&lt;/STRONG&gt; select the inheritance object and create two relationship between &lt;STRONG&gt;ImageDatabaseAccess&lt;/STRONG&gt; and &lt;STRONG&gt;ImageWebServiceAccess&lt;/STRONG&gt; inheriting from &lt;STRONG&gt;ImageImplementor&lt;/STRONG&gt;. 
&lt;LI&gt;Create a constructor for &lt;STRONG&gt;ImageDatabaseAccess&lt;/STRONG&gt; and &lt;STRONG&gt;ImageWebServiceAccess.&lt;/STRONG&gt; The &lt;STRONG&gt;ImageWebServiceAccess&lt;/STRONG&gt; constructor will take &lt;STRONG&gt;ImageServiceAgent &lt;/STRONG&gt;as a parameter and &lt;STRONG&gt;ImageDatabaseAccess&lt;/STRONG&gt; will have &lt;STRONG&gt;ImageSiteAgent&lt;/STRONG&gt;. 
&lt;LI&gt;Right click on &lt;STRONG&gt;ImageDatabaseAccess&lt;/STRONG&gt; and select &lt;STRONG&gt;IntelliSense &lt;/STRONG&gt;then select &lt;STRONG&gt;Override Members. Form the Override Members dialog &lt;/STRONG&gt;select the methods you want to override in our case RetrieveImageRecords. Override the methods for &lt;STRONG&gt;ImageWebServiceAccess&lt;/STRONG&gt; as well. Under the &lt;STRONG&gt;ImageDatabaseAccess&lt;/STRONG&gt; class create a member &lt;STRONG&gt;db &lt;/STRONG&gt;as type Database. Under &lt;STRONG&gt;ImageWebServiceAccess &lt;/STRONG&gt;create two members &lt;STRONG&gt;_uri&lt;/STRONG&gt; as type &lt;STRONG&gt;Uri&lt;/STRONG&gt; and &lt;STRONG&gt;_imageWebServiceas&lt;/STRONG&gt; type &lt;STRONG&gt;ImageWebService&lt;/STRONG&gt;. 
&lt;LI&gt;Next from the Toolbox select Association object and create an association between &lt;STRONG&gt;AbstractImage&lt;/STRONG&gt; and &lt;STRONG&gt;ImageImplementor &lt;/STRONG&gt;and name the association &lt;STRONG&gt;ImageImplementor&lt;/STRONG&gt;. Modify the code for &lt;STRONG&gt;ImageImplementor&lt;/STRONG&gt; method so that it has only a set accessor. 
&lt;LI&gt;Right click &lt;STRONG&gt;AbstractImage&lt;/STRONG&gt; class and add a private member &lt;STRONG&gt;imageImplementor &lt;/STRONG&gt;and a method &lt;STRONG&gt;GetImages&lt;/STRONG&gt;. 
&lt;LI&gt;&lt;STRONG&gt;GetImages &lt;/STRONG&gt;method accepts a string type ProductID as parameter and returns a DataSet. 
&lt;LI&gt;In &lt;STRONG&gt;ImageContext&lt;/STRONG&gt; class create two methods called &lt;STRONG&gt;Create&lt;/STRONG&gt;. One method will accept &lt;STRONG&gt;ImageServiceAgent &lt;/STRONG&gt;and the other &lt;STRONG&gt;ImageSiteAgent&lt;/STRONG&gt;.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Your completed diagram should look like the image Bellow:&lt;BR&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:635cd245-0d72-47f8-a47b-1ec5f5ff2869 contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 696px; HEIGHT: 460px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1249186/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1249186/original.aspx"&gt;&lt;/DIV&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Your Image Management System project code should look like the following:&lt;/P&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:e4f7846f-2086-473d-94ea-c88bb9dfbb67 contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 847px; HEIGHT: 5396px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1250028/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1250028/original.aspx"&gt;&lt;/DIV&gt;
&lt;P&gt;Now lets talk code for a while.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;ImageServiceAgent &lt;/STRONG&gt;and &lt;STRONG&gt;ImageSiteAgent &lt;/STRONG&gt;works similar to &lt;STRONG&gt;CatalogSiteAgent &lt;/STRONG&gt;and &lt;STRONG&gt;CatalogServiceAgent &lt;/STRONG&gt;I have only created a few methods to show you how you can create your own Agents based on your requirements you can add\remove what you need.&lt;/P&gt;
&lt;P&gt;In our &lt;STRONG&gt;AbstractImage&lt;/STRONG&gt; class we code our method so that it calls our Implementor's method to retrieving images.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;ImageWebServiceAccess&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;In the &lt;STRONG&gt;ImageWebServiceAccess's &lt;/STRONG&gt;constructor we need to set the Image Web Proxy's URL and the credentials for accessing the Web Service.&lt;/P&gt;
&lt;P&gt;The &lt;STRONG&gt;RetrieveImageRecords&lt;/STRONG&gt; method we call our Web Service Method to get our Images (we will code the Web Service later on).&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;ImageDatabaseAccess&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;In&amp;nbsp;the &lt;STRONG&gt;ImgeDatabaseAccess's&lt;/STRONG&gt; constructor we need to get the Product Catalog connection string and use it to create Database object using the EnterpriseLib Data Block. Now that we have a database object we can query our Image SQL objects.&lt;/P&gt;
&lt;P&gt;So in our &lt;STRONG&gt;RetrieveImageRecords&lt;/STRONG&gt; method we call &lt;STRONG&gt;img_GetImageProduct&lt;/STRONG&gt; &lt;STRONG&gt;Stored Procedure &lt;/STRONG&gt;and return the results back to our caller.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;Note: You may want to&amp;nbsp;sign EnterpriseLibrary projects if you are going to add your assemblies into the GAC.&amp;nbsp;&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;H2&gt;Image Module Code&lt;/H2&gt;
&lt;P&gt;Add the following references to your &lt;STRONG&gt;Image Module&lt;/STRONG&gt; Project:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Microsoft.CommerceServer.Runtime&lt;BR&gt;ImageManagementSystem&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Now lets add some methods, properties and members. Create a UML folder under the Image Module Project. Under the UML folder add a class diagram object. In the Diagram designer windows add a new class and name it &lt;STRONG&gt;WebImageModule.cs&lt;/STRONG&gt;. &lt;/P&gt;
&lt;P&gt;Add the following private Fields&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;disposed 
&lt;UL&gt;
&lt;LI&gt;Bool type has this instance been disposed&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;imageConnectionstringResource 
&lt;UL&gt;
&lt;LI&gt;"product Catalog" key will be used to get the connection string&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;imageresource 
&lt;UL&gt;
&lt;LI&gt;Reference to a single instance (singleton) of the Image Context class&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;imageResourceKey 
&lt;UL&gt;
&lt;LI&gt;The key name used to store the resource in the HttpContext Items collection&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Add the following methods&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Dispose 
&lt;UL&gt;
&lt;LI&gt;returns void accepting bool value (true if this was called from the Dispose method, false if called from the finalizer)&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Init 
&lt;UL&gt;
&lt;LI&gt;A public method returning void and accepting HttpApplication as a parameter. The current Application instance (ASP.Net maintains a pool of these for every ASP.Net application.&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;OnBeginRequest 
&lt;UL&gt;
&lt;LI&gt;BeginRequest event handler.&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Add the following properties&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;ImageContext 
&lt;UL&gt;
&lt;LI&gt;A public static method. Used to set and retrieve the ImageContext.&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Your class Diagram should look like the following:&lt;BR&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:bab72c8a-1d64-4d9a-b6e3-183ac1803c57 contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 248px; HEIGHT: 266px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1250768/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1250768/original.aspx"&gt;&lt;/DIV&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Your Image Module project code should look like the following:&lt;BR&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:9be58ff4-adee-4fbd-b956-d7073687d35a contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 808px; HEIGHT: 2027px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1250930/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1250930/original.aspx"&gt;&lt;/DIV&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The ImageContext property code explained:&lt;/P&gt;
&lt;P&gt;We use the Singleton pattern to get an ImageContext using site Agent. The site name is retrieved from the CommerceContext. We should have a dependency on CommerceApplicationModule, the reason for this is that we depend on this object to get our sitename.&lt;/P&gt;
&lt;H2&gt;Catalog Web Service Code&lt;/H2&gt;
&lt;P&gt;Modify the web.config so we have the &lt;STRONG&gt;CommerceApplicationModule&lt;/STRONG&gt; loaded and add a configuration section to hold our site name. I have outlined the section for you to modify.&lt;/P&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:7076cc45-491a-4dc5-92b9-cab661c22f12 contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 1044px; HEIGHT: 1006px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1250985/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1250985/original.aspx"&gt;&lt;/DIV&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;web.config&lt;/STRONG&gt; walk through, You need to add a section handler under the sectiongroup tag so our CommerceAppication can read the site name. Next we add application tag for Commerce Server's siteName and finally we add two modules the CommerceApplicationModule and our ImageModule.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Add a new new amsx file and call it ImageWebService. 
&lt;LI&gt;Add a new web method RetrieveImageRecords. 
&lt;LI&gt;You class should look like the following:&lt;BR&gt;&lt;BR&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:2de058a5-599a-45ac-a24e-2ae6cdd4e64e contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 666px; HEIGHT: 649px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1251017/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1251017/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Code walk through, in the WebService constructor set the field to current ImageContext. So in each method all you have to do is call the&amp;nbsp;ImageContext's methods.&lt;/P&gt;
&lt;H2&gt;Catalog Manager Code&lt;/H2&gt;
&lt;P&gt;Now lets tie it all together but first compile your solution to make sure that we have no errors.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;In Catalog Manager add &lt;STRONG&gt;ImageManagementSystem&lt;/STRONG&gt; reference 
&lt;LI&gt;In &lt;STRONG&gt;LaunchPad.cs&lt;/STRONG&gt; we need to create an &lt;STRONG&gt;ImageContext&lt;BR&gt;&lt;/STRONG&gt;&lt;BR&gt;add &lt;STRONG&gt;using ImageManagementSystem; &lt;/STRONG&gt;statement&lt;BR&gt;&lt;BR&gt;add &lt;STRONG&gt;private static ImageContext imageContext = new ImageContext();&lt;BR&gt;&lt;/STRONG&gt;&lt;/LI&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:e08ae921-7b88-4187-9d07-7c4223de5aac contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 596px; HEIGHT: 359px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1305669/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1305669/original.aspx"&gt;&lt;/DIV&gt;&lt;STRONG&gt;&lt;BR&gt;&lt;BR&gt;&lt;/STRONG&gt;add internal property &lt;BR&gt;&lt;STRONG&gt;/// &amp;lt;summary&amp;gt;&lt;BR&gt;/// Property to get Current Image Context&lt;BR&gt;/// &amp;lt;/summary&amp;gt;&lt;BR&gt;internal static ImageContext CurrentImageContext&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; get&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return imageContext;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:a8d07682-aecf-4e9f-a2a4-7f9da74e41fc contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 433px; HEIGHT: 399px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1305670/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1305670/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;&lt;BR&gt;&lt;/STRONG&gt;next add the following code under the&amp;nbsp;&lt;STRONG&gt;LoadDefaultSiteUrlConnection&lt;/STRONG&gt; method right&amp;nbsp;after creating the Catalog Context&amp;nbsp;&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;ImageServiceAgent imageServiceAgent = new ImageServiceAgent();&lt;BR&gt;imageServiceAgent.Credentials = LaunchPad.currentCatalogContext.ServiceAgent.Credentials;&lt;/STRONG&gt; &lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;Uri imageUri = new Uri(LaunchPad.currentCatalogContext.ServiceAgent.ServiceUri.AbsoluteUri.Replace("CatalogWebService.asmx", "ImageWebService.asmx"));&lt;BR&gt;imageServiceAgent.ServiceUri = imageUri;&lt;/STRONG&gt; &lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;LaunchPad.currentImageContext.Create(imageServiceAgent);&lt;/STRONG&gt; &lt;BR&gt;&lt;BR&gt;So here is why we did what we did. We need the private variable currentImageContext to encapsulate the internal property &lt;STRONG&gt;CurrentImageContext&lt;/STRONG&gt;. We initialize the ImageContext under the &lt;STRONG&gt;LoadDefaultSiteUrlConnection&lt;/STRONG&gt; method using our private variable currentImageContext.&lt;BR&gt;&lt;BR&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:11964601-444b-4243-8fbf-4cb561352d63 contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 953px; HEIGHT: 413px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1305671/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1305671/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;&lt;BR&gt;
&lt;LI&gt;Modify the &lt;STRONG&gt;CatalogManagerObjectFactory.cs &lt;/STRONG&gt;under the controller folder.&lt;BR&gt;&lt;BR&gt;Add enum to &lt;STRONG&gt;CatalogManagerItem &lt;/STRONG&gt;ViewProductImages&lt;BR&gt;then add code to&amp;nbsp;&lt;STRONG&gt;CatalogManagerObjectFactory &lt;/STRONG&gt;class's &lt;STRONG&gt;Create &lt;/STRONG&gt;method&lt;BR&gt;
&lt;P&gt;&lt;STRONG&gt;case CatalogManagerItem.ViewProductImages:&lt;BR&gt;objectToCreate = new ProductCatalogImages();&lt;BR&gt;break;&lt;BR&gt;&lt;BR&gt;&lt;/STRONG&gt;We added the enum so that we our factory can create the image tab based on the code we added in the switch statement of &lt;STRONG&gt;itemToCreate&lt;/STRONG&gt;.&lt;BR&gt;&lt;BR&gt;add code to &lt;STRONG&gt;CatalogItemEdit_Load&lt;/STRONG&gt; method of &lt;STRONG&gt;CatalogItemEdit &lt;/STRONG&gt;under the Dialog folder.&lt;BR&gt;&lt;STRONG&gt;pages.Add(CatalogManagerItem.ProductCatalogImages, "Images");&lt;/STRONG&gt; &lt;BR&gt;&lt;BR&gt;Once our factory knows how to create an image tab we need to add it to our form.&lt;/P&gt;
&lt;LI&gt;Now add code to &lt;STRONG&gt;ProductCatalogImages.cs&lt;/STRONG&gt; form to display the images under the &lt;STRONG&gt;Wizards &lt;/STRONG&gt;folder. Your code should look like below:&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:6e2ddff6-a454-4896-a7ea-183833563af5 contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 873px; HEIGHT: 1702px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1305672/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1305672/original.aspx"&gt;&lt;/DIV&gt;&lt;/OL&gt;
&lt;H2&gt;What About All The Other Methods&lt;/H2&gt;
&lt;P&gt;By now we have walked through one operation and you should be familiar enough with the projects to create the rest on your own, good luck.&lt;/P&gt;
&lt;H2&gt;How to upload Images&lt;/H2&gt;
&lt;P&gt;There are many ways to upload images to a file server you can use &lt;A href="http://msdn2.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx"&gt;FtpWebRequest Class&lt;/A&gt;&amp;nbsp;,&lt;STRONG&gt;&amp;nbsp;&lt;/STRONG&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/system.net.httpwebrequest.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.net.httpwebrequest.aspx"&gt;HttpWebRequest&lt;/A&gt;&lt;STRONG&gt; &lt;/STRONG&gt;(using the PUT verb) and Web Service.&amp;nbsp;Web Service&amp;nbsp;code sample:&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;You would need a method to read the image from the file system&lt;/P&gt;
&lt;P&gt;FileStream fs = new FileStream(textBox1.Text, FileMode.Open);&lt;BR&gt;Byte[] image = new Byte[fs.Length];&lt;BR&gt;fs.Read(image, 0, (int)fs.Length);&lt;BR&gt;fs.Close();&lt;BR&gt;localhost.ImageUpload ws = new localhost.ImageUpload();&lt;BR&gt;ws.Credentials = System.Net.CredentialCache.DefaultCredentials;&lt;BR&gt;ws.UplaodImage(image);&lt;BR&gt;
&lt;P&gt;From the Web Service you would accept a byte array of our image and save it to the file system&lt;/P&gt;
&lt;P&gt;[WebMethod]&lt;BR&gt;public void UplaodImage(byte[] image)&lt;BR&gt;{&lt;BR&gt;FileStream fs = new FileStream("C:\\Inetpub\\wwwroot\\CatalogWebService\\test.jpg", FileMode.CreateNew, FileAccess.Write);&lt;BR&gt;fs.Write(image, 0, image.GetLength(0));&lt;BR&gt;fs.Close();&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;In order for the Web Service to write the image you will need to give the AppPool write permissions.&lt;BR&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;Caching&lt;/H2&gt;
&lt;P&gt;Catalog Manager has a caching class you can use this to cache your image DataSets.&lt;/P&gt;
&lt;H2&gt;Exception Management&lt;/H2&gt;
&lt;P&gt;Use the Enterprise Library for exception management and logging for both the Server side and client side.&lt;/P&gt;
&lt;H2&gt;Authorization Manager&lt;/H2&gt;
&lt;P&gt;Extend the Authorization Manager to have Image Management roles as described in our requirement.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Image Reader 
&lt;LI&gt;Image writer 
&lt;LI&gt;Image Administrator&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;You will need to use the two methods under all the Web Service to get the authorization policy and perform your own access checks. This&amp;nbsp;means that you have to create your own Authorization Context. The AzMan has an interop layer that you can use.&lt;BR&gt;&lt;BR&gt;The Authorization Methods exposed to all Web Services (for more details see my post &lt;A href="http://blogs.msdn.com/maxakbar/archive/2006/11/09/extending-commerce-server-2007-web-services.aspx" mce_href="http://blogs.msdn.com/maxakbar/archive/2006/11/09/extending-commerce-server-2007-web-services.aspx"&gt;Extending Commerce Server 2007 Web Services&lt;/A&gt;):&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;protected bool AuthorizationEnabled { get; }&lt;BR&gt;Returns true if you have Authorization Enabled in the web.config 
&lt;LI&gt;protected string AuthorizationPolicyPath { get; }&lt;BR&gt;Returns the path to the Authorization Policy&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;For more information on Authorization Manager see this MSDN article &lt;A href="http://msdn.microsoft.com/msdnmag/issues/03/11/AuthorizationManager/" mce_href="http://msdn.microsoft.com/msdnmag/issues/03/11/AuthorizationManager/"&gt;Use Role-Based Security in Your Middle Tier .NET Apps with Authorization Manager&lt;/A&gt;.&lt;/P&gt;
&lt;H2&gt;Security&lt;/H2&gt;
&lt;P&gt;Not everyone does this but you should start thinking about it. This should be done during the design of your application to identify risks to your application. You can find out more about &lt;A href="http://msdn2.microsoft.com/en-us/security/aa570411.aspx" mce_href="http://msdn2.microsoft.com/en-us/security/aa570411.aspx"&gt;Threat Modeling&lt;/A&gt; on MSDN.&lt;/P&gt;
&lt;H2&gt;&lt;FONT face=Verdana&gt;Summary&lt;/FONT&gt;&lt;/H2&gt;
&lt;P&gt;So now you have all the tools and knowledge to complete the image projects and add multiple images to a product. When you upload your image to your Web Service you can use the Commerce Staging Service to move your files to your production site.&lt;/P&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;/DIV&gt;&lt;/FORM&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1306888" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/maxakbar/attachment/1306888.ashx" length="88182" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx">Catalog System</category><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Architectural+and+Design/default.aspx">Architectural and Design</category></item><item><title>Commerce Server 2007 Customization and Extensibility LAB released</title><link>http://blogs.msdn.com/maxakbar/archive/2006/12/03/commerce-server-2007-customization-and-extensibility-lab-released.aspx</link><pubDate>Mon, 04 Dec 2006 09:50:31 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1202992</guid><dc:creator>Max Akbar</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/maxakbar/comments/1202992.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maxakbar/commentrss.aspx?PostID=1202992</wfw:commentRss><description>&lt;p&gt;&lt;/p&gt; &lt;h2&gt;Commerce Server 2007: Customization and Extensibility&lt;/h2&gt; &lt;p&gt;&amp;nbsp; &lt;p&gt;In this lab you will learn to: &lt;ul&gt; &lt;li&gt;Extend Catalog Manager UI  &lt;li&gt;Extend Catalog Web Service  &lt;li&gt;Extend Authorization Manger roles &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a href="http://go.microsoft.com/?linkid=5836744"&gt;Take this lab&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1202992" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx">Catalog System</category></item><item><title>Adding Image Management to your Commerce Site Part (IV)</title><link>http://blogs.msdn.com/maxakbar/archive/2006/11/28/adding-image-management-to-your-commerce-site-part-iv.aspx</link><pubDate>Wed, 29 Nov 2006 10:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1169975</guid><dc:creator>Max Akbar</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/maxakbar/comments/1169975.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maxakbar/commentrss.aspx?PostID=1169975</wfw:commentRss><description>&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;So far we have figured out our requirements and created a design out of that.&amp;nbsp;In the last post we created our database structure to support the image management system. In this post we will create the wire frame projects to support our API's for Image Management and display them on the website.&lt;/P&gt;
&lt;P&gt;So I hope that you did your homework and did a bit of reading of the Bridge Pattern, read up on UIP and browsed the &lt;A href="http://msdn.microsoft.com/practices/" mce_href="http://msdn.microsoft.com/practices/"&gt;Patterns &amp;amp; Practices&lt;/A&gt; web site.&lt;/P&gt;
&lt;H2&gt;Design Overview&lt;/H2&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:c551cd65-bbab-4521-94d5-2fe5ed9b5527 contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 559px; HEIGHT: 286px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1169921/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1169921/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;&lt;BR&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;There are two paths the red numbers mark the Path of UI communication and the blue numbers mark the path of ASP.NET or Console\WinForms communications.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;FONT color=#ff0000&gt;&lt;STRONG&gt;Form the Catalog Manager our Image UI's will call an Image Management System.&lt;/STRONG&gt;&lt;/FONT&gt; 
&lt;LI&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;The Bridge Pattern will reside in &lt;STRONG&gt;&lt;FONT color=#ff0000&gt;Image Management&lt;/FONT&gt;&lt;/STRONG&gt; and has two types of access Web Service or Direct Data access.&lt;/FONT&gt;&lt;/STRONG&gt; 
&lt;LI&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;Based on how the Image Management is constructed in this case we call the Catalog Web Service.&lt;/FONT&gt;&lt;/STRONG&gt; 
&lt;LI&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;The Catalog Web Service which holds our Image Web Service asmx will call the Image Module.&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/STRONG&gt; 
&lt;LI&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;From here we make a call back to our Image Management and construct a Direct Data access.&lt;/FONT&gt;&lt;/STRONG&gt; 
&lt;LI&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;The Image Management will call the Product Catalog Database to access our Image SQL objects.&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;&lt;FONT color=#0000ff&gt;The Web Forms and Controls will call our Module.&lt;/FONT&gt;&lt;/STRONG&gt; 
&lt;LI&gt;&lt;STRONG&gt;&lt;FONT color=#0000ff&gt;The Commerce Site has a reference in the web.config about our Image Module. This allows us to construct an Image Context.&lt;/FONT&gt;&lt;/STRONG&gt; 
&lt;LI&gt;&lt;STRONG&gt;&lt;FONT color=#0000ff&gt;The Image Module makes a call to the Image Management and create a Direct Data access object.&lt;/FONT&gt;&lt;/STRONG&gt; 
&lt;LI&gt;&lt;STRONG&gt;&lt;FONT color=#0000ff&gt;&lt;STRONG&gt;&lt;FONT color=#0000ff&gt;The Direct Data object calls our Image SQL Objects.&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;H1&gt;Development Design&lt;/H1&gt;
&lt;P&gt;So where do we begin? Lets create our Image management in separate project so all our code will be in a project all by it self and we will integrate with the Partner SDK where needed. We want to keep the code separate to predict future changes in Partner SDK. For example in the next version of the Commerce Server the Partner SDK may have changes and this design will be easier, simpler and clean to migrate. You can do the same thing with the WinForms and UserControls but it's a bit more work so in this sample I am taking the easy road :) but in your enterprise it would be better to create your own control library.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;"Don't do as I do, do as I say:)"&lt;/STRONG&gt;&lt;/P&gt;
&lt;H3&gt;Development Environment&lt;/H3&gt;
&lt;P&gt;Now is a good time to create your test environment for the Image Management System by unpacking the CSharpSite site and configure it based on the readme docs. Make sure to create the Image SQL objects from our previous post under the &amp;lt;SiteName&amp;gt;_ProductCatlaog database.&lt;/P&gt;
&lt;H3&gt;Image Management Project&lt;/H3&gt;
&lt;P&gt;So lets create an Image Management project. Before continuing forward please make sure to download the &lt;A href="http://msdn.microsoft.com/library/?url=/library/en-us/dnpag2/html/EntLib2.asp" mce_href="http://msdn.microsoft.com/library/?url=/library/en-us/dnpag2/html/EntLib2.asp"&gt;Enterprise Library for .NET Framework 2.0&lt;/A&gt;&amp;nbsp;and install it accepting all default values. The Image Management project will use a Service interface layer to access the Business logic and in turn will perform CRUD operation using the Data Access.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Open the Partner SDK solution and add a new&amp;nbsp;Class Library&amp;nbsp;project.&lt;BR&gt;&lt;BR&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:cb7d7b17-50b5-4425-8c97-139907207751 contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 303px; HEIGHT: 241px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1131527/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1131527/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;&lt;BR&gt;This project will implement the Bridge Pattern as you will see in the next post.&lt;/LI&gt;&lt;/OL&gt;
&lt;H3&gt;UI Design&lt;/H3&gt;
&lt;P&gt;In Part II of this post we designed some UI's for our Image Management System so lets add our new controls and forms into our Catalog Manager.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Let's create our control that will be added to the Product Edit Page. Make sure to call it something other than Images. Catalog Manager already has a class named Images.&lt;BR&gt;&lt;BR&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:94951916-50ee-4d87-8bcb-32daceb18820 contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; FLOAT: none; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 482px; HEIGHT: 270px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/827594/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/827594/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;&lt;BR&gt;Create a new control under the Wizard folder inheriting &lt;STRONG&gt;WizardControlBase&lt;/STRONG&gt; and &lt;STRONG&gt;IEditableItem&lt;/STRONG&gt;. The &lt;STRONG&gt;IEditableItem&lt;/STRONG&gt; is an interface for all the dialogs which support editing of catalog and inventory items. &lt;STRONG&gt;WizardControlBase&lt;/STRONG&gt; is a base class used to support wizard functionality. When creating a product you navigate through a wizard process (Welcome Screen, Product Properties Screen, and Product Relationship Screen etc...). You may want to add the image control as part of the Wizard process but for this post we'll skip that.&lt;BR&gt;&lt;BR&gt;Modify the namespace to &lt;STRONG&gt;Microsoft.CommerceServer.UI.CatalogManaer &lt;/STRONG&gt;and remove the Access modifier &lt;STRONG&gt;public&lt;/STRONG&gt; from the class.&lt;BR&gt;&lt;BR&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:8bdabbb9-a16d-4fcf-af1c-d28e764587b8 contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 591px; HEIGHT: 266px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1131623/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1131623/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;&lt;BR&gt;Next implement the &lt;STRONG&gt;IEditableItem&lt;/STRONG&gt; interface.&lt;BR&gt;&lt;BR&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:30041e5f-335e-494b-807f-3a55461df68d contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 269px; HEIGHT: 88px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1131536/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1131536/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;
&lt;LI&gt;Since Image Preview is used on multiple controls it needs to be it's own reusable control so add a new control for reviewing images under the Wizard folder of Catalog Manager. Do not modify it's inheritance and keep it as default.&lt;BR&gt;Add a Label for image file name, a PictureBox for previewing images and a CheckBox for Auto-fitting the image.&lt;BR&gt;&lt;BR&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:b3e19156-ac66-4c92-a8c7-71275a6eed2c contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 254px; HEIGHT: 235px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1132625/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1132625/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;&lt;BR&gt;
&lt;LI&gt;Now go back to&amp;nbsp;&lt;A href="http://blogs.msdn.com/maxakbar/archive/2006/10/14/adding-image-management-to-your-commerce-site-part-ii.aspx" mce_href="http://blogs.msdn.com/maxakbar/archive/2006/10/14/adding-image-management-to-your-commerce-site-part-ii.aspx"&gt;Adding Image Management to your Commerce Site Part(II)&lt;/A&gt; post and review all the properties that needs to be added to our Product Catalog Edit Image Tab Control. Your designer should look like the following.&lt;BR&gt;&lt;BR&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:bc072a90-e27f-439a-9dc2-111a22716adc contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 601px; HEIGHT: 317px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1132821/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1132821/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;&lt;BR&gt;If you are creating a multilingual Catalog Manager the text in your Labels and Buttons should come from resource files. Catalog Manager uses &lt;STRONG&gt;CatalogResourceFile.resx&lt;/STRONG&gt; under the root of the Catalog Manager and it's accessed by &lt;STRONG&gt;CatalogResource.cs&lt;/STRONG&gt; file also under the root of Catalog Manager.&lt;BR&gt;&lt;BR&gt;
&lt;LI&gt;Create two more controls under the Wizard folder for uploading and searching and a From under Dialog&amp;nbsp;to contain our two controls. Make sure that the namespaces reflect &lt;STRONG&gt;Microsoft.CommerceServer.UI.CatalogManaer&lt;/STRONG&gt;. The inheritance of the two control are &lt;STRONG&gt;UserControlBase&lt;/STRONG&gt; and &lt;STRONG&gt;IEditableItem&lt;/STRONG&gt;. Both controls needs to have the&amp;nbsp;&lt;STRONG&gt;using Microsoft.CommerceServer.UI.ControlLibrary;&lt;/STRONG&gt; statement for the &lt;STRONG&gt;UserControlBase &lt;/STRONG&gt;and remove the Access modifier &lt;STRONG&gt;public&lt;/STRONG&gt; from the class. &lt;STRONG&gt;UserControlBase&lt;/STRONG&gt; is the base class for all user controls.&lt;BR&gt;&lt;BR&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:d1180c7e-c806-41e6-a9a7-31d1adfe53d4 contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 615px; HEIGHT: 401px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1136753/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1136753/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;&lt;BR&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:5e1a02a6-7a3b-4e7f-a353-a068fc54abb1 contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 610px; HEIGHT: 398px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1136760/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1136760/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;&lt;BR&gt;When the controls are completed you will need to create a Tab control in the Associate Images Form and add both Controls.&lt;BR&gt;&lt;BR&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:bd957f57-c0ef-4e93-9374-7ca9e30bae9c contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 640px; HEIGHT: 470px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1136749/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1136749/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;&lt;BR&gt;We will add finishing touches later for now we need to have the wire frame. You can delete the resx files that are created for the Controls and Form as we will not use them.&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;&lt;EM&gt;Note: If you want the form to be resizable you will need to work with the controls so they can scale when the form is resized.&lt;/EM&gt;&lt;/STRONG&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;H3&gt;ASP.NET and images&lt;/H3&gt;
&lt;P&gt;We will use some of the Commerce Server extensibility classes to create Commerce Modules to be used in ASP.NET context for displaying images on the site as well as the Image Web Service. I have a &lt;A href="http://www.gotdotnet.com/workspaces/releases/viewuploads.aspx?id=77487df3-96dc-41de-9ca0-b7f284a8c113" mce_href="http://www.gotdotnet.com/workspaces/releases/viewuploads.aspx?id=77487df3-96dc-41de-9ca0-b7f284a8c113"&gt;sample&lt;/A&gt; created in &lt;A href="http://www.gotdotnet.com/workspaces/workspace.aspx?id=77487df3-96dc-41de-9ca0-b7f284a8c113" mce_href="http://www.gotdotnet.com/workspaces/workspace.aspx?id=77487df3-96dc-41de-9ca0-b7f284a8c113"&gt;GotDotNET&lt;/A&gt; site for Commerce Server 2002 but it will also work for Commerce Server 2007.&lt;/P&gt;
&lt;H3&gt;Commerce Module for Image Management System&lt;/H3&gt;
&lt;P&gt;You can add the Image Module to your existing Image Management project or create a new one and add a reference to the Image Management project. For this sample we are going to create a new project and&amp;nbsp;add this project to &lt;STRONG&gt;Commerce Server 2006 Partner SDK&lt;/STRONG&gt; solution.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Add a new &lt;STRONG&gt;Class Library &lt;/STRONG&gt;and name it &lt;STRONG&gt;ImageModule&lt;/STRONG&gt;. 
&lt;LI&gt;Reference Microsoft.CommerceServer.Runtime. 
&lt;LI&gt;Add &lt;STRONG&gt;using Microsoft.CommerceServer.Runtime;&lt;/STRONG&gt; and &lt;STRONG&gt;using Microsoft.CommerceServer.Runtime.Configuration;&lt;/STRONG&gt; 
&lt;LI&gt;Rename Class1 to something more meaningful then inherit &lt;STRONG&gt;CommerceModule&lt;/STRONG&gt;. 
&lt;LI&gt;Add a reference to the Image Management project. 
&lt;LI&gt;Implement the &lt;STRONG&gt;CommerceModule&lt;/STRONG&gt; interfaces.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;We will fill the details in the next post.&lt;/P&gt;
&lt;H3&gt;Web Services for Images&lt;/H3&gt;
&lt;P&gt;We need to Extend the Catalog Web Service and create a new Web Service to implement interfaces for Image Management. Here is where our Commerce Module will be used with dependency on Catalog System. The Extension of the Catalog Web Service is to retrieve images as part of the Product Catalog and the purpose of the new Image Web Service&amp;nbsp;is to perform CRUD operations. We also need to create a proxy class in our Image Management Project to access the Image Web Service.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV&gt;&lt;STRONG&gt;Catalog Web Service&lt;/STRONG&gt;&lt;/DIV&gt;
&lt;OL&gt;
&lt;LI&gt;
&lt;DIV&gt;Add a new ASP.NET project by right clicking on &lt;STRONG&gt;Commerce Server 2006 Partner SDK&lt;/STRONG&gt; and select Add &lt;STRONG&gt;Existing Web Site...&lt;BR&gt;&lt;BR&gt;&lt;/STRONG&gt;&lt;/DIV&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:f9cf06aa-175c-42ad-8149-5cd96129fd24 contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 306px; HEIGHT: 310px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1155185/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1155185/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;
&lt;LI&gt;
&lt;DIV&gt;From the Add&amp;nbsp;Existing Web Site select &lt;STRONG&gt;CSharpSiteCatalogWebService &lt;/STRONG&gt;or whatever you named your Catalog Web Service.&lt;BR&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:3688298e-c7a2-41eb-9f4c-a61cf362112f contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 578px; HEIGHT: 462px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1155182/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1155182/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;
&lt;LI&gt;
&lt;DIV&gt;To extend the Catalog Web Service I have post &lt;A href="http://blogs.msdn.com/maxakbar/archive/2006/11/09/extending-commerce-server-2007-web-services.aspx" mce_href="http://blogs.msdn.com/maxakbar/archive/2006/11/09/extending-commerce-server-2007-web-services.aspx"&gt;Extending Commerce Server 2007 Web Services.&lt;/A&gt; Take a moment to read up on it and extend the Catalog Web Service.&lt;/DIV&gt;
&lt;LI&gt;
&lt;DIV&gt;Rename the CatalogWebService.asmx to CatalogWebService.asmx.old.&lt;/DIV&gt;
&lt;LI&gt;
&lt;DIV&gt;Add a new Web Service called CatalogWebService.asmx.&lt;/DIV&gt;
&lt;LI&gt;
&lt;DIV&gt;Then extend the Catalog Web Service as stated in &lt;A href="http://blogs.msdn.com/maxakbar/archive/2006/11/09/extending-commerce-server-2007-web-services.aspx" mce_href="http://blogs.msdn.com/maxakbar/archive/2006/11/09/extending-commerce-server-2007-web-services.aspx"&gt;Extending Commerce Server 2007 Web Services&lt;/A&gt;.&lt;/DIV&gt;
&lt;LI&gt;
&lt;DIV&gt;You will need to add a reference to Microsoft.CommerceServer.Catalog.dll.&lt;BR&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;LI&gt;
&lt;DIV&gt;&lt;STRONG&gt;Image Web Service&lt;/STRONG&gt;&lt;/DIV&gt;
&lt;OL&gt;
&lt;LI&gt;
&lt;DIV&gt;Under the Catalog Web Service create a new Web Service and call it ImageWebService.asmx.&lt;/DIV&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;We will fill the details in the next post.&lt;/P&gt;
&lt;H3&gt;Proxy Class for the Image Web Service&lt;/H3&gt;
&lt;P&gt;We now need to create a proxy class for the Image Web Service.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Right click on &lt;STRONG&gt;ImageManagementSystem&lt;/STRONG&gt; project and select &lt;STRONG&gt;Add Web Reference...&lt;/STRONG&gt;.&lt;BR&gt;&lt;BR&gt;
&lt;DIV class=wlWriterSmartContent id=6960CE03-38FC-44df-87D4-FA4540212B06:5aa770fa-346e-4ea3-a5f0-a2601384acbf contentEditable=false style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px"&gt;&lt;IMG style="WIDTH: 701px; HEIGHT: 499px" alt="" src="http://blogs.msdn.com/photos/commerceserver/images/1155241/original.aspx" mce_src="http://blogs.msdn.com/photos/commerceserver/images/1155241/original.aspx"&gt;&lt;/DIV&gt;&lt;BR&gt;
&lt;LI&gt;Next type &lt;STRONG&gt;"http://localhost/CSharpSiteCatalogWebService/ImageWebService.asmx"&lt;/STRONG&gt; for the URL and select &lt;STRONG&gt;Go&lt;/STRONG&gt;. 
&lt;LI&gt;When connected to the Web Service select the &lt;STRONG&gt;Add Reference&lt;/STRONG&gt; button.&lt;BR&gt;&lt;BR&gt;Note: You may encounter an error if you update your Web Service Proxy &lt;STRONG&gt;"Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information"&lt;/STRONG&gt; if so see this &lt;A href="http://support.microsoft.com/default.aspx/kb/912019/en-us" mce_href="http://support.microsoft.com/default.aspx/kb/912019/en-us"&gt;KB article&lt;/A&gt; for a hotfix.&lt;/LI&gt;&lt;/OL&gt;
&lt;H2&gt;Summary&lt;/H2&gt;
&lt;P&gt;In this post we have created all the wire frame to our Image Management and have a good idea of how our projects interact with each other so the fun begins and we will code the details.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1169975" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx">Catalog System</category><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Architectural+and+Design/default.aspx">Architectural and Design</category></item><item><title>Product Bundling with Commerce Server 2007</title><link>http://blogs.msdn.com/maxakbar/archive/2006/11/01/product-bundling-with-commerce-server-2007.aspx</link><pubDate>Thu, 02 Nov 2006 05:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:928072</guid><dc:creator>Max Akbar</dc:creator><slash:comments>17</slash:comments><comments>http://blogs.msdn.com/maxakbar/comments/928072.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maxakbar/commentrss.aspx?PostID=928072</wfw:commentRss><description>&lt;H2&gt;What is a Product Bundle?&lt;/H2&gt;
&lt;P&gt;A product bundle is a purchasable SKU that is made up of a collection of one or more SKU's that exist in the catalog system and is separately priced.&lt;/P&gt;
&lt;P&gt;Two examples of a product bundle:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;In the high tech and telecommunication/cable industry business users want the ability to group together a set of products and sell it as one product. &lt;/P&gt;
&lt;P&gt;Phone Service Example: 1500 Anytime Plan – 59.99 per month 
&lt;UL&gt;
&lt;LI&gt;1500 minutes per month 
&lt;LI&gt;Caller ID 
&lt;LI&gt;3-Way Conferencing 
&lt;LI&gt;1 MB of Data Service&lt;/LI&gt;&lt;/UL&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;In the retail industry business users may want to group furniture.&lt;/P&gt;
&lt;P&gt;Furniture Set Example:&amp;nbsp;Max's 8-pc Dining Set - 500.00&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Table 
&lt;LI&gt;6 Chairs 
&lt;LI&gt;Server&lt;/LI&gt;&lt;/UL&gt;&lt;/BLOCKQUOTE&gt;
&lt;H2&gt;Product Bundle Solutions&lt;/H2&gt;
&lt;P&gt;There are two ways to define product bundling. One using relationship and another using Discounts. &lt;/P&gt;
&lt;H3&gt;Using Relationships Solution Design Time&lt;/H3&gt;
&lt;P&gt;During design time do the following.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Use the Catalog and Inventory Schema Manager to create product definition called “Product_Bundle” and associate relevant properties to it. 
&lt;LI&gt;Next create a product using the “Product_Bundle” definition e.g. Local_Unlimited_Package. 
&lt;LI&gt;Give the bundle a price e.g. “Local_Unlimited_Package” costs $27&amp;nbsp;&lt;BR&gt;you can use variants if you have different pricing based on zipcode 
&lt;LI&gt;From the product Edit page create a Relationship called &lt;B&gt;BundleConstituent&lt;/B&gt; for example and add additional products (eg. 1500 minutes per month, Caller ID, 3-Way Conferencing and 1 MB of Data Service).&lt;/LI&gt;&lt;/OL&gt;
&lt;H3&gt;Using Relationships Solution Runtime&lt;/H3&gt;
&lt;OL&gt;
&lt;LI&gt;From the site code identify the product definition &lt;B&gt;BundleConstituent&lt;/B&gt;&amp;nbsp;and display the product appropriately. 
&lt;LI&gt;When the product is added to cart make sure to add subline items. You do this based on your fulfillment rules. When the product is sent to your backend system to be shipped will they understand what a BundleConstituent is? If so then you don't need to have subline items just add the item into the basket and you are done. If not you need to send each bundled product so they understand what to ship. This business rule should be a custom pipeline component but you can have it in your site code. 
&lt;LI&gt;The custom pipeline component iterates through all line items and checks to see if the item is a product bundle (I.E. - searches the product definition for string containing “bundle”). If so, it makes another query to get all the “Related” bundle constituents (retrieve all products that are related to this product through a relationship name that contains “bundle”. 
&lt;LI&gt;To prevent the intentional or accidental removal of any one bundle constituent, the site code would display the bundle constituents in the basket by generating a row for each bundle constituent but it would not create a line item for each bundle constituent. So the basket would still have only 1 line item – the bundle sku with information about the bundle constituents. If the bundle sku is removed, then all of the constituents get removed from the display. This code would be part of the site code. 
&lt;LI&gt;
&lt;P&gt;The site code or custom pipeline component ensures that only the bundle price is displayed towards the basket subtotal the prices of the bundle constituents are not accounted for in the basket subtotal.&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;The Update Inventory pipeline can therefore get the inventory decrement for the bundle constituents. By the time the checkout completes, the order has the complete list of items sold, appearing as individual line items. This order can now be sent to Fulfillment back-end systems.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;I&gt;Note: the Bundle sku inventory has to be manually created upfront to have the inventory of the minimum of all bundle constituents (to prevent a situation where the bundle cannot be sold because one of the constituents is out of stock). The inventory of the bundle sku should also be updated every time a constituent is sold so that the inventory never goes out of sync. &lt;/I&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Marketing Discounts: On a bundle, the individual sku's lose their identity and the discounts that would be applicable on individual sku's, need to be disallowed. By ensuring that the bundle constituents are not individual line items, the discounts for the individual bundle constituents do not get applied (as desired). The only discounts that get applied are the ones on the bundle sku. &lt;/EM&gt;&lt;/P&gt;
&lt;H3&gt;Using Discounts Solution Design Time&lt;/H3&gt;
&lt;OL&gt;
&lt;LI&gt;
&lt;P&gt;Create a product called Local_Unlimited_Package.&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;Give the bundle a price &lt;I&gt;e.g. “Local_Unlimited_Package” costs $27 (pricing may vary based on zip code and so variants could be created for this purpose)&lt;/I&gt;&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;Create a Discount “Buy product Local_Unlimited_Package and get the following free: e. list of items that are free&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;CallerID 
&lt;LI&gt;3-way-conf&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;H3&gt;Using Discounts Solution Runtime&lt;/H3&gt;
&lt;OL&gt;
&lt;LI&gt;The runtime discount filtering feature (&lt;B&gt;CS2007&lt;/B&gt; only) will determine the simple discounts that apply to the products on the page and will display the names of the award items. However, the details of each award item will not be available (custom site code would need to make a call to the QCI component to fetch the products mentioned in the award items list. 
&lt;LI&gt;The shopper would have to add each item of the bundle in the basket manually. Alternatively, a custom pipeline component could add all the bundle constituents automatically. 
&lt;LI&gt;The basket pipeline (actually the discount sub-pipeline) ensures that only the bundle price is charged in the overall basket total; the individual prices of the bundle constituents are negated by the discount that applies. 
&lt;LI&gt;Shoppers can add more of the bundle constituents and there is no problem because the discount pipeline would apply discounts appropriately (additional items would be full price). 
&lt;LI&gt;The basket pipeline, when called, calls the discount sub-pipeline but it cannot ensure that the award constituents are always present. If the awards are removed from the basket, then the awards can be lost. Intentional or accidental removal of any one bundle constituent cannot be prevented.&lt;/LI&gt;&lt;/OL&gt;
&lt;H2&gt;Summary&lt;/H2&gt;
&lt;P&gt;This post is credited to Mark Townsend and Ankur Agarwal previous Catalog PMs.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=928072" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx">Catalog System</category><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Marketing+System/default.aspx">Marketing System</category></item><item><title>Adding Image Management to your Commerce Site Part(III)</title><link>http://blogs.msdn.com/maxakbar/archive/2006/10/31/adding-images-management-to-your-commerce-site-part-iii.aspx</link><pubDate>Wed, 01 Nov 2006 05:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:916556</guid><dc:creator>Max Akbar</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/maxakbar/comments/916556.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maxakbar/commentrss.aspx?PostID=916556</wfw:commentRss><description>&lt;p&gt;&lt;/p&gt; &lt;p&gt;Let's take a trip to memory lane and see what we have learned so far. We gathered some requirements and from that we created an architecture design. Now we are going to try to develop what we have designed.&lt;/p&gt; &lt;h2&gt;Product Catalog Database&lt;/h2&gt; &lt;p&gt;We need to figure out our Database Design first. So let's get back to our requirements and see how this fits.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Images\files should support sequencing  &lt;li&gt;Displaying multi lingual images  &lt;li&gt;Support pageable searches  &lt;li&gt;When deleting images\file records need to store the deleted names so IT personal can remove ghost images\files from file server  &lt;ul&gt; &lt;li&gt;When deleting images make sure that there are no other association before removing file to deleted table&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Need to support file paths  &lt;li&gt;Image\files can be shared among other products&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Tables&lt;/h3&gt; &lt;p&gt;The ImageHierarchy table is used to join with &amp;lt;CatalogName&amp;gt;_CatalogProducts table for image\file association. ImageHierarchyID and ImageFileID are the primary key to keep uniqueness of files.&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="100%" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td colspan="3"&gt;&lt;strong&gt;&lt;/strong&gt;&amp;nbsp;&lt;strong&gt;ImageHierarchy&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;&lt;em&gt;&lt;strong&gt;Column Name&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt; &lt;td valign="top" align="left"&gt;&lt;em&gt;&lt;strong&gt;&amp;nbsp;Data Type&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt; &lt;td valign="top" align="left"&gt;&lt;em&gt;&lt;strong&gt;&amp;nbsp;Description&lt;/strong&gt;&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;ImageHierarchyID &lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;int&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;An integer value for Image Hierarchy&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;ImageFileID &lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;int &lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;An integer value used to join to&amp;nbsp;Images table&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;Sequence &lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;int &lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;sequence value for a given image\file&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;ProductID &lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;nvarchar(255)&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;The value of ProductID is used to join to &amp;lt;CatalogName&amp;gt;_CatalogProducts table to retrieve images for products&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;VariantID &lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;nvarchar(255)&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;The value of VariantID is used to join to &amp;lt;CatalogName&amp;gt;_CatalogProducts table to retrieve images for products Variants&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;CategoryName &lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;nvarchar(128)&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;The value of CategoryName is used to join to &amp;lt;CatalogName&amp;gt;_CatalogProducts table to retrieve images for Categories&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;CatalogName &lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;nvarchar(85)&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;Catalog where the image resides&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;The Images table records what type of image\file is stored and when it was created. You may want to create another record for ModifiedDate. The DeleteMe column can be used to do offline bulk operation if there are performance impacts.&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="100%" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td colspan="3"&gt;&amp;nbsp;&lt;strong&gt;Images&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;&lt;strong&gt;&lt;em&gt;Column Name&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" align="left"&gt;&lt;strong&gt;&lt;em&gt;&amp;nbsp;Data Type&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" align="left"&gt;&lt;strong&gt;&lt;em&gt;&amp;nbsp;Description&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;ImageFileID&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;int&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;An integer value to represent an image&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;FeatureID&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;smallint&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;An integer value to join an image type&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;CreateDate&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;datetime&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;Date that the image\file record was created (may need one more for ModifiedDate)&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;DeleteMe&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;bit&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;A value to identify that the image can be deleted (may not need this)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;The ImageType table records type of images\files that are supported by your system. To be consistent and organized we hold the path for the images based on type.&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="100%" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td colspan="3"&gt;&amp;nbsp;&lt;strong&gt;ImageTypes&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;&lt;strong&gt;&lt;em&gt;Column Name&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" align="left"&gt;&lt;strong&gt;&lt;em&gt;&amp;nbsp;Data Type&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" align="left"&gt;&lt;strong&gt;&lt;em&gt;&amp;nbsp;Description&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;FeatureID&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;smallint&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;An integer value representing the image type&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;ImageType&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;nvarchar(128)&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;A value for the type of image\file&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;Path&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;nvarchar(128)&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;Path to the image\file type&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;The Images_&amp;lt;language code&amp;gt; Need a table to hold multi lingual images\files. For this post I will assume that we do not have multilingual tables other than US English.&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="100%" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td colspan="3"&gt;&amp;nbsp;&lt;strong&gt;Images_&amp;lt;language code&amp;gt; (i.e. en-US)&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;&lt;strong&gt;&lt;em&gt;Column Name&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" align="left"&gt;&lt;strong&gt;&lt;em&gt;&amp;nbsp;Data Type&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" align="left"&gt;&lt;strong&gt;&lt;em&gt;&amp;nbsp;Description&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;DisplayName&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;nvarchar(128)&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;A value describing the image\file&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;ImageName&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;nvarchar(128)&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;Image file name&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;Height&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;nvarchar(4)&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;Image height&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;Width&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;nvarchar(4)&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;Image Width&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;ImageFileID&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;int&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;An integer value joining to Images table&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;Need a table to hold deleted image\files. You will use this table to generate batch scripts to clean out ghost images.&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="100%" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td colspan="3"&gt;&amp;nbsp;&lt;strong&gt;Images_Deleted&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;&lt;strong&gt;&lt;em&gt;Column Name&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" align="left"&gt;&lt;strong&gt;&lt;em&gt;&amp;nbsp;Data Type&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt; &lt;td valign="top" align="left"&gt;&lt;strong&gt;&lt;em&gt;&amp;nbsp;Description&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;ImageFileID&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;int&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;An integer value representing the deleted image&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;ImageName&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;nvarchar(128)&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;Image file name&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;ImagePath&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;nvarchar(128)&lt;/td&gt; &lt;td valign="top" align="left"&gt;&amp;nbsp;Image path&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/photos/commerceserver/images/890072/original.aspx"&gt;  &lt;h4&gt;T-SQL Code for Tables&lt;/h4&gt; &lt;table cellspacing="1" cellpadding="1" width="100%" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;/****** Object: Table [dbo].[ImageHierarchy] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;&lt;/p&gt; &lt;p&gt;CREATE TABLE [dbo].[ImageHierarchy]&lt;br&gt;(&lt;br&gt;[ImageHierarchyID] [int] IDENTITY(1,1) NOT NULL,&lt;br&gt;[ImageFileID] [int] NOT NULL,&lt;br&gt;[Sequence] [int] NULL,&lt;br&gt;[ProductID] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,&lt;br&gt;[VariantID] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,&lt;br&gt;[CategoryName] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,&lt;br&gt;[CatalogName] [nvarchar](85) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,&lt;br&gt;CONSTRAINT [PK_ImageHierarchy] PRIMARY KEY CLUSTERED &lt;br&gt;(&lt;br&gt;[ImageHierarchyID] ASC,&lt;br&gt;[ImageFileID] ASC&lt;br&gt;)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]&lt;br&gt;) ON [PRIMARY] &lt;/p&gt; &lt;p&gt;GO&lt;br&gt;&lt;/p&gt; &lt;p&gt;/****** Object: Table [dbo].[Images] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;&lt;/p&gt; &lt;p&gt;CREATE TABLE [dbo].[Images]&lt;br&gt;(&lt;br&gt;[ImageFileID] [int] IDENTITY(1,1) NOT NULL,&lt;br&gt;[FeatureID] [smallint] NULL,&lt;br&gt;[CreateDate] [datetime] NULL,&lt;br&gt;[DeleteMe] [bit] NULL,&lt;br&gt;CONSTRAINT [PK_Images] PRIMARY KEY CLUSTERED &lt;br&gt;(&lt;br&gt;[ImageFileID] ASC&lt;br&gt;)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]&lt;br&gt;) ON [PRIMARY] &lt;/p&gt; &lt;p&gt;GO&lt;br&gt;&lt;/p&gt; &lt;p&gt;/****** Object: Table [dbo].[Images_Deleted] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;CREATE TABLE [dbo].[Images_Deleted](&lt;br&gt;[ImageFileID] [int] NOT NULL,&lt;br&gt;[ImageName] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,&lt;br&gt;[ImagePath] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL&lt;br&gt;) ON [PRIMARY] &lt;/p&gt; &lt;p&gt;GO&lt;br&gt;&lt;/p&gt; &lt;p&gt;/****** Object: Table [dbo].[Images_en-US] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;CREATE TABLE [dbo].[Images_en-US](&lt;br&gt;[DisplayName] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,&lt;br&gt;[ImageName] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,&lt;br&gt;[Height] [nvarchar](4) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,&lt;br&gt;[Width] [nvarchar](4) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,&lt;br&gt;[ImageFileID] [int] NULL&lt;br&gt;) ON [PRIMARY] &lt;/p&gt; &lt;p&gt;GO&lt;br&gt;&lt;/p&gt; &lt;p&gt;/****** Object: Table [dbo].[ImageTypes] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;CREATE TABLE [dbo].[ImageTypes](&lt;br&gt;[FeatureID] [smallint] IDENTITY(1,1) NOT NULL,&lt;br&gt;[ImageType] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,&lt;br&gt;[Path] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,&lt;br&gt;CONSTRAINT [PK_ImageTypes] PRIMARY KEY CLUSTERED &lt;br&gt;(&lt;br&gt;[FeatureID] ASC&lt;br&gt;)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]&lt;br&gt;) ON [PRIMARY] &lt;/p&gt; &lt;p&gt;GO&lt;br&gt;&lt;/p&gt; &lt;p&gt;ALTER TABLE [dbo].[ImageHierarchy] WITH CHECK ADD CONSTRAINT [FK_ImageHierarchy_Images] FOREIGN KEY([ImageFileID])&lt;br&gt;REFERENCES [dbo].[Images] ([ImageFileID])&lt;br&gt;GO&lt;br&gt;&lt;/p&gt; &lt;p&gt;ALTER TABLE [dbo].[ImageHierarchy] CHECK CONSTRAINT [FK_ImageHierarchy_Images]&lt;br&gt;GO&lt;br&gt;&lt;/p&gt; &lt;p&gt;ALTER TABLE [dbo].[Images] WITH CHECK ADD CONSTRAINT [FK_Images_ImageTypes] FOREIGN KEY([FeatureID])&lt;br&gt;REFERENCES [dbo].[ImageTypes] ([FeatureID])&lt;br&gt;GO&lt;br&gt;&lt;/p&gt; &lt;p&gt;ALTER TABLE [dbo].[Images] CHECK CONSTRAINT [FK_Images_ImageTypes]&lt;br&gt;GO&lt;br&gt;&lt;/p&gt; &lt;p&gt;ALTER TABLE [dbo].[Images_en-US] WITH CHECK ADD CONSTRAINT [FK_Images_en-US_Images] FOREIGN KEY([ImageFileID])&lt;br&gt;REFERENCES [dbo].[Images] ([ImageFileID])&lt;br&gt;GO&lt;br&gt;&lt;/p&gt; &lt;p&gt;ALTER TABLE [dbo].[Images_en-US] CHECK CONSTRAINT [FK_Images_en-US_Images]&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;h3&gt;View&lt;/h3&gt; &lt;p&gt;Create a view that can retrieve an image or be searched. A view may be necessary for each language.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;img src="http://blogs.msdn.com/photos/commerceserver/images/890140/original.aspx"&gt; &lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="100%" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;/****** Object: View [dbo].[GetImage] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;CREATE VIEW [dbo].[GetImage]&lt;br&gt;AS&lt;br&gt;SELECT dbo.ImageHierarchy.Sequence, dbo.[Images_en-US].DisplayName, dbo.[Images_en-US].ImageName, dbo.[Images_en-US].Height, &lt;br&gt;dbo.[Images_en-US].Width, dbo.ImageTypes.ImageType, dbo.ImageTypes.Path, dbo.ImageHierarchy.ProductID, dbo.ImageHierarchy.VariantID, &lt;br&gt;dbo.ImageHierarchy.CategoryName, dbo.ImageHierarchy.CatalogName, dbo.Images.ImageFileID&lt;br&gt;FROM dbo.ImageHierarchy INNER JOIN&lt;br&gt;dbo.Images ON dbo.ImageHierarchy.ImageFileID = dbo.Images.ImageFileID INNER JOIN&lt;br&gt;dbo.[Images_en-US] ON dbo.Images.ImageFileID = dbo.[Images_en-US].ImageFileID INNER JOIN&lt;br&gt;dbo.ImageTypes ON dbo.Images.FeatureID = dbo.ImageTypes.FeatureID&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;h3&gt;Stored Procedures&lt;/h3&gt; &lt;p&gt;We need a stored procedure that searches on either FileName or&amp;nbsp;FileDisplayName field. The stored procedure will also do pagination.&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="100%" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;/****** Object: StoredProcedure [dbo].[img_Search] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;-- =============================================&lt;br&gt;-- Author: Max Akbar&lt;br&gt;-- Create date: &lt;br&gt;-- Description: Search Images&lt;br&gt;-- =============================================&lt;br&gt;CREATE PROCEDURE [dbo].[img_Search] &lt;br&gt;-- Add the parameters for the stored procedure here&lt;br&gt;@keyword nvarchar(255) = null,&lt;br&gt;@ImageFileID int = 1,&lt;br&gt;@RecordsReturned int&lt;br&gt;AS &lt;/p&gt; &lt;p&gt;DECLARE @Query nvarchar (4000)&lt;br&gt;BEGIN&lt;br&gt;-- SET NOCOUNT ON added to prevent extra result sets from&lt;br&gt;SET NOCOUNT ON;  &lt;p&gt;SET @Query = 'SELECT TOP '+ CAST(@RecordsReturned as nvarchar(255)) +' GetImage.*&lt;br&gt;FROM GetImage&lt;br&gt;WHERE ((DisplayName = ''' + @keyword + ''') or (ImageName = ''' + @keyword + '''))&lt;br&gt;and (ImageFileID &amp;gt; ' + CAST(@ImageFileID as nvarchar(255))+ ')'  &lt;p&gt;EXEC sp_executesql @Query&lt;br&gt;END  &lt;p&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;We also need a stored procedure for sequencing and ressequencing images\files.&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="100%" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;/****** Object: StoredProcedure [dbo].[img_Resequence] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;-- =============================================&lt;br&gt;-- Author: Max Akbar&lt;br&gt;-- Create date: &lt;br&gt;-- Description: Resequence images&lt;br&gt;-- =============================================&lt;br&gt;CREATE PROCEDURE [dbo].[img_Resequence] &lt;br&gt;-- Add the parameters for the stored procedure here&lt;br&gt;@ImageHierarchyID int,&lt;br&gt;@ImageFileID int, &lt;br&gt;@ProductID nvarchar(255),&lt;br&gt;@Sequence int&lt;br&gt;AS &lt;/p&gt; &lt;p&gt;DECLARE @oldSequence int&lt;br&gt;DECLARE @OldImageHierarchyID int&lt;br&gt;DECLARE @OldImageFileID int  &lt;p&gt;BEGIN&lt;br&gt;-- SET NOCOUNT ON added to prevent extra result sets from&lt;br&gt;SET NOCOUNT ON;  &lt;p&gt;SELECT @oldSequence = Sequence&lt;br&gt;FROM ImageHierarchy&lt;br&gt;WHERE ImageHierarchyID = @ImageHierarchyID&lt;br&gt;and ImageFileID = @ImageFileID&lt;br&gt;SELECT @OldImageHierarchyID = ImageHierarchyID,&lt;br&gt;@OldImageFileID = ImageFileID&lt;br&gt;FROM ImageHierarchy&lt;br&gt;WHERE ProductID = @ProductID&lt;br&gt;and &lt;br&gt;Sequence = @Sequence  &lt;p&gt;UPDATE ImageHierarchy&lt;br&gt;SET Sequence = @Sequence&lt;br&gt;WHERE ImageHierarchyID = @ImageHierarchyID &lt;br&gt;and &lt;br&gt;ImageFileID = @ImageFileID  &lt;p&gt;IF @@ROWCOUNT &amp;gt; 0&lt;br&gt;BEGIN  &lt;p&gt;UPDATE ImageHierarchy&lt;br&gt;SET Sequence = @oldSequence&lt;br&gt;WHERE ImageHierarchyID = @OldImageHierarchyID &lt;br&gt;and &lt;br&gt;ImageFileID = @OldImageFileID&lt;br&gt;END&lt;br&gt;END  &lt;p&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;Now we need stored procedures for CRUD operations.&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="100%" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;/****** Object: StoredProcedure [dbo].[img_CreateImage] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;-- =============================================&lt;br&gt;-- Author: Max Akbar&lt;br&gt;-- Create date: &lt;br&gt;-- Description: Create a Product Image\File record&lt;br&gt;-- =============================================&lt;br&gt;CREATE PROCEDURE [dbo].[img_CreateImage] &lt;br&gt;-- Add the parameters for the stored procedure here&lt;br&gt;@FeatureID int,&lt;br&gt;@Sequence int,&lt;br&gt;@ProductID nvarchar(255) = null,&lt;br&gt;@VariantID nvarchar(255) = null,&lt;br&gt;@CategoryName nvarchar(255) = null,&lt;br&gt;@CatalogName nvarchar(85),&lt;br&gt;@DisplayName nvarchar(255), &lt;br&gt;@ImageName nvarchar(255), &lt;br&gt;@Height nvarchar(4) = null, &lt;br&gt;@Width nvarchar(4) = null,&lt;br&gt;@language nvarchar(255) = 'en-US'&lt;br&gt;AS  &lt;p&gt;DECLARE @ImageID as nvarchar(255)  &lt;p&gt;BEGIN&lt;br&gt;-- SET NOCOUNT ON added to prevent extra result sets from&lt;br&gt;SET NOCOUNT ON;  &lt;p&gt;BEGIN TRANSACTION &lt;br&gt;-- insert the record into the image table&lt;br&gt;INSERT INTO Images(FeatureID, CreateDate)&lt;br&gt;VALUES (@FeatureID, GetDate())  &lt;p&gt;SELECT @ImageID = @@IDENTITY  &lt;p&gt;-- insert a record into the ImageHierarchy&lt;br&gt;INSERT INTO ImageHierarchy (ImageFileID, Sequence, ProductID, VariantID, CategoryName, CatalogName)&lt;br&gt;VALUES (@ImageID, @Sequence, @ProductID, @VariantID, @CategoryName, @CatalogName)  &lt;p&gt;-- insert a record into the language table&lt;br&gt;IF @language = 'en-US'&lt;br&gt;BEGIN&lt;br&gt;-- this should be stored procedure&lt;br&gt;INSERT INTO [Images_en-US] (DisplayName, ImageName, Height, Width, ImageFileID)&lt;br&gt;VALUES (@DisplayName, @ImageName, @Height, @Width, @ImageID)&lt;br&gt;END  &lt;p&gt;IF(@@Error=0)&lt;br&gt;BEGIN&lt;br&gt;COMMIT TRANSACTION&lt;br&gt;END&lt;br&gt;ELSE&lt;br&gt;BEGIN&lt;br&gt;ROLLBACK TRANSACTION&lt;br&gt;END  &lt;p&gt;END  &lt;p&gt;GO&lt;br&gt;/****** Object: StoredProcedure [dbo].[img_DeleteCategory] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;-- =============================================&lt;br&gt;-- Author: Max Akbar&lt;br&gt;-- Create date: &lt;br&gt;-- Description: Create a Product Image\File record&lt;br&gt;-- =============================================&lt;br&gt;CREATE PROCEDURE [dbo].[img_DeleteCategory]&lt;br&gt;-- Add the parameters for the stored procedure here&lt;br&gt;@ImageFileID int,&lt;br&gt;@CategoryName nvarchar(255),&lt;br&gt;@language nvarchar(255) = 'en-US'&lt;br&gt;AS  &lt;p&gt;DECLARE @ImageName nvarchar(255)&lt;br&gt;DECLARE @Path nvarchar(255)  &lt;p&gt;BEGIN&lt;br&gt;-- SET NOCOUNT ON added to prevent extra result sets from&lt;br&gt;SET NOCOUNT ON;  &lt;p&gt;-- check to make sure it's ok to delete the product.&lt;br&gt;SELECT * FROM GetImage WHERE (ImageFileID = @ImageFileID)&lt;br&gt;IF @@ROWCOUNT &amp;lt;&amp;gt; 0&lt;br&gt;BEGIN&lt;br&gt;RETURN&lt;br&gt;END  &lt;p&gt;SELECT @ImageName = ImageName, @Path = Path FROM GetImage&lt;br&gt;WHERE (ImageFileID = @ImageFileID) and (CategoryName = @CategoryName)&lt;br&gt;IF @@ROWCOUNT = 0&lt;br&gt;BEGIN&lt;br&gt;RETURN&lt;br&gt;END&lt;br&gt;BEGIN TRANSACTION &lt;br&gt;-- delete a record into the ImageHierarchy&lt;br&gt;DELETE FROM ImageHierarchy&lt;br&gt;WHERE (ImageFileID = @ImageFileID) and (CategoryName = @CategoryName)  &lt;p&gt;-- delete a record into the language table&lt;br&gt;IF @language = 'en-US'&lt;br&gt;BEGIN&lt;br&gt;-- this should be stored procedure&lt;br&gt;DELETE FROM [Images_en-US]&lt;br&gt;WHERE (ImageFileID = @ImageFileID)&lt;br&gt;END &lt;br&gt;-- delete the record into the image table&lt;br&gt;DELETE FROM Images&lt;br&gt;WHERE (ImageFileID = @ImageFileID)  &lt;p&gt;INSERT INTO Images_Deleted (ImageFileID, ImageName, ImagePath)&lt;br&gt;VALUES (@ImageFileID, @ImageName, @Path)  &lt;p&gt;IF(@@Error&amp;lt;&amp;gt;0)&lt;br&gt;BEGIN&lt;br&gt;COMMIT TRANSACTION&lt;br&gt;END&lt;br&gt;ELSE&lt;br&gt;BEGIN&lt;br&gt;ROLLBACK TRANSACTION&lt;br&gt;END  &lt;p&gt;END  &lt;p&gt;GO&lt;br&gt;/****** Object: StoredProcedure [dbo].[img_DeleteProduct] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;-- =============================================&lt;br&gt;-- Author: Max Akbar&lt;br&gt;-- Create date: &lt;br&gt;-- Description: Create a Product Image\File record&lt;br&gt;-- =============================================&lt;br&gt;CREATE PROCEDURE [dbo].[img_DeleteProduct]&lt;br&gt;-- Add the parameters for the stored procedure here&lt;br&gt;@ImageFileID int,&lt;br&gt;@ProductID nvarchar(255),&lt;br&gt;@language nvarchar(255) = 'en-US'&lt;br&gt;AS  &lt;p&gt;DECLARE @ImageName nvarchar(255)&lt;br&gt;DECLARE @Path nvarchar(255)  &lt;p&gt;BEGIN&lt;br&gt;-- SET NOCOUNT ON added to prevent extra result sets from&lt;br&gt;-- interfering with SELECT statements.&lt;br&gt;SET NOCOUNT ON;  &lt;p&gt;-- check to make sure it's ok to delete the product.&lt;br&gt;SELECT * FROM GetImage WHERE (ImageFileID = @ImageFileID)&lt;br&gt;IF @@ROWCOUNT &amp;lt;&amp;gt; 0&lt;br&gt;BEGIN&lt;br&gt;RETURN&lt;br&gt;END  &lt;p&gt;SELECT @ImageName = ImageName, @Path = Path FROM GetImage&lt;br&gt;WHERE (ImageFileID = @ImageFileID) and (ProductID = @ProductID)&lt;br&gt;IF @@ROWCOUNT = 0&lt;br&gt;BEGIN&lt;br&gt;RETURN&lt;br&gt;END  &lt;p&gt;BEGIN TRANSACTION &lt;br&gt;-- delete a record into the ImageHierarchy&lt;br&gt;DELETE FROM ImageHierarchy&lt;br&gt;WHERE (ImageFileID = @ImageFileID) and (ProductID = @ProductID)  &lt;p&gt;-- delete a record into the language table&lt;br&gt;IF @language = 'en-US'&lt;br&gt;BEGIN&lt;br&gt;-- this should be stored procedure&lt;br&gt;DELETE FROM [Images_en-US]&lt;br&gt;WHERE (ImageFileID = @ImageFileID)&lt;br&gt;END  &lt;p&gt;-- delete the record into the image table&lt;br&gt;DELETE FROM Images&lt;br&gt;WHERE (ImageFileID = @ImageFileID)  &lt;p&gt;INSERT INTO Images_Deleted (ImageFileID, ImageName, ImagePath)&lt;br&gt;VALUES (@ImageFileID, @ImageName, @Path)  &lt;p&gt;IF(@@Error=0)&lt;br&gt;BEGIN&lt;br&gt;COMMIT TRANSACTION&lt;br&gt;END&lt;br&gt;ELSE&lt;br&gt;BEGIN&lt;br&gt;ROLLBACK TRANSACTION&lt;br&gt;END  &lt;p&gt;END  &lt;p&gt;GO&lt;br&gt;/****** Object: StoredProcedure [dbo].[img_DeleteVariant] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;-- =============================================&lt;br&gt;-- Author: Max Akbar&lt;br&gt;-- Create date: &lt;br&gt;-- Description: Create a Product Image\File record&lt;br&gt;-- =============================================&lt;br&gt;CREATE PROCEDURE [dbo].[img_DeleteVariant] &lt;br&gt;-- Add the parameters for the stored procedure here&lt;br&gt;@ImageFileID int,&lt;br&gt;@ProductID nvarchar(255),&lt;br&gt;@VariantID nvarchar(255),&lt;br&gt;@language nvarchar(255) = 'en-US'&lt;br&gt;AS  &lt;p&gt;DECLARE @ImageName nvarchar(255)&lt;br&gt;DECLARE @Path nvarchar(255)  &lt;p&gt;BEGIN&lt;br&gt;-- SET NOCOUNT ON added to prevent extra result sets from&lt;br&gt;SET NOCOUNT ON;  &lt;p&gt;-- check to make sure it's ok to delete the product.&lt;br&gt;SELECT * FROM GetImage WHERE (ImageFileID = @ImageFileID)&lt;br&gt;IF @@ROWCOUNT &amp;lt;&amp;gt; 0&lt;br&gt;BEGIN&lt;br&gt;RETURN&lt;br&gt;END  &lt;p&gt;SELECT @ImageName = ImageName, @Path = Path FROM GetImage&lt;br&gt;WHERE (ImageFileID = @ImageFileID) and (VariantID = @VariantID) and (ProductID = @ProductID)&lt;br&gt;IF @@ROWCOUNT = 0&lt;br&gt;BEGIN&lt;br&gt;RETURN&lt;br&gt;END  &lt;p&gt;BEGIN TRANSACTION&lt;br&gt;-- delete a record into the ImageHierarchy&lt;br&gt;DELETE FROM ImageHierarchy&lt;br&gt;WHERE (ImageFileID = @ImageFileID) and (VariantID = @VariantID) and (ProductID = @ProductID)  &lt;p&gt;-- delete a record into the language table&lt;br&gt;IF @language = 'en-US'&lt;br&gt;BEGIN&lt;br&gt;-- this should be stored procedure&lt;br&gt;DELETE FROM [Images_en-US]&lt;br&gt;WHERE (ImageFileID = @ImageFileID)&lt;br&gt;END  &lt;p&gt;-- delete the record into the image table&lt;br&gt;DELETE FROM Images&lt;br&gt;WHERE (ImageFileID = @ImageFileID)  &lt;p&gt;INSERT INTO Images_Deleted (ImageFileID, ImageName, ImagePath)&lt;br&gt;VALUES (@ImageFileID, @ImageName, @Path)  &lt;p&gt;IF(@@Error&amp;lt;&amp;gt;0)&lt;br&gt;BEGIN&lt;br&gt;COMMIT TRANSACTION&lt;br&gt;END&lt;br&gt;ELSE&lt;br&gt;BEGIN&lt;br&gt;ROLLBACK TRANSACTION&lt;br&gt;END  &lt;p&gt;END  &lt;p&gt;GO&lt;br&gt;/****** Object: StoredProcedure [dbo].[img_GetImagecategory] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;-- =============================================&lt;br&gt;-- Author: Max Akbar&lt;br&gt;-- Create date: &lt;br&gt;-- Description: Get Image based on CategoryName&lt;br&gt;-- =============================================&lt;br&gt;CREATE PROCEDURE [dbo].[img_GetImagecategory]&lt;br&gt;-- Add the parameters for the stored procedure here&lt;br&gt;@CategoryName nvarchar(255) = null&lt;br&gt;AS&lt;br&gt;BEGIN&lt;br&gt;-- SET NOCOUNT ON added to prevent extra result sets from&lt;br&gt;SET NOCOUNT ON;  &lt;p&gt;SELECT Sequence, DisplayName, ImageName, Height, Width, ImageType, Path, ProductID, VariantID, CategoryName&lt;br&gt;FROM GetImage&lt;br&gt;WHERE (CategoryName = @CategoryName)  &lt;p&gt;END  &lt;p&gt;GO&lt;br&gt;/****** Object: StoredProcedure [dbo].[img_GetImageProduct] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;-- =============================================&lt;br&gt;-- Author: Max Akbar&lt;br&gt;-- Create date: &lt;br&gt;-- Description: Get Image based on ProductID&lt;br&gt;-- =============================================&lt;br&gt;CREATE PROCEDURE [dbo].[img_GetImageProduct] &lt;br&gt;-- Add the parameters for the stored procedure here&lt;br&gt;@ProductID nvarchar(255) = null&lt;br&gt;AS&lt;br&gt;BEGIN&lt;br&gt;-- SET NOCOUNT ON added to prevent extra result sets from&lt;br&gt;SET NOCOUNT ON;  &lt;p&gt;SELECT Sequence, DisplayName, ImageName, Height, Width, ImageType, Path, ProductID, VariantID&lt;br&gt;FROM GetImage&lt;br&gt;WHERE (ProductID = @ProductID)  &lt;p&gt;END  &lt;p&gt;GO&lt;br&gt;/****** Object: StoredProcedure [dbo].[img_GetImageProductVariant] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;-- =============================================&lt;br&gt;-- Author: Max Akbar&lt;br&gt;-- Create date: &lt;br&gt;-- Description: Get Image based on VariantID&lt;br&gt;-- =============================================&lt;br&gt;CREATE PROCEDURE [dbo].[img_GetImageProductVariant]&lt;br&gt;-- Add the parameters for the stored procedure here&lt;br&gt;@ProductID nvarchar(255) = null,&lt;br&gt;@VariantID nvarchar(255) = null&lt;br&gt;AS&lt;br&gt;BEGIN&lt;br&gt;-- SET NOCOUNT ON added to prevent extra result sets from&lt;br&gt;SET NOCOUNT ON;  &lt;p&gt;SELECT Sequence, DisplayName, ImageName, Height, Width, ImageType, Path, ProductID, VariantID&lt;br&gt;FROM GetImage&lt;br&gt;WHERE (ProductID = @ProductID) and (VariantID = @VariantID)  &lt;p&gt;END  &lt;p&gt;GO&lt;br&gt;/****** Object: StoredProcedure [dbo].[img_Resequence] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;-- =============================================&lt;br&gt;-- Author: Max Akbar&lt;br&gt;-- Create date: &lt;br&gt;-- Description: Create a Product Image\File record&lt;br&gt;-- =============================================&lt;br&gt;CREATE PROCEDURE [dbo].[img_updateImageHierarchytbl] &lt;br&gt;-- Add the parameters for the stored procedure here&lt;br&gt;@ImageFileID int, &lt;br&gt;@Sequence int, &lt;br&gt;@ProductID nvarchar (255), &lt;br&gt;@VariantID nvarchar(255), &lt;br&gt;@CategoryName nvarchar(255), &lt;br&gt;@CatalogName nvarchar(85),&lt;br&gt;@ImageHierarchyID int&lt;br&gt;AS  &lt;p&gt;BEGIN&lt;br&gt;-- SET NOCOUNT ON added to prevent extra result sets from&lt;br&gt;SET NOCOUNT ON;  &lt;p&gt;BEGIN TRANSACTION &lt;br&gt;-- insert a record into the ImageHierarchy&lt;br&gt;UPDATE ImageHierarchy&lt;br&gt;SET ImageFileID = @ImageFileID, &lt;br&gt;Sequence = @Sequence, &lt;br&gt;ProductID = @ProductID, &lt;br&gt;VariantID = @VariantID, &lt;br&gt;CategoryName = @CategoryName, &lt;br&gt;CatalogName = @CatalogName&lt;br&gt;WHERE (ImageHierarchyID = @ImageHierarchyID)  &lt;p&gt;IF(@@Error=0)&lt;br&gt;BEGIN&lt;br&gt;COMMIT TRANSACTION&lt;br&gt;END&lt;br&gt;ELSE&lt;br&gt;BEGIN&lt;br&gt;ROLLBACK TRANSACTION&lt;br&gt;END  &lt;p&gt;END  &lt;p&gt;GO&lt;br&gt;/****** Object: StoredProcedure [dbo].[img_UpdateImagetbl] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;-- =============================================&lt;br&gt;-- Author: Max Akbar&lt;br&gt;-- Create date: &lt;br&gt;-- Description: Create a Product Image\File record&lt;br&gt;-- =============================================&lt;br&gt;CREATE PROCEDURE [dbo].[img_UpdateImagetbl] &lt;br&gt;-- Add the parameters for the stored procedure here&lt;br&gt;@FeatureID int,&lt;br&gt;@ImageFileID int&lt;br&gt;AS  &lt;p&gt;BEGIN&lt;br&gt;-- SET NOCOUNT ON added to prevent extra result sets from&lt;br&gt;SET NOCOUNT ON;  &lt;p&gt;BEGIN TRANSACTION &lt;br&gt;-- insert the record into the image table&lt;br&gt;UPDATE Images&lt;br&gt;SET FeatureID = @FeatureID&lt;br&gt;WHERE (ImageFileID = @ImageFileID)  &lt;p&gt;IF(@@Error=0)&lt;br&gt;BEGIN&lt;br&gt;COMMIT TRANSACTION&lt;br&gt;END&lt;br&gt;ELSE&lt;br&gt;BEGIN&lt;br&gt;ROLLBACK TRANSACTION&lt;br&gt;END  &lt;p&gt;END  &lt;p&gt;GO&lt;br&gt;/****** Object: StoredProcedure [dbo].[img_UpdateLanguagetbl] ******/&lt;br&gt;SET ANSI_NULLS ON&lt;br&gt;GO&lt;br&gt;SET QUOTED_IDENTIFIER ON&lt;br&gt;GO&lt;br&gt;-- =============================================&lt;br&gt;-- Author: Max Akbar&lt;br&gt;-- Create date: &lt;br&gt;-- Description: Create a Product Image\File record&lt;br&gt;-- =============================================&lt;br&gt;CREATE PROCEDURE [dbo].[img_UpdateLanguagetbl]&lt;br&gt;-- Add the parameters for the stored procedure here&lt;br&gt;@ImageFileID nvarchar(255),&lt;br&gt;@DisplayName nvarchar(255), &lt;br&gt;@ImageName nvarchar(255), &lt;br&gt;@Height int, &lt;br&gt;@Width int,&lt;br&gt;@language nvarchar(255) = 'en-US'&lt;br&gt;AS  &lt;p&gt;BEGIN&lt;br&gt;-- SET NOCOUNT ON added to prevent extra result sets from&lt;br&gt;SET NOCOUNT ON;  &lt;p&gt;BEGIN TRANSACTION &lt;br&gt;-- insert the record into the image table&lt;br&gt;IF @language = 'en-US'&lt;br&gt;BEGIN&lt;br&gt;-- this should be stored procedure&lt;br&gt;UPDATE [Images_en-US]&lt;br&gt;SET DisplayName = @DisplayName,&lt;br&gt;ImageName = @ImageName,&lt;br&gt;Height = @Height,&lt;br&gt;Width = @Width&lt;br&gt;WHERE (ImageFileID = @ImageFileID)&lt;br&gt;END  &lt;p&gt;IF(@@Error=0)&lt;br&gt;BEGIN&lt;br&gt;COMMIT TRANSACTION&lt;br&gt;END&lt;br&gt;ELSE&lt;br&gt;BEGIN&lt;br&gt;ROLLBACK TRANSACTION&lt;br&gt;END  &lt;p&gt;END  &lt;p&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;Data file to update image types.&lt;br&gt;Note: You may want to add this as a requirement so that your business users can perform CRUD operations. For this example we are going to create several image file types using T-SQL.&amp;nbsp;A PDF file type, an image file type for Product and Categories and finally EndCaps. I will explain EndCaps in another blog post basically an EndCap is a retail industry&amp;nbsp;word describing the&amp;nbsp;display fixture located at the end of an aisle. So imagine having your product listing page as an aisle with an EndCap. Next time you go to a drug store check out the end of the aisle for an EndCap for promotional purposes.&lt;/p&gt; &lt;p&gt;We are going to keep all product images in one file but if you would like to keep multilingual products separate then I would suggest adding a column to the images table and concatenate ImageTypes column with Image column to get the full image path.&lt;/p&gt; &lt;table cellspacing="1" cellpadding="1" width="100%" border="1"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;INSERT INTO ImageTypes (ImageType, Path)&lt;br&gt;VALUES ('Product', 'Images\Products')&lt;br&gt;GO&lt;/p&gt;INSERT INTO ImageTypes (ImageType, Path)&lt;br&gt;VALUES ('Product', 'Images\Categories')&lt;br&gt;GO&lt;br&gt; &lt;p&gt;INSERT INTO ImageTypes (ImageType, Path)&lt;br&gt;VALUES ('PDF', 'Images\PDFs')&lt;br&gt;GO&lt;br&gt;INSERT INTO ImageTypes (ImageType, Path)&lt;br&gt;VALUES ('EndCap', 'Images\EndCaps')&lt;br&gt;GO&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;h3&gt;Database Performance Considerations&lt;/h3&gt; &lt;p&gt;If you have multiple catalogs then you may want to create a set of image tables for each catalogs. Only do this if you have over 100K products per catalog (I am flying by the seat of my pants) but you need to decide what the threshold is by running performance tests. All productID, VariantID, CategoryName and CatalogNames should be the same value as the Product Catalog and must have indexes. Make sure to test the stored procedures under performance peak operations and collect performance data to be analyzed by your DBA. You must test the performance under realistic values for example if your Product Catalog has 100K SKU's and each SKU has an average of two images then you must pre fill the image tables with that amount of data before running performance tests. Make sure to run the test with comparable hardware as your production.&amp;nbsp;Make sure to run database consistency checks and reindexing procedures during non peak hours.&lt;/p&gt; &lt;h3&gt;Staging Consideration&lt;/h3&gt; &lt;p&gt;SQL replication may require database changes. If you are using Commerce Server Staging then there may be a chance that you will have out of synch issues for short periods of time between the image table and Product Catalog data. Make sure that you have code in your site that checks to see if there is an image associated with the product if not display no image found dummy image. You will need to create a dummy image with the text no image found for the use of dummy image. At a later post I will show you how to extend the Commerce Server Staging to give you finer control of Product Catalog and any other associated tables. Keep your stored procedures simple and put most of your business logic into the API, this will make feature addins much easier.&lt;/p&gt; &lt;h3&gt;Design Problems&lt;/h3&gt; &lt;p&gt;I have already described a scenario where you will have out of synch issues&amp;nbsp;of Images\files and Product Catalog Data. So I will solve this in another post about extensibility of Commerce Server Staging.&lt;/p&gt; &lt;h3&gt;Test your Database Design&lt;/h3&gt; &lt;p&gt;Call your stored procedures to make sure that they execute within your design. I have created some sample T-SQL Scripts that you can use for your testing.&lt;/p&gt; &lt;h2&gt;Summary&lt;/h2&gt; &lt;p&gt;So we now have a database design that will be the foundation for our Development Design. We may have to come back and revisit and tweak the database objects&amp;nbsp;based on our Development Design. After reading this post it would be a good idea to learn about patterns specifically the Bridge , Factory Pattern and Agent Design. Don't forget to read up on UIP.&amp;nbsp;Here are some links that will help you:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternBridge.aspx"&gt;http://www.dofactory.com/Patterns/PatternBridge.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternAbstract.aspx"&gt;http://www.dofactory.com/Patterns/PatternAbstract.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.dofactory.com/Patterns/PatternFactory.aspx"&gt;http://www.dofactory.com/Patterns/PatternFactory.aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://msdn.microsoft.com/practices/"&gt;http://msdn.microsoft.com/practices/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I have also posted some test scripts see attachment.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=916556" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/maxakbar/attachment/916556.ashx" length="3242" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx">Catalog System</category><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Architectural+and+Design/default.aspx">Architectural and Design</category></item><item><title>Adding Image Management to your Commerce Site Part(II)</title><link>http://blogs.msdn.com/maxakbar/archive/2006/10/14/adding-image-management-to-your-commerce-site-part-ii.aspx</link><pubDate>Sun, 15 Oct 2006 08:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:827613</guid><dc:creator>Max Akbar</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/maxakbar/comments/827613.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maxakbar/commentrss.aspx?PostID=827613</wfw:commentRss><description>So in the last post you learned a bit about gathering requirements in this post we will convert the requirement into a design documents we can use to develop our Image Management System. 
&lt;H2&gt;Image Management Architecture&lt;/H2&gt;
&lt;P&gt;The following figure shows the architecture of our Image Management. The numbers in the figure correspond to brief explanations of the various components of the architecture that follows the figure.&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://blogs.msdn.com/photos/commerceserver/images/821541/original.aspx" border=0 mce_src="http://blogs.msdn.com/photos/commerceserver/images/821541/original.aspx"&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Business users will use the Catalog Manager to manage Product Catalog. We will modify the Catalog Manager so that the business users can upload images, search images and associate images to the Product Catalog Data. 
&lt;LI&gt;Catalog Manager will interface with Web Services to perform CRUD operations in the Database and upload images to the IIS Server. 
&lt;LI&gt;We will store all SQL objects related to Images\Files in the Product Catalog Table. 
&lt;LI&gt;We will use Commerce Server Staging to move Images\Files from our Staging Environment to Production, this only applies to enterprise customers. If you are a small to medium business you can upload the images directly to your Web Servers.&lt;/LI&gt;&lt;/OL&gt;
&lt;H2&gt;Image Management Deployment&lt;/H2&gt;
&lt;P&gt;The following figure shows the deployment topology of our Image Management. The numbers in the figure correspond to brief explanations of the various components of the deployment that follows the figure.&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://blogs.msdn.com/photos/commerceserver/images/821543/original.aspx" border=0 mce_src="http://blogs.msdn.com/photos/commerceserver/images/821543/original.aspx"&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Business users will access the Commerce Server Applications and upload images to the Application Server as well as performing CRUD operations in Product Catalog Database and upload images to a file Server by means of HTTP PUT. 
&lt;LI&gt;Files and Data are moved from Staging to Production Environment by Commerce Server Staging.&lt;/LI&gt;&lt;/OL&gt;
&lt;H2&gt;Image Management Design&lt;/H2&gt;
&lt;P&gt;Now we have a pretty good idea of our requirements, Architecture and Infrastructure so lets design our system.&lt;/P&gt;
&lt;H3&gt;Catalog Manager&lt;/H3&gt;
&lt;P&gt;Before we dive into the designing the changes tot he Catalog Manager let understand a few things. Commerce Server 2007 UI source code is available from Microsoft. To download the code you will need to register with a passport account.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.microsoft.com/commerceserver/partners/sdk/privacy.mspx" mce_href="http://www.microsoft.com/commerceserver/partners/sdk/privacy.mspx"&gt;Link to : Commerce Server 2007 Partner Software Development Kit&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Download the source code for Marketing Manager, Customer and Order Manager and Catalog Manager (Commerce Server 2007 Partner SDK). Now you are almost ready to start coding. All of the Commerce Server's Management UI's are build on top of User Interface Pattern (UIP) Application Block. UIP was developed by Microsoft patterns&amp;nbsp;&amp;amp; practices to provide a simple yet extensible framework for developing user interface processes. It is designed to abstract the control flow and state management out of the user interface layer into a user interface process layer. I am not going to explain the UIP Application block here so it would be a good idea to watch the following Webcast &lt;A href="http://msevents.microsoft.com/cui/EventDetail.aspx?EventID=1032243325&amp;amp;Culture=en-US" mce_href="http://msevents.microsoft.com/cui/EventDetail.aspx?EventID=1032243325&amp;amp;Culture=en-US"&gt;User Interface Process Application Block&lt;/A&gt;&amp;nbsp;and read about the &lt;A href="http://msdn.microsoft.com/practices/guidetype/appblocks/default.aspx?pull=/library/en-us/dnpag/html/uipab.asp" mce_href="http://msdn.microsoft.com/practices/guidetype/appblocks/default.aspx?pull=/library/en-us/dnpag/html/uipab.asp"&gt;User Interface Process (UIP) Application Block - Version 2.0&lt;/A&gt;. I will explain how our design will fit into Catalog Manager and UIP.&lt;/P&gt;
&lt;H3&gt;User Interface&lt;/H3&gt;
&lt;P&gt;We need to design the UI interfaces for Catalog Manager. First we need to have a Tab at the Product Catalog Edit page called Images. This Tab will display all our images and since images can also be multi lingual we need to account for that as well. On this Tab we can navigate to another Form that allows us to search for images&amp;nbsp;and associate them to products or upload new images. We also need to design these controls and Forms so they are Task sensitive. What I mean is that a Catalog Reader Role will have access to the Images Tab so they can see all of the images but not edit and a Catalog Editor can Edit existing images change the order of images and a Catalog Administrator who can Perform all action previously stated and upload new images.&lt;/P&gt;
&lt;P&gt;The Images Tab is Language context sensitive as Business User change Language Selection we also need to account for displaying images for the current language. Why have images for different languages? Lets say we have a multilingual site that will display English and French. Some of our images may contain text like "On Sale" so we can't display this image to french speaking customers as they won't understand what "On Sale" means because it's in English. For this reason we need to have an image for each language. In other words our image file name is multilingual property.&lt;/P&gt;
&lt;H4&gt;Product Catalog Edit Image Tab&lt;/H4&gt;
&lt;P&gt;In this form users can view images and reorder the sequence of images users with privileges can also add and remove images.&lt;/P&gt;&lt;IMG src="http://blogs.msdn.com/photos/commerceserver/images/827594/original.aspx" border=0 mce_src="http://blogs.msdn.com/photos/commerceserver/images/827594/original.aspx"&gt; 
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;TABLE class="" cellSpacing=1 cellPadding=1 width="100%" border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class="" colSpan=6&gt;&lt;STRONG&gt;Image Tab Properties:&lt;/STRONG&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;STRONG&gt;&lt;EM&gt;Control&lt;/EM&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;STRONG&gt;&lt;EM&gt;Description&lt;/EM&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;STRONG&gt;&lt;EM&gt;Tab Order&lt;/EM&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;EM&gt;&lt;STRONG&gt;Type&lt;/STRONG&gt;&lt;/EM&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;EM&gt;&lt;STRONG&gt;State&lt;/STRONG&gt;&lt;/EM&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;EM&gt;&lt;STRONG&gt;Data&lt;/STRONG&gt;&lt;/EM&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Describes ListView&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;1&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Label&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Product Image (s)&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;List of Image file name and their sequence for current Product&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;2&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;ListView&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;List of images associated with current product&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Move Image Order Up&lt;BR&gt;Only available to Catalog Editor and Catalog Administrator&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;3&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Image Up arrow&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Move Image Order Down&lt;BR&gt;Only available to Catalog Editor and Catalog Administrator&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;4&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Image Down arrow&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Label to describe PictureBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;5&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Label&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Image: &amp;lt;image name if an image is selected&amp;gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Render current image&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;6&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;PictureBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Image&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Auto-fit image to PictureBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;7&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;CheckBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Auto-fit Image&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;Launch New Form&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Add Images&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;8&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Add Images...&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Remove all Images (Enable only if an image is selected)&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;9&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Disabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Remove Image (s)&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;H4&gt;Associating Images to Products&lt;/H4&gt;
&lt;P&gt;This Form can be accessed two ways from the Catalog Manger to upload images but not associate them to Products or access the Form from Product Catalog Edit Form. This Form has two Tabs one to search existing images and another to upload new ones. &lt;/P&gt;
&lt;H5&gt;Search Tap&lt;/H5&gt;
&lt;P&gt;The search Tap allows searching for existing images, changing their types and Language. Business users can also be&amp;nbsp;preview images.&lt;/P&gt;
&lt;H6&gt;Image Types&lt;/H6&gt;
&lt;P&gt;Our requirements were to be able to associate more than one image and file type. In this scenario we can have multiple images per product and\or associate other file types. For example your business rules may be that you have a product so you need to show an image for that (Product Image Type) and this product is an dishwasher which has energy saver (Logo Image Type) not only that you may need to store the manual for the dishwasher (PDF Image Type).&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://blogs.msdn.com/photos/commerceserver/images/824451/original.aspx" border=0 mce_src="http://blogs.msdn.com/photos/commerceserver/images/824451/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;
&lt;TABLE class="" cellSpacing=1 cellPadding=1 width="100%" border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class="" colSpan=6&gt;&lt;STRONG&gt;Image Tab Properties:&lt;/STRONG&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;STRONG&gt;&lt;EM&gt;Control&lt;/EM&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;STRONG&gt;&lt;EM&gt;Description&lt;/EM&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;STRONG&gt;&lt;EM&gt;Tab Order&lt;/EM&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;EM&gt;&lt;STRONG&gt;Type&lt;/STRONG&gt;&lt;/EM&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;EM&gt;&lt;STRONG&gt;State&lt;/STRONG&gt;&lt;/EM&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;EM&gt;&lt;STRONG&gt;Data&lt;/STRONG&gt;&lt;/EM&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Describes CheckedListBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;1&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Label&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Image Types&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;List of Image Types&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;2&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;CheckedListBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&amp;lt;List of Image Types&amp;gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Describes TextBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;3&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Label&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Image File Name&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Image name to be searched&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;4&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;TextBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Describes DropDown&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;5&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Label&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Max Images to Retrieve&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;A number of search results to be returned&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;6&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;DropDownBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;10,50, 100&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Perform Search&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;7&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Search&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Describes ListView&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;8&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Label&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Images&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;List of search results &lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;9&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;ListView&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Selects all image types&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;10&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Select All&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Displays image selected&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;11&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;PictureBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Auto-fits image to PictureBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;12&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;CheckBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Auto-fit Image&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Clears current search&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;13&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Clear All&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;Close Form&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Closes the form and returns search results&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;14&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;OK&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;Close Form&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Closes the form and returns null&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;15&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Cancel&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;H4&gt;&amp;nbsp;&lt;/H4&gt;
&lt;H5&gt;Upload Tab&lt;/H5&gt;
&lt;P&gt;&amp;nbsp;Catalog Administrators can upload images change their types and language settings.&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://blogs.msdn.com/photos/commerceserver/images/827591/original.aspx" border=0 mce_src="http://blogs.msdn.com/photos/commerceserver/images/827591/original.aspx"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;
&lt;TABLE class="" cellSpacing=1 cellPadding=1 width="100%" border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class="" colSpan=6&gt;&lt;STRONG&gt;Image Tab Properties:&lt;/STRONG&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;STRONG&gt;&lt;EM&gt;Control&lt;/EM&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;STRONG&gt;&lt;EM&gt;Description&lt;/EM&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;STRONG&gt;&lt;EM&gt;Tab Order&lt;/EM&gt;&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;EM&gt;&lt;STRONG&gt;Type&lt;/STRONG&gt;&lt;/EM&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;EM&gt;&lt;STRONG&gt;State&lt;/STRONG&gt;&lt;/EM&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;EM&gt;&lt;STRONG&gt;Data&lt;/STRONG&gt;&lt;/EM&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Describes ListView&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;1&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Label&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Images&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;List of images to be uploaded&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;2&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;ListView&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;Launches OpenFileDialog&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Browse of image files&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;3&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Browse...&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;When a file is selected the button is enabled to change image type&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;4&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Disabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Change Type&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;When a file is selected the button is enabled to change image language&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;5&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Disabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Change Language&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Removes the selected file from ListView&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;6&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Remove&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Displays selected image&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;7&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;PictureBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Auto-fits image to PictureBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;8&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;CheckBox&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Clears the ListView&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;9&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Clear All&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;Close Form&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Close the Form and return list of images&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;10&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;OK&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&amp;nbsp;Close Form&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Close the Form and return null&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;11&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Button&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Enabled&lt;/TD&gt;
&lt;TD class=""&gt;&amp;nbsp;Cancel&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;H2&gt;&amp;nbsp;Summary&lt;/H2&gt;
&lt;P&gt;Things to consider&amp;nbsp;for performance reason you may want to keep an image table for each catalog so you should consider this when designing your multiple images to Product Catalog data. Should you decide that you want to have a distinct image table for each Catalog you may want to modify the Web Service to allow for image table creation when a catalog is created.&lt;/P&gt;
&lt;P&gt;In our next post we will design and extend Catalog Manager and our Catalog Web Services code to incorporate our solution.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=827613" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx">Catalog System</category><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Architectural+and+Design/default.aspx">Architectural and Design</category></item><item><title>Adding Image Management to your Commerce Site Part(I)</title><link>http://blogs.msdn.com/maxakbar/archive/2006/09/20/764026.aspx</link><pubDate>Thu, 21 Sep 2006 07:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:764026</guid><dc:creator>Max Akbar</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/maxakbar/comments/764026.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maxakbar/commentrss.aspx?PostID=764026</wfw:commentRss><description>&lt;P&gt;In this post I hope to give you some ideas of how to manage images with Commerce Server. I am going to show how to associate multiple images\files to a product catalog data then upload the associated files to your commerce site. We will also solve the problem of when the products are removed the associated images are deleted as well.&lt;/P&gt;
&lt;H2&gt;Multiple File Requirements&lt;/H2&gt;
&lt;P&gt;Before going further lets understand some basic requirements:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;We need to associate multiple files with a Product Catalog Data. These files can be images or other types of media like pdf files. 
&lt;LI&gt;Provide mechanism for uploading files using Catalog Manager from business users desktop or network. 
&lt;LI&gt;Allow business users to search for images. 
&lt;LI&gt;Provide mechanism for moving files to a Commerce Site. 
&lt;LI&gt;When Product Catalog Data is deleted so should the files associated.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;So now we have our requirements let begin on how we are going to address the above requirement.&lt;/P&gt;
&lt;H3&gt;Multiple Files&lt;/H3&gt;
&lt;P&gt;To associate more than one file we need to extend the Product Catalog Schema. There are two ways you can do this. One know the number of files you allow a Product Catalog and add exact properties to the Product or Category definition. So lets say that we limit this to five files. The limitation to this is that in the future we may want to grow the size to a number larger than five. If your requirements are simple then this approach will suffice. If you don’t know how many files you may wish to associate to the Product Catalog Data and you have more complex requirements such as a file can be shared among many Product Catalog Data then you will need to create custom tables and associated it with the Product\Category Definition. &lt;/P&gt;
&lt;H4&gt;File Data Store&lt;/H4&gt;
&lt;P&gt;To support the latter part of the requirement above you need to create three external SQL Tables:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;You need one Table to hold file association and image sequencing. 
&lt;LI&gt;Another Table to hold file types images, pdf etc… 
&lt;LI&gt;And one last table to hold the files&lt;/LI&gt;&lt;/UL&gt;
&lt;H4&gt;File Repository&lt;/H4&gt;
&lt;P&gt;The SQL Table holds the pointer to where the files are located but you will also need a file server to store files.&lt;/P&gt;
&lt;H4&gt;File Management&lt;/H4&gt;
&lt;P&gt;You then create views to use with Product Catalog SetJoin API for presentation and stored procedures for management. You will then extend the Commerce Server Product Catalog Web Service to support file management interfaces. Create and extend the Authorization Manager for new roles for image management.&lt;/P&gt;
&lt;H5&gt;Image Roles&lt;/H5&gt;
&lt;UL&gt;
&lt;LI&gt;You need this so that an administrator is responsible uploading images to the file repository.&lt;/LI&gt;
&lt;LI&gt;You need another role for file editor to associate files with your Product Catalog Data and one last role to view images.&lt;/LI&gt;
&lt;LI&gt;You will also need to modify the Catalog Manager to support the underplaying file management.&lt;/LI&gt;&lt;/UL&gt;
&lt;H4&gt;File Transport&lt;/H4&gt;
&lt;P&gt;How to move files from the business users desktop to a remote server? We will create a file transport provider and the mechanism are as follows:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;FTP 
&lt;LI&gt;HTTP PUT 
&lt;LI&gt;File Upload over HTTP&lt;/LI&gt;&lt;/UL&gt;
&lt;H4&gt;File Security&lt;/H4&gt;
&lt;P&gt;While designing the multiple file engine we need to think about security at all times. We need to make sure that wherever we store files no execute permission are set only read, write and modify.&lt;/P&gt;
&lt;H2&gt;Summary&lt;/H2&gt;
&lt;P&gt;In this Post you understood the multiple file requirements and thought about how to solve it. In the next post we will design our system.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=764026" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx">Catalog System</category><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Architectural+and+Design/default.aspx">Architectural and Design</category></item><item><title>CS2002 NetCatalogSitelet.pup upgraded to CS2007</title><link>http://blogs.msdn.com/maxakbar/archive/2006/08/27/727723.aspx</link><pubDate>Mon, 28 Aug 2006 06:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:727723</guid><dc:creator>Max Akbar</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/maxakbar/comments/727723.aspx</comments><wfw:commentRss>http://blogs.msdn.com/maxakbar/commentrss.aspx?PostID=727723</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;I have migrated CS2002 NetCatalogSitelet.pup and can be downloaded from my &lt;A href="http://www.gotdotnet.com/workspaces/workspace.aspx?id=77487df3-96dc-41de-9ca0-b7f284a8c113"&gt;GotDotNet site&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=727723" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/maxakbar/archive/tags/Catalog+System/default.aspx">Catalog System</category></item></channel></rss>