I\'m trying to get better at handling exceptions but I feel like my code gets very ugly, unreadable and cluttered when I try my best to catch them. I would love to see how other
Rule one of exception handling - do not catch exceptions you don't know how to handle.
Catching exceptions just in order to provide nice error messages is questionable. The exception type and message already contain enough information for a developer - the messages you have provided do not add any value.
the DataContractJsonSerializer show no exceptions on the intellisense. Does this mean the constructor will never fail? Can I be sure?
No, you can't be sure. C# and .NET in general are not like Java where you have to declare what exceptions may be thrown.
A third option would be to ignore all exceptions apart from the ones that would allow me to take an action like retrying the connection.
That indeed is the best option.
You can also add a general exception handler at the top of the application that will capture all unhandled exceptions and log them.
First, read my article on exception handling:
http://ericlippert.com/2008/09/10/vexing-exceptions/
My advice is: you must handle the "vexing exceptions" and "exogenous exceptions" that can be thrown by your code. Vexing exceptions are "non exceptional" exceptions and so you have to handle them. Exogenous exceptions can happen due to considerations beyond your control, and so you have to handle them.
You must not handle the fatal and boneheaded exceptions. The boneheaded exceptions you don't need to handle because you are never going to do anything that causes them to be thrown. If they are thrown then you have a bug and the solution is fix the bug. Don't handle the exception; that's hiding the bug. And you can't meaningfully handle fatal exceptions because they're fatal. The process is about to go down. You might consider logging the fatal exception, but keep in mind that the logging subsystem might be the thing that triggered the fatal exception in the first place.
In short: handle only those exceptions that can possibly happen that you know how to handle. If you don't know how to handle it, leave it to your caller; the caller might know better than you do.
In your particular case: don't handle any exceptions in this method. Let the caller deal with the exceptions. If the caller passes you an url that cannot be resolved, crash them. If the bad url is a bug then the caller has a bug to fix and you are doing them a favour by bringing it to their attention. If the bad url is not a bug -- say, because the user's internet connection is messed up -- then the caller needs to find out why the fetch failed by interrogating the real exception. The caller might know how to recover, so help them.