Using always calls Dispose, even if an exception is raised. This is just easier than using "try..finally" all over the place.
The only time you really need to call Dispose (whether it's directly called or indirectly called) is when there's unmanged resources involved.
The key unmanaged resource is normally ADO.NET connections. However, in ASP.NET you typically have a pool of connections managed for you automatically, so there's less need to call Dispose for ASP.NET.
Many people consider it "good practice" to call Dispose anytime a class implements it. It's mostly C++ programmers who migrate to C# that have this outlook, but it's probably the "most correct" outlook, anyway.