Entity Framework Code First and WebMatrix membership - entity-framework

I started a new project with EntityFramework 5.0 Code First with Automatic Migration and MVC4 with Simple Membership.
And I modified the Configuration.cs with the following:
protected override void Seed(UsersContext context)
{
if (!WebSecurity.Initialized)
{
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "UserID", "Username", true);
}
Console.WriteLine("Initialized websecurity");
CreateUser("admin");
CreateUser("radu");
CreateUser("mariana");
}
private static void CreateUser(string username)
{
if (!WebSecurity.UserExists(username))
{
WebSecurity.CreateUserAndAccount(username, "123456");
}
else
{
Membership.DeleteUser(username);
WebSecurity.CreateUserAndAccount(username, "123456");
}
}
Web.config entries look like this :
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
<roleManager enabled="true" defaultProvider="SimpleRoleProvider">
<providers>
<clear/>
<add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
</providers>
</roleManager>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear/>
<add name="SimpleMembershipProvider"
type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData"/>
</providers>
</membership>
Error message: The user name or password provided is incorrect.
Unfortunately after a successfully migration when I try to log in with one of the users inserted in db, I get invalid log in message. Why is that and how should I fix this?

I have found the problems:
protected override void Seed(Handmade.Web.Models.UsersContext context) {
if (!WebSecurity.Initialized) {
//WebSecurity.InitializeDatabaseConnection("DefaultConnection", "Users", "UserID", "Username", true);
// I used wrong init for seed method
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", true);
}
Console.WriteLine("Initialized websecurity");
CreateUser("admin");
CreateUser("radu");
CreateUser("mariana");
}
private static void CreateUser(string username) {
if (!WebSecurity.UserExists(username)) {
WebSecurity.CreateUserAndAccount(username, "123456");
} else {
Membership.DeleteUser(username);
WebSecurity.CreateUserAndAccount(username, "123456");
}
}
Also corrected init from the filter attribute I used:
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
//Database.SetInitializer<UsersContext>(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}

Related

JAX-WS client, incorrect soap request - The markup in the document following the root element must be well-formed

