Friday, September 7, 2012

ASP.NET MVC Image Helper that accepts nulls

One of the things I liked about ASP.NET's ASP:Image tag was that it would not render an HTML image tag if the url was null. Using @Url.Content in an image tag throws an error, but I was able to easily accomplish the same behavior as ASP:Image using Razor with the following code (90%+ of the source is from this StackOverflow question):
   public static class ImageHelper  
   {  
     public static HtmlString Image(this HtmlHelper helper, string id, string url, string alternateText)  
     {  
       return Image(helper, id, url, alternateText, null);  
     }  
   
     public static HtmlString Image(this HtmlHelper helper, string id, string url, string alternateText, object htmlAttributes)  
     {  
       MvcHtmlString ret;  
   
       if (url == null)  
       {  
         ret = null;  
       }  
       else  
       {  
         // Instantiate a UrlHelper   
         var urlHelper = new UrlHelper(helper.ViewContext.RequestContext);  
   
         // Create tag builder  
         var builder = new TagBuilder("img");  
   
         // Create valid id  
         builder.GenerateId(id);  
   
         // Add attributes  
         builder.MergeAttribute("src", urlHelper.Content(url));  
         builder.MergeAttribute("alt", alternateText);  
         builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));  
   
         // Render tag  
         ret = new MvcHtmlString(builder.ToString(TagRenderMode.SelfClosing));  
       }  
   
       return ret;  
     }  
   }  
I'm really just testing out different blog code formatting options, but I think this is at least a bit useful :-)

Wednesday, July 25, 2012

IIS 7 URL Rewrite debugging

I needed to redirect a url from one domain to another while also removing part of the path, i.e.

http://www.test.com/folder/test.aspx
to
http://www.newtest.com/test.aspx

I used IIS 7's "URL Rewrite" module, and the test tool showed that my regex appeared to work correctly, but nothing was actually being redirected. I finally turned on "Failed Request Tracing Rules", added a rule to catch all 404 errors, and was able to look through the resulting log and quickly determine the error.

Here's the setup:




The log files are in the regular log files directory, under the "FaileReqLogFiles" directory by default. Open the  file with or similar to the name "fr000001.xml", and search for your redirection rule name. You should see lots of debugging details to help you determine why the redirect didn't work. In my case, I was trying to match the slash before the folder as well as after it, but IIS was only looking at the part of the path after the domain name, so it never matched.

And here's the rule setup to redirect from a domain to another domain while replacing part of the path, in case anybody needs it:


Under "Match URL --> Pattern", add a regex similar to this:

folder\/(.*)

This gets the url that contains the folder name with a slash after it, then creates a backreference for anything else that follows it, that you can refer to as "{R:1}".

Under "Redirect URL", enter:

http://www.newtest.com/{R:1}



Friday, May 11, 2012

Generic XML attribute parser

I may just end up using something like LINQ to XSD for this (if possible), but I wanted to see how easy it would be to write an XML parser that takes in an element of any kind, and returns a strongly-typed value. Here's what I came up with:

private T parseAttr<T>(XElement x, string elemName)
{
    Type type = typeof(T);
    T parsedValue;

    try
    {
        parsedValue = type.IsEnum ? (T)Enum.Parse(typeof(T), x.Element(elemName).Value) : (T)Convert.ChangeType(x.Element(elemName).Value, typeof(T));
    }
    catch
    {
        parsedValue = default(T);
    }

    return parsedValue;
}

which can be used like this (example is from a LINQ projection):

let picks =
    from pick in playerPicks.Element("PlayerList").Descendants("Player").Elements("Picks")
    select new PlayerPick
    {
        TickerSymbol = parseAttr<string>(pick, "TickerSymbol"),
        Status = parseAttr<Status>(pick, "Status"),
        PickCall = parseAttr<PickCall>(pick, "PickCall"),
        StartPrice = parseAttr<double>(pick, "StartPrice"),
        EndPrice = parseAttr<double>(pick, "EndPrice"),
        StartDate = parseAttr<DateTime>(pick, "StartDate"),
        EndDate = parseAttr<DateTime>(pick, "EndDate")
    }

It works on regular types as well as enums. I'm not completely happy with it - "Convert" is generally less useful than .Parse(), but I couldn't figure out how to use Parse with generics on static methods (i.e. (T).Parse()).

Also, it's hardly bulletproof, but I think I may validate the whole XML document first anyway if it doesn't take too long. Not sure if I'll end up using this or not - I was just amazed about how easy this was to write using generics, and thought it might be useful to somebody.

Monday, May 7, 2012

Renaming an ASP.NET MVC solution in Visual Studio

The Platinum Bay blog has a good writeup on how to rename a Visual Studio project correctly (so that the underlying folders are renamed and re-hooked up). 

But I still ran into problems - an MVC project that I renamed returned the following error :
Multiple types were found that match the controller named 'Home'. This can happen if the route that services this request ('{controller}/{action}/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter. 
The request for 'Home' has found the following matching controllers:
(new project namespace).Controllers.HomeController
(old project namespace).Controllers.HomeController
A file system search even turned up nothing, but I finally figured out the solution while reading a great in-depth article on controllers by Scott Allen, where he states:
...if you tell the factory to look for a "Home" controller, the factory can return a newly instantiated instance of a HomeController class regardless of the namespace or assembly it lives in—as long as it implements IController
If you've build the old project, you'll probably have old debugging dlls in the project's "bin" folder, so MVC will search and find those. Clear them out and rebuild, and everything should work. By the way, you could actually just follow the instructions in the error, and specify your route like this:

routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                namespaces: new string[] {"(new project namespace)"}
            );

but it's cleaner to delete the old .dlls, as they could potentially cause you other problems as well. I'm very surprised that even the VS 11 beta still doesn't rename solutions correctly out of the box.



