Nelle applicazioni web che seguo molta logica applicativia, di business, si trova all'interno di stored procedure.
Questa soluzione permette di gestire in modo molto più performante tutta una serie di validazioni che devono essere fatte a database e che diversamente, volendole eseguire lato app nello strato di business logic, comporterebbero dei caricamenti aggiuntivi delle nostre entities(classi di dominio).
Sicuramente molti di voi non saranno d'accordo con questo tipo di approccio, ma spesso è necessario scendere a compromessi che allontanano dalla "teoria" a favore delle prestazioni(nel mio caso).
Sempre a proposito di validazioni gestite via stored procedure, cio' che faccio è generare delle RAISEERROR con un messaggio che sarà poi visualizzato dall'alert generato dal framework di Ajax.
In realta sul messaggio applico un prefisso ed una formattazione che permette anche il passaggio di parametri nella stringa stessa, in modo che lato ASP.NET/Ajax possa gestire la visualizzazione multilingua del messaggio stesso.
Questo post Handling exceptions during a partial update spiega come gestire gli errori quando usiamo Ajax e l'updating parziale tramite Update Panel, impostando AllowCustomErrorRedirect=False sullo Script Manager.
La soluzione che ho adottato io nelle mie web app è quella di gestire i custom errors di ASP.NET, con una pagina dedicata, per tutti gli eventuali errori generati non durante postback parziali.
Nel caso di postback parziali utilizzo AsyncPostBackErrorMessage per visualizzare l'alert di errore.