Linq Foray

I’m working on a website with lots of user controls interacting with one another using ASP.NET Ajax using events. So I end up needing to find other controls often, especially within repeaters. Nested controls all over the place. I found this wonderful post about using an extension method to the Controls Collection that flattens the tree and allows for much simpler Linq queries. The extension method adds and All() function which is seriously useful.

Posted: Sunday, March 22, 2009 9:27:00 PM (Eastern Standard Time, UTC-05:00)  #    Comments - Trackback
.Net 3.5 | ASP.NET | JavaScript/AJAX | Linq

Don’t Do This

In ASP.NET, the DataList control renders as a table. Opening a new table in the header and trying to get rows to render just won’t end well. Lots of strange browser behavior should be the tip off that this isn't right.

Posted: Sunday, March 22, 2009 7:48:00 PM (Eastern Standard Time, UTC-05:00)  #    Comments - Trackback
.Net 2.0 | .Net 3.5 | ASP.NET

Moving Commerce Server 2007 Databases

I needed to move the set of Commerce Server databases from one server to another, so I developed and tested this procedure.

  1. Script the database users to file. Our site is using domain users, so I performed this step first to keep the users in sync with a backup/restore of the databases.
  2. Backup each of the Commerce Server databases:
    • Marketing
    • Marketing_Lists
    • ProductCatalog
    • Profiles
    • TransactionConfig
    • Transactions
    • MSCS_Admin
    • MSCS_CatalogScratch
  3. Transfer the scripts and backup files to the new server.
  4. Run user scripts against the new server
  5. Restore each database on the new server
  6. On the web server, open Commerce Server Manager to change connection strings:
    1. Admin Database:
      1. Click the Commerce Server Manager node
      2. Click the Administration Database link in the right panel
      3. Change the Connection String, click OK
    2. Profiles
      1. Expand this node:
        Global Resources/Profiles
      2. Right-click and change the following 3 connection strings:
        s_BizDataStoreConnectionString
        s_CommerceProviderConnectionString
        s_ProfileServiceConnectionString
    3. Profile Database
      1. Expand this node:
        Global Resources/Profiles/ProfileCatalog/DataSources/ProfileService_SQLSource/Partitions
      2. Right-click SQLSource in the right pane and choose properties
      3. Change the Connection String, click OK
    4. Inventory Database
      1. Expand this node:
        Commerce Sites/CSharpSite/Site Resources/Inventory
      2. Right-click Inventory Database in the right pane and choose properties
      3. Change the Connection String, click OK
    5. Marketing Database
      1. Expand this node:
        Commerce Sites/CSharpSite/Site Resources/Marketing
      2. Right-click Mailing List Connection String in the right pane and choose properties
      3. Change the Connection String, click OK
      4. iv. Right-click Marketing Database Connection String in the right pane and choose properties
      5. Change the Connection String, click OK
    6. Product Catalog
      1. Expand this node:
        Commerce Sites/CSharpSite/Site Resources/Product Catalog
      2. Right-click Catalog Database in the right pane and choose properties
      3. Change the Connection String, click OK
    7. Transaction Config
      1. Expand this node:
        Commerce Sites/CSharpSite/Site Resources/Transaction Config
      2. Right-click Transactions Config Database in the right pane and choose properties
      3. Change the Connection String, click OK
    8. Transactions
      1. Expand this node:
        Commerce Sites/CSharpSite/Site Resources/Transaction Config
      2. Right-click Transactions Database in the right pane and choose properties
      3. Change the Connection String, click OK
  7. Change connection strings in the web.config for site (if any using API calls)
  8. Restart IIS
Posted: Sunday, February 08, 2009 8:28:53 PM (Eastern Standard Time, UTC-05:00)  #    Comments - Trackback
Commerce Server | SQL Server

Commerce Server 2007 Customer and Orders Payment Method Error

Right off I just want to say it sucks when the error message is correct but you don't understand why.

We needed to add a new payment method to a Commerce Server 2007 implementation. The Customer and Orders UI threw an error immediately when going to manage Payment methods:

The underlying table was full of data. The site has been in production for over a year, collecting credit card payments the whole time without issues. Obviously the payment methods weren't missing.

Of course, Googling was no help whatsoever. I played with the Commerce API, wrote some code, ran SQL traces, all to no avail.

So on the a non-production version of the site (with the same problem luckily), I decided to work on the database table directly. I scripted off the original data, and truncated the table. Now the UI doesn't throw the error. So I re-added the data manually, and again the UI is fine, no errors.

So I compared the newly entered data with the old data, and there was a difference (outside of the obvious differences like keys). There is a bit column in the table called IsDefault. In the old data, all rows except one were set to False. In the new data, all rows were set to True. To test that this was the problem, I truncated the table again, and re-inserted the original data. Then I changed the IsDefault values to True on all the rows. Bingo. The UI now works again, and I could add the new data. So apparently someone did modify the data in the past, and the error message was correct about the database being tampered with. Luckily this modification had not affected Commerce Server's ability to process credit cards.