Thursday, April 26, 2012

Querying fact tables for lower-level members (SAP BPC - MS version)

Top-level dimension members aren't represented at all in BPC fact tables (SQL side), so if you need to find records that belong to a top-level member, you either need to manually look up all of the lower-level members, or have a query do it for you. Here's one I put together using a basic recursive CTE that will give you all records that contain lower-level members, given a higher-level member:

WITH a
AS (
 SELECT *
 FROM mbrDataSrc_F
 WHERE [ID] = 'Top_Level_Datasource_Name' --top parent
         
 UNION ALL
         
 SELECT b.*
 FROM mbrDataSrc_F b
  JOIN a
   ON b.PARENTH1 = a.[ID]
        )
SELECT *
FROM tblFactForecast
WHERE DataSrc_F IN (
 SELECT [ID]
 FROM a
)

If you're not familiar with them, the SQL after the UNION is the recursive part (some more info on recursive Common Table Expressions). I use them a lot in place of derived tables for their slightly cleaner syntax, but don't usually have too much of a need for recursion.

BTW, I don't believe in SELECT *, except for ad-hoc queries, which this one was for me. There is an interesting discussion about it over at StackOverflow.com - basically, minimal performance gains in most situations, but more clean and safer to select the actual columns.

Wednesday, February 8, 2012

FizzBuzz

Apparently, the "FizzBuzz" problem is a common programming interview question. I came across it while reading You Can't Teach Height - Measuring Programmer Competence via FizzBuzz on Scott Hanselman's blog.

The "FizzBuzz" problem is:
Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.
After reading this, my first thought was to write code to solve the problem. Funny that the end of Hansleman's post states:
One other thing that's amazing to me ... is that some of the programmers who read these blogs feel the need to actually solve the FizzBuzz problem.
They've completely - no, I need a work with more oomph - utterly? missed the point.
I'm pretty sure the point of his post is just that an interviewer should ask the applicant to show what he/she can do, rather than just talk about it. I agree with this. And I always have a better feeling about a place where I interview if they at least have me provide code samples and have me talk about them.

But I've got to agree with one of the commenters:
Missed the point?? Developers are problem-solvers - OF COURSE we're going to try to code a solution! :-)
I love puzzles. So I tried coding it without looking up anything, then compiling to see if it worked. I first used a switch/case statement, so that if a number was both a multiple of 3 and 5, it would fall through both and output "FizzBuzz" without needing a separate case to handle both, something like this:

switch (i)
{
    case i % 3 == 0:
        Console.WriteLine("Fizz");
    case i % 5 == 0:
        Console.WriteLine("Buzz");
    default:
        Console.WriteLine(i);
}

Whoops. C# only allows constants in switch/case statements, and it doesn't support break fall-throughs, either (need to use "goto"!). So I tried to mimic it with regular if/then statements. But at the same time, I also had the idea to make it a method, so I ended up with this:

using System;
using System.Collections;
using System.Text;

namespace FizzBuzz
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (string i in fizzBuzz())
            {
                Console.WriteLine(i);
            }

            Console.ReadLine();
        }

        private static IEnumerable fizzBuzz()
        {
            bool isReplaced = false;

            for (int i = 1; i < 101; i++)
            {
                if (i % 3 == 0)
                {
                    yield return "Fizz";
                    isReplaced = true;
                }

                if (i % 5 == 0)
                {
                    yield return "Buzz";
                    isReplaced = true;
                }

                if (!isReplaced)
                {
                    yield return i.ToString();
                }

                isReplaced = false;
            }
        }
    }
}
This works, but for numbers like 15, it outputs Fizz and Buzz on two separate lines. It would be better off combining the 3 and 5 multiple case first, and having one if/else statement.

By the way, this doesn't loop twice - it starts the loop in main, goes into the fizzBuzz method, runs the logic until it gets to a "yield" statement, then finishes the loop in main, then runs the next iteration of the loop. It then picks up where it left off in the fizzBuzz method. This approach would let you format each string iteration differently if you wanted to (i.e. having the word "Fizz" output in green).

So my next thought was to compare my solution to others. I found this, which has a number of solutions in many different languages (none use the enumerable interface idea).

The Articulating Ideas blog has a really interesting post on efficient ways to solve the problem using C# - the bitwise operator one is very interesting (and a bit beyond my current coding skills):

string[] messages = new string[]{null, "Fizz", "Buzz", "FizzBuzz"};
int acc = 810092048; //11 00 00 01 00 10 01 00 00 01 10 00 01 00 00
int c = 0;
for (int i=1; i < = N; ++i)  {
    c = acc & 3;
    result += (c > 0 ? messages[c] : i.ToString()) + ", ";
    acc = acc >> 2 | c < < 28;
}


I'm surprised that this solution wasn't the clear winner (it tied another very slick version that doesn't use modulo, and was only a little faster than another using modulo). Division is usually the most expensive math operation, and shifting bits lets you get around that very cleverly (if you are clever enough to know how to use it...).

It really is true that 100 different programmers will come up with 100 different solutions to the same problem.

Saturday, February 4, 2012

C# "??" operator

I just ran across something I hadn't seen before - a two question mark operator. I found it in the AccountMembership service method in the default AccountModel.cs file that's used when you start a new ASP.NET MVC 3 project. Here's the line of code:
_provider = provider ?? Membership.Provider;
I did a little research and found it's just a shortcut for this, using an iif/conditional:
_provider = provider != null ? provider : Membership.Provider;
which of course is a shortcut for this regular if statement:
if(provider != null) {
     _provider = provider;
} else {
     _provider = Membership.Provider;
}

More info here: http://msdn.microsoft.com/en-us/library/ms173224.aspx
Very cool. I love the terseness of C#.