views:

42

answers:

3

What if a user hits my site with http://www.mysite.com/Quote/Edit rather than http://www.mysite.com/Quote/Edit/1000 In other words, they do not specify a value for {id}. If they do not, I want to display a nice "Not Found" page, since they did not give an ID. I currentl handle this by accepting a nullable int as the parameter in the Controller Action and it works fine. However, I'm curious if there a more standard MVC framework way of handling this, rather than the code I presently use (see below). Is a smoother way to handle this, or is this pretty mush the right way to do it?

    [HttpGet]
    public ActionResult Edit(int? id)
    {
        if (id == null)
            return View("QuoteNotFound");

        int quoteId = (int)id;

        var viewModel = new QuoteViewModel(this.UserId);
        viewModel.LoadQuote(quoteId);
        if (viewModel.QuoteNo > 0)
        {
            return View("Create", viewModel.Quote.Entity);
        }
        else
            return View("QuoteNotFound");
    }
+1  A: 

Your other options would be

  • Having two Edit actions ; One with int id as its parameters and another without any parameters.
  • Only having Edit(int id) as your action and letting your controller's HandleUnknownAction method to do what it's supposed to do when your entity is not found (this is a bit more complicated).

But I like your approach the best, as it's simple and correctly handles the situation.

BTW, you don't need that local variable, you can just do this for better readability :

//...
if (!id.HasValue)
    return View("QuoteNotFound");

var viewModel = new QuoteViewModel(this.UserId);
viewModel.LoadQuote(id.Value);
//...
çağdaş
The reason I was using local var quoteId is to cast the nullable int id into a regular int, because the LoadQuote() method does not accept nullable int. However, think I get your point... So, I could use viewModel.LoadQuote((int) id); Or perhaps you're saying id.value will handle that for me? I'll need to study up on this... Thanks for pointing it out.
MattSlay
@MattSlay, Nullable int's `Value` property is an `int` so your `LoadQuote` method should work OK.
çağdaş
A: 

No real issue with the way you have it but semantically it's not really an invalid quote number, its that they have navigated to an invalid route that they should not have gone to.

In this case, I would tend to redirect to /quote and if you really want to show a message to the user just show an error banner or similar (assuming you have that functionality in your master page etc).

    public ActionResult Edit(int? id) 
    { 
        if (id == null) 
        {
            // You will need some framework in you master page to check for this message.
            TempData["error"] = "Error Message to display";
            return RedirectToAction("Index"); 
        }

        ... 
    }
RM
A: 

Use route constraint

You can always define a route constraint in your routes.MapRoute() call that won't pass through any requests with undefined (or non-numeric) id:

new { id = "\d+" }

This is a regular expression that checks the value of id to be numeric.

You will probably have to create a new route that defines this, because for other controller actions you probably don't want routes to be undefined. In this case, your controller action wouldn't need a nullable parameter, because id will always be defined.

Don't be afraid of using multiple routes. With real life applications this is quite common.

Robert Koritnik