The very simplest solution would be to change the URLs from using IDs to random GUIDs. You would almost eliminate the chance of someone guessing another valid value. Of course, this is not secure by definition (mostly because someone could get the other URL from history or another source), but in some scenarios this is enough.
A better solution is to create a new attribute based on
IActionFilter interface that implements
OnActionExecuting method and checks the ID by using
this.RouteData.Values["id"]. You will then apply this attribute to your controller methods.
In our current system we implemented row level security in controller methods by just adding the code that verifies the user permissions as the first line in each method. The checking code is the same as with the attribute and it requires the same amount of code to add. This approach has one additional benefit - it is easier to implement scenarios like where a coach would be able to see the details of other teams but not modify them (we have one action and view for both reading and updating depending on permissions).
You would also use the last approach if you need to go to the database to check the permissions and you are using IoC frameworks such as Ninject with constructor based injection - since you will not have access to those values in the attribute.