Question: I want to eliminate some duplicated code. Can anyone make this code shorter and better?

```
switch (now.site)
{

    case item.SITE.AMAZON:
        try
        {
            price = driver.FindElement(By.XPath("//*[@id=\"priceblock_ourprice\"]")).Text;
            fetched = true;
        }
        catch
        {
            try
            {
                price = driver.FindElement(By.XPath("//*[@id=\"priceblock_dealprice\"]")).Text;
                fetched = true;
            }
            catch
            {
                fetched = false;
            }
        }
        break;
    case item.SITE.ALI:
        try
        {
            price = driver.FindElement(By.XPath("//*[@id=\"j-sku-discount-price\"]")).Text;
            fetched = true;
        }
        catch
        {
            try
            {
                price = driver.FindElement(By.XPath("//*[@id=\"j-sku-price\"]")).Text;
                fetched = true;
            }
            catch
            {
                fetched = false;
            }
        }
        break;
    }
}

```

Answer: 
You could create a dictionary of available path strings. I don't know what the type of `site` is. I assume `string`

```
private static Dictionary<string, string[]> pricePaths = new Dictionary<string, string[]> {
   [item.SITE.AMAZON] = new string[] { "//*[@id=\"priceblock_ourprice\"]",
                                       "//*[@id=\"priceblock_dealprice\"]" },
   [item.SITE.ALI] = new string[] { "//*[@id=\"j-sku-discount-price\"]",
                                    "//*[@id=\"j-sku-price\"]" },
};

```

With this, you can write a more generic logic.

```
bool fetched = false;
if (pricePaths.TryGetValue(now.site, out string[] paths)) {
    foreach (string path in paths) {
        try {
            price = driver.FindElement(By.XPath(path)).Text;
            fetched = true;
            break;
        } catch {
        }
    }
}

```

It allows you to easily add new sites. The sites can have an arbitrary number of alternate paths.
Here are some recommendations as to how you can beautify your code - 

1. Declare constants for all XPath queries.
2. Declare a variable outside the switch statement to capture the price value based on your case statement.
3. Create a function with one try catch statements which accepts 2 xPath strings and an out parameter for Price and returns a boolean value to indicate if the query was successful.
4. Remove the try catch from under each case and call that function passing the correct xPath strings from the set of constants.

```
const string priceblock_ourprice = "//*[@id=\"priceblock_ourprice\"]";
const string priceblock_dealprice = "//*[@id=\"priceblock_dealprice\"]";
const string j_sku_discount_price = "//*[@id=\"j-sku-discount-price\"]";
const string j_sku_price = "//*[@id=\"j-sku-price\"]";

public void YourPrimaryFunction
{  
    decimal price;  
    switch (now.site)  
    {  
        case item.SITE.AMAZON:  
            fetched = FetchPrice(priceblock_ourprice, priceblock_dealprice, out price);
            break;  
        case item.SITE.ALI:  
            fetched = FetchPrice(j_sku_discount_price, j_sku_price, out price);
            break;
    }
}

private bool FetchPrice(string xPathPrim, string xPathFallBack, decimal out price)
{
    try
    {
        price = driver.FindElement(By.XPath(xPathPrim)).Text;
        return true;
    }
    catch
    {
        try
        {
            price = driver.FindElement(By.XPath(xPathFallBack)).Text;
            return true;
        }
        catch
        {
            return false;
        }
    }
}

```