2

Short question: Why does safari cause errors on my MVC3 web application - Request.Form is blank for some reason?

Detailed question: My MVC3 website sends me an email every time there is an uncaught exception. I use these to find and fix bugs quickly, the email contains the exception, stack trace, user's IP address, user-agent string, and any form values that may have been posted.

Recently I have been noticing errors that have proven hard to track down, I thought I would post my findings here in the hope they help others.

The original symptom was these errors: System.Web.Mvc.HttpAntiForgeryException: A required anti-forgery token was not supplied or was invalid.

My form's action was throwing the error, and I couldn't figure out how anyone was getting the page into a state where it didn't have the __RequestVerificationToken hidden field, or the other form fields.

So I spent ages looking into cookies, and how the token works, and eventually just removed the [ValidateAntiForgeryToken] attribute on my ActionResult to see how it went - I still got errors though.

Then I noticed that the useragent strings showed it was only Safari 5.1.7 causing the issue.

tereško
  • 58,060
  • 25
  • 98
  • 150
Matt Kemp
  • 2,742
  • 2
  • 28
  • 38

2 Answers2

4

For those of you who, like me, are experiencing this issue even with the [HttpPost] attribute, I have found a solution.

http://forums.iis.net/t/1182376.aspx/1

That thread on IIS describes that Negotiate (i.e. Kerberos) authentication is handled improperly in Safari. You have to disable Negotiate as a provider.

In IIS (I am using IIS 7.5), click your site, then Authentication(double click) → Windows Authentication(single click) → Providers(on the right side) → Remove Negotiate and leave NTLM

This fixed all my problems with Safari.

Jeff Johnson
  • 1,095
  • 10
  • 15
2

Short Answer: Don't forget to add a [HttpPost] attribute!!!

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult PageSubmit() {

Longer Answer: Safari has a feature where they show the "top sites" you've visited on a wall-style screen. On my site although I had multiple pages, they all submit to the same form action. This made the form action "very popular", and it appears on the top sites.

People can then click the site, which was doing a direct GET to my processing page, with no form variables, and causing the errors.

I added the [HttpPost] attribute and now it 404's if you click it.

Here is some extra info on the preview feature: Safari Top Sites Preview it appears you can check for a server variable:

Request.ServerVariables["HTTP_X_PURPOSE"] == "preview"

and there is a javascript check you can do too:

window.navigator&&window.navigator.loadPurpose==="preview"

I hope this saves someone some time.

Community
  • 1
  • 1
Matt Kemp
  • 2,742
  • 2
  • 28
  • 38
  • This isn't working for me at all. I've ensured that I am using HttpPost on all my MVC Controller methods, but I still get issues. It works fine if I use PHP, alas, I don't have that option. It's gotta be an IIS thing :(. – Jeff Johnson Apr 03 '13 at 20:20
  • Hi Jeff, are you saying that even when you add the [HttpPost] attribute, you can still call the method directly with a GET? If you can, then I'd be looking at your routing maybe? Definitely put a breakpoint in the method, and make sure it's definitely hitting that one and not something else you didn't expect. HttpPost has been around since MVC2, you aren't using MVC1 are you? – Matt Kemp Apr 07 '13 at 08:19
  • I am using MVC 4. I am also using the Intranet template. Whenever I post form data via jQuery's `ajax` method, it works 100% in IE7+, Chrome, and FF2+. No problems. No issues. But when I send a form (via `post`) using Safari (v5.7), it's a blank form every time. I think it has to do with IIS's Windows Authentication...but I don't have the expertise to track it down :( – Jeff Johnson Apr 09 '13 at 01:41