views:

38

answers:

1

I have an ASP.NET MVC2 application that uses a parent controller to setup specific variables that are used around the app. I also implement validation to make sure that an ID in the URI exists in the database. If it does not, I redirect and stop the execution of the script.

My parent controller looks something like this:


// Inside class declaration

// Set instance of account object to blank account
protected Account account = new Account();

protected override void Initialize(System.Web.Routing.RequestContext requestContext) {
    // Call parent init method
    base.init(requestContext);

    // Check to make sure account id exists
    if (accountRepos.DoesExistById(requestContext.RouteData.Values["aid"].ToString()) {
        account = accountRepos.GetById(requestContext.RouteData.Values["aid"].ToString());
    } else {
        requestContext.HttpContext.Response.Redirect("url");
        requestContext.HttpContext.Response.End();
    }
}

At first this worked, but now when an incorrect id is entered, it doesn't redirect and throws a NullPointerException when the Account class is used. I originally just declared the account variable rather instantiating it, but that also proved to throw exceptions and didn't redirect.

The reason I try to end the execution of the script is because I want to make sure that it stops even if the redirect doesn't work. Kinda like calling exit() after header() in PHP :p . If I am doing this wrong, I would appreciate any pointers.

I'm just wondering how I can fix this.

Any help is greatly appreciated =D

+1  A: 

I don't think that's the proper way to do what you want. Instead you should use route constraints on your routes to make sure the id exists, and fall back from there in a "catch all" route.

Something like this:

Routes.MapRoute("Name", "Url", new { ... }, new {
    Id = new IdConstraint() // <- the constraint returns true/false which tells the route if it should proceed to the action
});

The constraint would be something like this:

public class IdConstraint : IRouteConstraint {
    public bool Match(
        HttpContextBase Context,
        Route Route,
        string Parameter,
        RouteValueDictionary Dictionary,
        RouteDirection Direction) {
        try {
            int Param = Convert.ToInt32(Dictionary[Parameter]);

            using (DataContext dc = new DataContext() {
                ObjectTrackingEnabled = false
            }) {
                return (dc.Table.Any(
                    t =>
                        (t.Id == Param)));
            };
        } catch (Exception) {
            return (false);
        };
    }
}

This is what I use with my routes to make sure that I'm getting an Id that really exists. If it doesn't exist, the constraint returns a false, and the route does not execute and the request continues down the route chain. At the very bottom of your routes you should have a generic catch all route that sends your user to a page that tells them what they want doesn't exist and to do X or X (something along those lines, I'm just coming up with scenarios).

Alex
+1 interesting solution; I was about to recommend a custom Authorization filter but I like the IRouteContraint better
Tahbaza
Great! I'll try this out.
Swamp56
I read up on the IRouteConstraint interface and implemented my own constraint class and it worked!
Swamp56
Glad I could be of help. :) As a side note, I've been using MVC since MVC 1.0 Preview 2, way back in time, and I've used the Initialize override once throughout that whole time. I needed it because I was doing some funky cross-database linking... So, I guess I want to say that going down that road may seem like the right thing to do, but it not always is (this is more of a reference for future developers starting with MVC).
Alex