I have generated a web service client using wsimport command line (JAX-WS) and generated Java objects using JAXB and separate XSD files.
But when I try to request, it gives following error from server side.
SAXException, cause: The markup in the document following the root element must be well-formed.
So I checked my soap request with a sample working soap message. Then I realized that there is a different between these two messages.
1. Sample working message.
<m:getMyDetail xmlns:m="http://axis.frontend.hi.example.net">
<MyDetailRQ xmlns="http://www.example.net/schemas/1005/06/messages"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.net/1005/06/messages ../xsd/MyDetailRQ.xsd"
version="2013/12">
2. Web service client generated soap message.
<ns3:getMyDetail xmlns:ns3="http://axis.frontend.hi.example.net" xmlns="http://www.
example.net/schemas/1005/06/messages" xmlns:ns2="http://www. example.net/wsdl/1005/06"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="MyDetailRQ">
As you can see, above expected MyDetailRQ wrapper tag element is missing but it generated as xsi:type="MyDetailRQ" attribute.
I’m not sure why this happen and how to fix this through my client project configurations.
Appreciate your help and advice.
Thanks
- Relevant WSDL part
<wsdl:types>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://axis.frontend.h1.example.com">
<element name="getMyDetail" type="xsd:anyType"/>
</schema>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.com/wsdl/2005/06">
<element name="getMyDetailReturn" type="xsd:anyType"/>
</schema>
</wsdl:types>
<wsdl:message name="getMyDetailRequest">
<wsdl:part element="tns1:getMyDetail" name="part"/>
</wsdl:message>
<wsdl:message name="getMyDetailResponse">
<wsdl:part element="impl:getMyDetailReturn" name="getMyDetailReturn"/>
</wsdl:message>
<wsdl:portType name="MyService">
<wsdl:operation name="getMyDetail">
<wsdl:input message="impl:getMyDetailRequest" name="getMyDetailRequest"/>
<wsdl:output message="impl:getMyDetailResponse" name="getMyDetailResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="MyServiceSoapBinding" type="impl:MyService">
<wsdl:operation name="getMyDetail">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="getMyDetailRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getMyDetailResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="MyServiceService">
<wsdl:port binding="impl:MyServiceSoapBinding" name="MyService">
<wsdlsoap:address location="http://interface.example.com/xmls/ws/MyService"/>
</wsdl:port>
</wsdl:service>
- Relevant XSD part
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="http://www.example.net/schemas/1005/06/messages" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.net/schemas/1005/06/messages" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:include schemaLocation="MyCommonTypes.xsd"/>
<xs:element name="MyDetailRQ">
- Relevant Java Object
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "MyDetailRQ", propOrder = {
"myCode"
})
#XmlRootElement(name = "MyDetailRQ")
public class MyDetailRQ
extends MainRequest
{
}
- web service client - service interface (Updated on 17-Oct-2014)
#WebService(name = "MyService", targetNamespace = "http://www.example.net/wsdl/1005/06")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
#XmlSeeAlso({
com.myp.hi.frontend.axis.ObjectFactory.class,
com.myp.ObjectFactory.class
})
public interface MyService {
/**
*
* #param part
* #return
* returns java.lang.Object
*/
#WebMethod
#WebResult(name = "getMyDetailReturn", targetNamespace = "http://www.example.net/wsdl/1005/06", partName = "getMyDetailReturn")
public Object getMyDetail(
#WebParam(name = "getMyDetail", targetNamespace = "http://axis.frontend.hi.example.net", partName = "part")
Object part);
}
- ObjectFactory class (Updated on 17-Oct-2014)
#XmlRegistry
public class ObjectFactory {
private final static QName _GetMyDetail_QNAME = new QName("http://axis.frontend.hi.example.net", "getMyDetail");
public ObjectFactory() {
}
#XmlElementDecl(namespace = "http://axis.frontend.hi.example.net", name = "getMyDetail")
public JAXBElement<Object> createGetMyDetail(Object value) {
return new JAXBElement<Object>(_GetMyDetail_QNAME, Object.class, null, value);
}
}
-MyServiceService class (Updated on 17-Oct-2014)
#WebServiceClient(name = "MyServiceService", targetNamespace = "http://www.example.net/wsdl/1005/06", wsdlLocation = "http://interface.example.com/xmls/ws/MyService?wsdl")
#GZIP
public class MyServiceService
extends Service
{
private final static URL MYSERVICESERVICE_WSDL_LOCATION;
private final static WebServiceException MYSERVICESERVICE_EXCEPTION;
private final static QName MYSERVICESERVICE_QNAME = new QName("http://www.example.net/wsdl/1005/06", "MyServiceService");
static {
URL url = null;
WebServiceException e = null;
try {
url = new URL("http://interface.example.com/xmls/ws/MyService?wsdl");
} catch (MalformedURLException ex) {
e = new WebServiceException(ex);
}
MYSERVICESERVICE_WSDL_LOCATION = url;
MYSERVICESERVICE_EXCEPTION = e;
}
#WebEndpoint(name = "MyService")
public MyService getMyService() {
MyService port = super.getPort(new QName("http://www.example.net/wsdl/1005/06", "MyService"), MyService.class);
return port;
}
private static URL __getWsdlLocation() {
if (MYSERVICESERVICE_EXCEPTION!= null) {
throw MYSERVICESERVICE_EXCEPTION;
}
return MYSERVICESERVICE_WSDL_LOCATION;
}
}
- My Test class (Updated on 17-Oct-2014)
MyService myService = new MyServiceService().getMyService();
MyDetailRQ myDetailRQ = new MyDetailRQ();
myDetailRQ.setCredentials(credentials);
myDetailRQ.setLanguage("ENG");
myDetailRQ.setMyCode("52319");
MyDetailRS myDetailRS = (MyDetailRS) myService.getMyDetail(myService);
I have found a solution, but not sure whether perfect one.
What I have done is; pass a XML String to service and get response as a String from service.
Then manually do marshalling and un- marshalling.
See the example below.
MyService myService = new MyServiceService().getMyService();
MyDetailRQ myDetailRQ = new MyDetailRQ();
myDetailRQ.setCredentials(credentials);
myDetailRQ.setLanguage("ENG");
myDetailRQ.setMyCode("52319");
String requestStr = getStringFromJaxb(myDetailRQ.class, myDetailRQ);
String responseStr = (String) myService.getMyDetail(requestStr);
MyDetailRS myDetailRS = (MyDetailRS) getJaxbFromString(MyDetailRS.class, responseStr);
private static Object getJaxbFromString(Class<?> clazz, String xmlString) {
StringReader input = null;
Object o = null;
try {
input = new StringReader(xmlString);
JAXBContext context = JAXBContext.newInstance(clazz);
Unmarshaller um = context.createUnmarshaller();
o = um.unmarshal(input);
if (o instanceof JAXBElement)
o = ((JAXBElement<?>) o).getValue();
} catch (JAXBException e) {
e.printStackTrace();
} finally {
if (input != null)
input.close();
}
return o;
}
/**
* Helper method to get xml string from JAXB Object.
* #param clazz
* #param o
* #return
*/
private static String getStringFromJaxb(Class<?> clazz, Object o) {
String theXML = "";
try {
StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance(clazz);
Marshaller m = context.createMarshaller();
m.setProperty("com.sun.xml.bind.xmlDeclaration", Boolean.FALSE);
m.marshal(o, writer);
// output string to console
theXML = writer.toString();
} catch (Exception e) {
e.printStackTrace();
}
return theXML;
}

