When a browser is told to refresh, it re-sends the last request that it sent. If the last request sent was a form submission, then the form will be re-submitted. There's no way around that because that's simply how the model works.
To prevent undesired effects, you have to either:
- use post-redirect-get, so that the last request (the one that gets re-sent) will be one which reads the results of your form submission rather than the form submission itself
or
- put an identifier in the form so that the re-submission can be ignored by the server (although the user will still see the "do you want to re-submit?" confirmation)
I am not aware of any other options and, given the way that "refresh" works, I don't really see how there could be any others. Of those two choices, post-redirect-get gives the cleanest user experience and is the most theoretically "pure" use of HTTP verbs, so it is generally preferred and, IMO, the correct solution.