When I\'m putting following code:
@using (Html.BeginForm(\"LogOff\", \"Account\", FormMethod.Post, new { id = \"logoutForm\" }))
{
@Html.AntiForgery
It's telling you that it won't work because despite being logged in, Membership.GetUser().UserName
is not providing a name that can be used for hashing.
So your real problem is, "How come my logged in user doesn't have a username?"
There can be some cases when logged in user doesn't have Identity.Name set (in my case I have to integrate my app with some crazy log-in system). Then there are two ways around:
1) unsecure - all users will be treated the same way by antiforgery system regardless of their auth status
// System.Web.WebPages.dll
using System.Web.Helpers;
// not a production solution
public class MvcApplication : HttpApplication {
protected void Application_Start() {
AntiForgeryConfig.SuppressIdentityHeuristicChecks = true;
}
}
2) secure - provide your own (custom) way how you distinguish your users
using System;
using System.Globalization;
using System.Web;
using System.Web.Helpers;
public class ContoscoAntiForgeryAdditionalDataProvider : IAntiForgeryAdditionalDataProvider {
public string GetAdditionalData(HttpContextBase context) {
if (context == null) {
throw new ArgumentNullException("context");
}
var contoscoContext = new ContoscoHttpContext(context);
int userID = contoscoContext.GetUserID().GetValueOrDefault();
return Convert.ToString(userID, CultureInfo.InvariantCulture);
}
public bool ValidateAdditionalData(HttpContextBase context, string additionalData) {
string data = GetAdditionalData(context);
return string.Compare(data, additionalData, StringComparison.Ordinal) == 0;
}
}
public class MvcApplication : HttpApplication {
protected void Application_Start() {
AntiForgeryConfig.AdditionalDataProvider =
new ContoscoAntiForgeryAdditionalDataProvider();
}
}
where ContoscoHttpContext
is class that returns UserID (or any unique user token) based on current context (i.e. HttpContextBase
):
public class ContoscoHttpContext {
private HttpContextBase _context;
public ContoscoHttpContext(HttpContextBase context) {
_context = context;
}
public int? GetUserID() {
// TODO: provide your own implementation how to get user id
// based on HttpContextBase stored in _context
// in my case it was something like
// return ((ContoscoPrincipal)_context.User).UserID;
}
}