Handle spring-data-rest application events within the transaction

I need to publish notification events to external systems over JMS, when data is updated. Id like this to be done within the same transaction as the objects are committed to the database to ensure integrity.
The ApplicationLifecycle events that spring-data-rest emits seemed like the logical place to implement this logic.
#org.springframework.transaction.annotation.Transactional
public class TestEventListener extends AbstractRepositoryEventListener<Object> {
private static final Logger LOG = LoggerFactory.getLogger(TestEventListener.class);
#Override
protected void onBeforeCreate(Object entity) {
LOG.info("XXX before create");
}
#Override
protected void onBeforeSave(Object entity) {
LOG.info("XXX before save");
}
#Override
protected void onAfterCreate(Object entity) {
LOG.info("XXX after create");
}
#Override
protected void onAfterSave(Object entity) {
LOG.info("XXX after save");
}
}
However, these events happen before and after the tx starts and commits.
08 15:32:37.119 [http-nio-9000-exec-1] INFO n.c.v.vcidb.TestEventListener - XXX before create
08 15:32:37.135 [http-nio-9000-exec-1] TRACE o.s.t.i.TransactionInterceptor - Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
08 15:32:37.432 [http-nio-9000-exec-1] TRACE o.s.t.i.TransactionInterceptor - Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
08 15:32:37.479 [http-nio-9000-exec-1] INFO n.c.v.vcidb.TestEventListener - XXX after create
What extension point does spring-data-rest have for adding behaviour that will execute within the spring managed transaction?
I use aop (pointcut and tx advice) to solve this problem:
#Configuration
#ImportResource("classpath:/aop-config.xml")
public class AopConfig { ...
and aop-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"
default-autowire="byName">
<aop:config>
<aop:pointcut id="restRepositoryTx"
expression="execution(* org.springframework.data.rest.webmvc.RepositoryEntityController.*(..))" />
<aop:advisor id="managerTx" advice-ref="txAdvice" pointcut-ref="restRepositoryTx" order="20" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="postCollectionResource*" propagation="REQUIRES_NEW" rollback-for="Exception" />
<tx:method name="putItemResource*" propagation="REQUIRES_NEW" rollback-for="Exception" />
<tx:method name="patchItemResource*" propagation="REQUIRES_NEW" rollback-for="Exception" />
<tx:method name="deleteItemResource*" propagation="REQUIRES_NEW" rollback-for="Exception" />
<!-- <tx:method name="*" rollback-for="Exception" /> -->
</tx:attributes>
</tx:advice>
</beans>
This is the same as having controller methods annotated with #Transactional.
The solution described by phlebas work. And I also think "Run event handler within a same transaction" should be a feature which should be provided by Spring Data Rest. There are many common use cases to need to split logic to sepreate eventHandler. just like "triggers in database". The version show below is same as phlebas solution.
#Aspect
#Component
public class SpringDataRestTransactionAspect {
private TransactionTemplate transactionTemplate;
public SpringDataRestTransactionAspect(PlatformTransactionManager transactionManager) {
this.transactionTemplate = new TransactionTemplate(transactionManager);
this.transactionTemplate.setName("around-data-rest-transaction");
}
#Pointcut("execution(* org.springframework.data.rest.webmvc.*Controller.*(..))")
public void aroundDataRestCall(){}
#Around("aroundDataRestCall()")
public Object aroundDataRestCall(ProceedingJoinPoint joinPoint) throws Throwable {
return transactionTemplate.execute(transactionStatus -> {
try {
return joinPoint.proceed();
} catch (Throwable e) {
transactionStatus.setRollbackOnly();
if(e instanceof RuntimeException) {
throw (RuntimeException)e;
} else {
throw new RuntimeException(e);
}
}
});
}
}
I have not worked on spring-data-rest, but with spring, this can be handled the following way.
1) Define custom TransactionSynchronizationAdapter, and register the bean in TransactionSynchronizationManager.
Usually, I have a method registerSynchronizaiton with a #Before pointcut for this.
#SuppressWarnings("rawtypes") #Before("#annotation(org.springframework.transaction.annotation.Transactional)")
public void registerSynchronization() {
// TransactionStatus transStatus = TransactionAspectSupport.currentTransactionStatus();
TransactionSynchronizationManager.registerSynchronization(this);
final String transId = UUID.randomUUID().toString();
TransactionSynchronizationManager.setCurrentTransactionName(transId);
transactionIds.get().push(transId);
if (TransactionSynchronizationManager.isActualTransactionActive() && TransactionSynchronizationManager
.isSynchronizationActive() && !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
if (!TransactionSynchronizationManager.hasResource(KEY)) {
final List<NotificationPayload> notifications = new ArrayList<NotificationPayload>();
TransactionSynchronizationManager.bindResource(KEY, notifications);
}
}
}
2) And, implement Override method as follows
#Override public void afterCompletion(final int status) {
CurrentContext context = null;
try {
context = ExecutionContext.get().getContext();
} catch (final ContextNotFoundException ex) {
logger.debug("Current Context is not available");
return;
}
if (status == STATUS_COMMITTED) {
transactionIds.get().removeAllElements();
publishedEventStorage.sendAllStoredNotifications();
// customize here for commit actions
} else if ((status == STATUS_ROLLED_BACK) || (status == STATUS_UNKNOWN)) {
// you can write your code for rollback actions
}
}

