views:

306

answers:

1

Due to a prinitng error in some promotional material I have a site that is receiving a lot of requests which should be for one site arriving at another.
i.e.
The valid sites are http://site1.com/abc & http://site2.com/def but people are being told to go to http://site1.com/def.

I have control over site1 but not site2.

site1 contains logic for checking that the first part of the route is valid in an actionfilter, like this:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    base.OnActionExecuting(filterContext);

    if ((!filterContext.ActionParameters.ContainsKey("id")) 
     || (!manager.WhiteLabelExists(filterContext.ActionParameters["id"].ToString())))
    {
        if (filterContext.ActionParameters["id"].ToString().ToLowerInvariant().Equals("def"))
        {
            filterContext.HttpContext.Response.Redirect("http://site2.com/def", true);
        }

        filterContext.Result = new ViewResult { ViewName = "NoWhiteLabel" };
        filterContext.HttpContext.Response.Clear();
    }
}

I'm not sure how to test the redirection to the other site though.
I already have tests for redirecting to "NoWhiteLabel" using the MvcContrib Test Helpers, but these aren't able to handle (as far as I can see) this situation.

How do I test the redirection to antoher site?

A: 

I would recommend you using RedirectResult instead of calling Response.Redirect:

if (youWantToRedirect) 
{
    filterContext.Result = new RedirectResult("http://site2.com/def")
}
else
{
    filterContext.Result = new ViewResult { ViewName = "NoWhiteLabel" };
}

Now if you know how to test ViewResult with MVCContrib TestHelper you will be able to test the RedirectResult the same way. The tricky part is mocking the manager to force it to satisfy the if condition.


UPDATE:

Here's how a sample test might look like:

    // arrange
    var mock = new MockRepository();
    var controller = mock.StrictMock<Controller>();
    new TestControllerBuilder().InitializeController(controller);
    var sut = new MyFilter();
    var aec = new ActionExecutingContext(
        controller.ControllerContext, 
        mock.StrictMock<ActionDescriptor>(), 
        new Dictionary<string, object>());

    // act
    sut.OnActionExecuting(aec);

    // assert
    aec.Result.ShouldBe<RedirectResult>("");
    var result = (RedirectResult)aec.Result;
    result.Url.ShouldEqual("http://site2.com/def", "");

Update (By Matt Lacey)
Here's how I actually got this working:

    // arrange
    var mock = new MockRepository();
    // Note that in the next line I create an actual instance of my real controller - couldn't get a mock to work correctly
    var controller = new HomeController(new Stubs.BlankContextInfoProvider(), new Stubs.BlankWhiteLabelManager());
    new TestControllerBuilder().InitializeController(controller);
    var sut = new UseBrandedViewModelAttribute(new Stubs.BlankWhiteLabelManager());

    var aec = new ActionExecutingContext(
        controller.ControllerContext,
        mock.StrictMock<ActionDescriptor>(),
        // being sure to specify the necessary action parameters
        new Dictionary<string, object> { { "id", "def" } });

    // act
    sut.OnActionExecuting(aec);

    // assert
    aec.Result.ShouldBe<RedirectResult>("");
    var result = (RedirectResult)aec.Result;
    result.Url.ShouldEqual("http://site2.com/def", "");
Darin Dimitrov
I get the following exception when trying to run this: "System.InvalidOperationException: Previous method 'ControllerContext.get_HttpContext();' requires a return value or an exception to throw."
Matt Lacey
@Darin - Thanks for the pointer. I eventually got this working (as shown above)
Matt Lacey
@Matt, glad to hear you made this working.
Darin Dimitrov