I think the IsDefault column refers to the language setting for the row in the table, as you can have multiple language variants for a credit card and choose which one is the default language. So for the UI to function properly, at least one row for each language needs to have IsDefault set to True.

Posted: Monday, February 02, 2009 11:01:49 AM (Eastern Standard Time, UTC-05:00)  #    Comments - Trackback
Commerce Server | Strange Problems

Welcome to my new home!

Thanks for coming by and checking out my new blog site. I'm really excited to be hosting this on my own. As part of my 2008 resolutions, I'm trying to consistently have new content and be less sporadic.

I'm using DasBlog as the engine for this blog. As a .Net developer, I'm very happy with it. It is easy to modify, easy to understand how it's working.

Again, thanks for reading!

Posted: Monday, January 26, 2009 8:58:31 AM (Eastern Standard Time, UTC-05:00)  #    Comments - Trackback

eBooks on CodePlex

Wriju has a gread roundup of eBooks/guidance available on CodePlex.

Posted: Friday, January 09, 2009 4:01:49 PM (Eastern Standard Time, UTC-05:00)  #    Comments - Trackback
.Net 2.0 | .Net 3.0 | .Net 3.5 | Programming | TFS | WCF

Catching Thread Exceptions in C#

I have a Winforms app where I am performing asynchronous functions. I am using the delegate model and have threadsafe calls for updating my UI. My worker threads happen in an instance of another class, not the class that is the form.

I had the impression that the global Application.ThreadException event handler would catch exceptions that happened off on my working threads. This does not seem to be the case. The following code (as a console app) shows my problem and won't catch the exception. The program executes as if nothing bad happened.

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.Remoting.Messaging;
using System.Threading;
 
namespace BadThreadException
{
    class Program
    {
        delegate void WorkerDelegate(int input);
 
        static void Main(string[] args)
        {
            Application.ThreadException += new ThreadExceptionEventHandler(App_ThreadException);
 
            Worker mult = new Worker();
 
            AsyncCallback callback = new AsyncCallback(Finished);
 
            WorkerDelegate threadedWork = new WorkerDelegate(mult.DoSomethingImpressive);
 
            threadedWork.BeginInvoke(9, callback, null);
 
            Console.ReadKey();
        }
 
        static void Finished(IAsyncResult result)
        {
            Console.WriteLine("Done");
        }
 
        static void App_ThreadException(object sender, ThreadExceptionEventArgs e)
        {
            Console.WriteLine("Got an error");
        }
    }
 
    class Worker
    {
        public void DoSomethingImpressive(int input)
        {
            throw new Exception("Ouch");
        }
    }
 
}

Well, I definitely need a solution to the problem, since exceptions definitely can happen off in my worker class. After some research, it turns out that you must call the EndInvode method on the delegate for the exception to bubble up. In my case, I wasn't calling it because there was no return type. Now I understand why people frequently mention it is a best practice to always call EndInvoke, even if you don't care about the return value (Doh!). The correct callback looks like this:

        static void Finished(IAsyncResult result)
        {
            AsyncResult ar = (AsyncResult)result;
            WorkerDelegate d = (WorkerDelegate)ar.AsyncDelegate;
 
            try
            {
                d.EndInvoke(ar);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Got an error on the callback");
            }
 
            Console.WriteLine("Done");
        }

I still haven't discovered how/when the Application.ThreadException event handler gets called.

Posted: Sunday, November 30, 2008 4:33:50 AM (Eastern Standard Time, UTC-05:00)  #    Comments - Trackback
Winforms

Quick ADO.Net Tip

If you need to stop a datareader in the middle, instead of at the end, you have to call cancel on the command object. Calling the Close() method will result in a timeout exception.

using (SqlCommand cmd = new SqlCommand(sql, conn))
{
          XmlReader reader = cmd.ExecuteXmlReader();
          reader.Read();

while (!reader.EOF)
{
            if (this.Cancel)
            {
                cmd.Cancel();
                reader.Close():
                break;
            }
            holder = reader.ReadOuterXml();
}
}
Posted: Monday, November 10, 2008 4:47:04 PM (Eastern Standard Time, UTC-05:00)  #    Comments - Trackback
.Net 2.0

Getting Started with WCF and REST

Now that WCF has support for REST in .Net 3.5, it's time to get learning....

WCF REST Starter Kit

A Guide to Designing and Building RESTful Web Services with WCF 3.5

A bunch of screencasts by Aaron Skonnard

WCF and REST from the PDC

Dan Rigsby - REST support in WCF

Posted: Tuesday, November 04, 2008 12:58:09 AM (Eastern Standard Time, UTC-05:00)  #    Comments - Trackback
.Net 3.5 | WCF