MembershipCreateUserException: The username supplied is invalid

Im trying to use Facebook registration on my MVC 4 application, but I keep getting this cryptic error System.Web.Security.MembershipCreateUserException: The username supplied is invalid.
when OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName); is run
provider = "facebook"
providerUserId = "token-key"
model.Username = "bobsaget"
Everything is basically set back to a default MVC 4 application at this point. Here is the code I am running.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl)
{
string provider = null;
string providerUserId = null;
if (User.Identity.IsAuthenticated || !OAuthWebSecurity.TryDeserializeProviderUserId(model.ExternalLoginData, out provider, out providerUserId))
{
return RedirectToAction("Manage");
}
if (ModelState.IsValid)
{
// Insert a new user into the database
using (UsersContext db = new UsersContext())
{
UserProfile user = db.UserProfiles.FirstOrDefault(u => u.UserName.ToLower() == model.UserName.ToLower());
// Check if user already exists
if (user == null)
{
// Insert name into the profile table
db.UserProfiles.Add(new UserProfile { UserName = model.UserName});
db.SaveChanges();
db.SaveChanges();
OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("UserName", "User name already exists. Please enter a different user name.");
}
}
}
ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(provider).DisplayName;
ViewBag.ReturnUrl = returnUrl;
return View(model);
}
The MembershipAttribute have always been default, except its getting information from web.config.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<UsersContext>(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
var i = Config.ConnectionStringName;
WebSecurity.InitializeDatabaseConnection(
Config.ConnectionStringName,
Config.UserTableName,
Config.UsersPrimaryKeyColumnName,
Config.UsersUserNameColumnName,
autoCreateTables: true);
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}
}
I have browsed the web, Stackoverflow and even tried to decompile the dll without getting to the root of the problem.
Thanks in advance for your input.
I am not sure but i think you need to make to sure that an entry of user is properly inserted into userprofile table and also the other tables which are required for membership.

JPA #OneToMany not persisting/cascading

I have the following code in UserController in my Session Scoped Bean
public void addItemToBundle(ItemEntity item){
//System.out.println(item.getTitle());
try {
em.getTransaction().begin();
UserEntity user = em.find(UserEntity.class, this.username);
BundleEntity bundle = new BundleEntity();
BundleEntityPK compositePk = new BundleEntityPK();
compositePk.setCheckedOutDate(new Date());
compositePk.setItemId(item.getItemId());
compositePk.setUsername(user.getUsername());
bundle.setId(compositePk);
Set<BundleEntity> bundles = new HashSet<BundleEntity>();
bundles.add(bundle);
user.setBundleEntities(bundles);
em.persist(user);
em.flush();
em.getTransaction().commit();
} finally {
}
}
public String addToBundle(){
try {
addItemToBundle(item);
} catch (NullPointerException e) {
e.getMessage();
}
return null;
}
This code uses private ItemEntity item; which gets passed in by the following JSF markup:
<p:commandLink action="#{itemController.item}">
<f:setPropertyActionListener target="#{itemController.selectedItem}" value="#{movie}" />
</p:commandLink>
(I'm using PrimeFaces in this example) The problem is that the addItemToBundle is not calling any SQL code in the console (I have FINE enabled) and the bundle never gets created or added to the user. I also tried em.persist(user) and em.flush() and setting cascadeType in my UserEntity with no luck.
#OneToMany(mappedBy="userEntity",cascade=CascadeType.PERSIST)
private Set<BundleEntity> bundleEntities;
Thanks!
You know that this:
try {
addItemToBundle(item);
} catch (NullPointerException e) {
e.getMessage();
}
is very bad practice, right? Maybe, that's the problem here, you run into a NPE and never notice it.
You should at least log the exception to know what's going on there (just for demo purposes, I've used stdout, please replace with your favorite logging framework):
try {
addItemToBundle(item);
} catch (NullPointerException e) {
System.err.println(e.getMessage()); //use logger here
}

Not seeing roles on Principal in ASP.NET MVC 2 Application

I am writing an ASP.NET MVC 2 application and don't want to use ASP.NET Membership. I do want to use the Authorize attribute on the Controllers. What I have done so far is ...
Web.config
<roleManager enabled="true" />
<authentication mode="Forms">
<forms loginUrl="~/Authentication/Login" timeout="2880"/>
</authentication>
<authorization>
<allow users="*" /> /* This is for testing */
</authorization>
In my Global.asax
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
var cookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie == null) return;
var decryptedCookie = FormsAuthentication.Decrypt(cookie.Value);
var roles = decryptedCookie.UserData.Split('|');
var tcmIdentity = new TcmIdentity(decryptedCookie.Name);
var tcmPrincipal = new GenericPrincipal(tcmIdentity, roles);
Context.User = tcmPrincipal;
}
I am using a custom IIdentity so that I can add some custom properties in the future. To test this in my Controller action I did this ...
var testPrincipal = User;
I can see the custom Identity with all of the user information but there are no roles on principal object. Any help with what i have missed would be great. Thanks.
I believe you need a role provider. Much like how a Membership provider handles the membership of users, create, delete, validate, edit, in order to use roles, you need to use a RoleProvider (ASP.NET Implementing a Role Provider).
Which also requires enabling roles in the web.config, for example:
<roleManager enabled="enabled" defaultProvider="AspNetSqlRoleProvider">
<providers>
<clear/>
<add name="AspNetSqlRoleProvider"
type="System.Web.Security.SqlRoleProvider"
connectionStringName="ApplicationServices"
applicationName="/" />
<add name="AspNetWindowsTokenRoleProvider"
type="System.Web.Security.WindowsTokenRoleProvider"
applicationName="/" />
</providers>
</roleManager>
This might be useful:
SO asp-net-mvc-roles-without-database-and-without-role-provider
As Might be:
ASP.NET 2.0, Custom Role assignment without a 'Role Provider'
UPDATE:
In the end I got this working by changing
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
var cookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie == null) return;
var decryptedCookie = FormsAuthentication.Decrypt(cookie.Value);
var roles = decryptedCookie.UserData.Split('|');
var tcmIdentity = new TcmIdentity(decryptedCookie.Name);
var tcmPrincipal = new GenericPrincipal(tcmIdentity, roles);
Context.User = tcmPrincipal;
}
to
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
var cookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie == null) return;
var decryptedCookie = FormsAuthentication.Decrypt(cookie.Value);
var roles = decryptedCookie.UserData.Split('|');
var tcmIdentity = new TcmIdentity(decryptedCookie.Name);
var tcmPrincipal = new GenericPrincipal(tcmIdentity, roles);
Thread.CurrentPrincipal = Context.User = tcmPrincipal;
}